Commit 883724b9 authored by Robert Schmidt's avatar Robert Schmidt

Merge branch 'integration_2024_w12' into 'develop'

Integration `2024.w12`

See merge request oai/openairinterface5g!2637

* !2640 Fix UPF crash at startup after latest Docker and Ubuntu updates
* !2579 Add telnetsrv_rrc for triggering RRCRelease
* !2613 NR UE fix for procedure after T300 expiry
* !2625 Changes to support 32 UEs in the gNB.
* !2632 NR fix for initialization of gold sequences for DMRS
* !2588 fix(doc): add ptp4l service configuration file in 7.2 documentation
* !2630 Move BladeRF config to right subfolder
* !2626 On RFsimulator end, close open connections
* !2628 NR UE fix double sync
* !2634 feat(phy-test): disable CQI and RSRP errors when running in phy-test mode → review to be addressed
* !2621 CI: set memory limit for docker build cache
* !2604 NR UE BSR improvements → waiting for final changes
* !2638 NR UE data scrambling fixes
* !2602 [E2 agent] KPM & RC SMs improvements
parents 9379bf85 4c07dca3
......@@ -517,9 +517,13 @@ class Containerize():
# Remove all intermediate build images and clean up
cmd.run(f"{self.cli} image rm ran-build:{imageTag} ran-build-asan:{imageTag}")
cmd.run(f"{self.cli} volume prune --force")
# Remove any cached artifacts: we don't use the cache for now, prevent
# out of diskspace problem
cmd.run(f"{self.cli} buildx prune --filter=until=6h --force")
# Remove some cached artifacts to prevent out of diskspace problem
logging.debug(cmd.run("df -h").stdout)
logging.debug(cmd.run("docker system df").stdout)
cmd.run(f"{self.cli} buildx prune --filter until=1h --force")
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}'
......
......@@ -1011,6 +1011,8 @@ bool nr_timer_tick(NR_timer_t *timer)
bool expired = false;
if (timer->active) {
timer->counter += timer->step;
if (timer->target == UINT_MAX) // infinite target, never expires
return false;
expired = nr_timer_expired(*timer);
if (expired)
timer->active = false;
......@@ -1020,9 +1022,16 @@ bool nr_timer_tick(NR_timer_t *timer)
bool nr_timer_expired(NR_timer_t timer)
{
if (timer.target == UINT_MAX) // infinite target, never expires
return false;
return (timer.counter >= timer.target);
}
uint32_t nr_timer_elapsed_time(NR_timer_t timer)
{
return timer.counter;
}
void nr_timer_setup(NR_timer_t *timer, const uint32_t target, const uint32_t step)
{
timer->target = target;
......
......@@ -158,6 +158,13 @@ bool nr_timer_expired(NR_timer_t timer);
* @return Indication if the timer is active or not
*/
bool is_nr_timer_active(NR_timer_t timer);
/**
* @brief To return how much time has passed since start of timer
* @param timer Timer to be checked
* @return Time passed since start of timer
*/
uint32_t nr_timer_elapsed_time(NR_timer_t timer);
extern const nr_bandentry_t nr_bandtable[];
......
......@@ -64,8 +64,13 @@ add_library(telnetsrv_bearer MODULE telnetsrv_bearer.c)
target_link_libraries(telnetsrv_bearer PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs)
add_dependencies(telnetsrv telnetsrv_bearer)
message(STATUS "Add RRC specific telnet functions in libtelnetsrv_rrc.so")
add_library(telnetsrv_rrc MODULE telnetsrv_rrc.c)
target_link_libraries(telnetsrv_rrc PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs)
add_dependencies(telnetsrv telnetsrv_rrc)
# all libraries should be written to root build dir
set_target_properties(telnetsrv telnetsrv_enb telnetsrv_5Gue telnetsrv_ci telnetsrv_bearer
set_target_properties(telnetsrv telnetsrv_enb telnetsrv_5Gue telnetsrv_ci telnetsrv_bearer telnetsrv_rrc
PROPERTIES LIBRARY_OUTPUT_DIRECTORY ../../..
)
/*
* 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 <sys/types.h>
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include "openair2/RRC/NR/rrc_gNB_UE_context.h"
#define TELNETSERVERCODE
#include "telnetsrv.h"
#define ERROR_MSG_RET(mSG, aRGS...) do { prnt(mSG, ##aRGS); return 1; } while (0)
/**
* Module brief:
* This module is used to add RRCRelease commands to the telnet server in the
* absence of full support for E2SM RAN Control (RC).
* This provides similar functionality to the ORAN.WG3.E2SM-RC-R003-v05.00
* 8.4.5.4 RRC Connection Release Control which is initiated by the RIC.
*
* Implementation notes:
* We refer to the method call rrc_gNB_generate_RRCRelease at rrc_gNB_NGAP.c
* during rrc_gNB_process_NGAP_UE_CONTEXT_RELEASE_COMMAND message generation.
*
* Building the telnetsrv and module:
* ./build_oai --build-lib telnetsrv
*
* Loading the module:
* sudo ./nr-softmodem --sa -E --rfsim --log_config.global_log_options level,nocolor,time -O ~/gnb.sa.band78.106prb.rfsim.conf --telnetsrv --telnetsrv.shrmod rrc
*/
static int get_single_ue_id(void)
{
rrc_gNB_ue_context_t *ue_context_p = NULL;
RB_FOREACH(ue_context_p, rrc_nr_ue_tree_s, &(RC.nrrrc[0]->rrc_ue_head)) {
return ue_context_p->ue_context.rrc_ue_id;
}
return -1;
}
/**
* @brief Trigger RRC Release for a specific UE
* @param buf: RRC UE ID
* @param debug: Debug flag
* @param prnt: Print function
* @return 0 on success, -1 on failure
*/
int rrc_gNB_trigger_release(char *buf, int debug, telnet_printfunc_t prnt) {
ue_id_t ue_id = -1;
protocol_ctxt_t ctxt;
if (!buf) {
ue_id = get_single_ue_id();
if (ue_id < 1) {
prnt("No UE found!\n");
ERROR_MSG_RET("No UE found!\n");
}
} else {
ue_id = strtol(buf, NULL, 10);
if (ue_id < 1 || ue_id >= 0xfffffe) {
prnt("UE ID needs to be [1,0xfffffe]\n");
ERROR_MSG_RET("UE ID needs to be [1,0xfffffe]\n");
}
}
/* get RRC and UE */
gNB_RRC_INST *rrc = RC.nrrrc[0];
rrc_gNB_ue_context_t *ue_context_p = rrc_gNB_get_ue_context(rrc, ue_id);
if (!ue_context_p) {
prnt("Could not find UE context associated with UE ID %lu\n", ue_id);
LOG_E(RRC, "Could not find UE context associated with UE ID %lu\n", ue_id);
return -1;
}
gNB_RRC_UE_t *UE = &ue_context_p->ue_context;
PROTOCOL_CTXT_SET_BY_INSTANCE(&ctxt, 0, GNB_FLAG_YES, UE->rrc_ue_id, 0, 0);
ctxt.eNB_index = 0;
rrc_gNB_generate_RRCRelease(&ctxt, ue_context_p);
prnt("RRC Release triggered for UE %u\n", ue_id);
return 0;
}
/**
* @brief Trigger RRC Release for all UEs
*/
int rrc_gNB_trigger_release_all(char *buf, int debug, telnet_printfunc_t prnt) {
rrc_gNB_ue_context_t *ue_context_p = NULL;
protocol_ctxt_t ctxt; /* Not sure what exactly is this */
RB_FOREACH(ue_context_p, rrc_nr_ue_tree_s, &(RC.nrrrc[0]->rrc_ue_head)) {
gNB_RRC_UE_t *UE = &ue_context_p->ue_context;
PROTOCOL_CTXT_SET_BY_INSTANCE(&ctxt, 0, GNB_FLAG_YES, UE->rrc_ue_id, 0, 0);
ctxt.eNB_index = 0;
rrc_gNB_generate_RRCRelease(&ctxt, ue_context_p);
prnt("RRC Release triggered for UE %u\n", UE->rrc_ue_id);
}
return 0;
}
static telnetshell_cmddef_t rrc_cmds[] = {
{"release_rrc", "[rrc_ue_id(int,opt)]", rrc_gNB_trigger_release},
{"release_rrc_all", "", rrc_gNB_trigger_release_all},
{"", "", NULL},
};
static telnetshell_vardef_t rrc_vars[] = {
{"", 0, 0, NULL}
};
void add_rrc_cmds(void) {
add_telnetcmd("rrc", rrc_vars, rrc_cmds);
}
......@@ -57,11 +57,12 @@ We have only verified LLS-C3 configuration in our lab, i.e. using an external
grandmaster, a switch as a boundary clock, and the gNB/DU and RU. We haven't
tested any RU without S-plane. Radio units we are testing/integrating:
|Vendor |Software Version |
|-----------|-----------------|
|VVDN LPRU |03-v3.0.4 |
|LiteON RU |01.00.08/02.00.03|
|Benetel 650|v0.8.1 |
|Vendor |Software Version |
|-----------------|-----------------|
|VVDN LPRU |03-v3.0.4 |
|LiteON RU |01.00.08/02.00.03|
|Benetel 650 |v0.8.1 |
|Benetel 550 CAT-A|v0.8.1 |
Tested libxran releases:
......@@ -203,6 +204,12 @@ hybrid_e2e 0
```
Probably you need to increase `tx_timestamp_timeout` to 50 or 100 for Intel E-810. You will see that in the logs of ptp.
Create the configuration file for ptp4l (`/etc/sysconfig/ptp4l`)
```
OPTIONS="-f /etc/ptp4l.conf"
```
Create the configuration file for phc2sys (`/etc/sysconfig/phc2sys`)
```
......@@ -373,6 +380,7 @@ git checkout oran_e_maintenance_release_v1.0
Apply the patch (available in `oai_folder/cmake_targets/tools/oran_fhi_integration_patches/E`):
```bash
cd ~/phy
git apply ~/openairinterface5g/cmake_targets/tools/oran_fhi_integration_patches/E/oaioran_E.patch
```
......@@ -628,7 +636,7 @@ Edit the sample OAI gNB configuration file and check following parameters:
that is employed by the xRAN library (`xran_fh_init` and `xran_fh_config`
structs in the code):
* `dpdk_devices`: PCI addresses of NIC VFs binded to the DPDK (not the physical NIC but the VFs, use `lspci | grep Virtual`)
* `system_core`: absolute CPU core ID for DPDK control threads
* `system_core`: absolute CPU core ID for DPDK control threads, it should be an isolated core, in our environment we are using CPU 0
(`rte_mp_handle`, `eal-intr-thread`, `iavf-event-thread`)
* `io_core`: absolute CPU core ID for XRAN library, it should be an isolated core, in our environment we are using CPU 4
* `worker_cores`: array of absolute CPU core IDs for XRAN library, they should be isolated cores, in our environment we are using CPU 2
......@@ -664,10 +672,12 @@ xRAN SRS reception is not supported.
Run the `nr-softmodem` from the build directory:
```bash
cd ~/openairinterface5g/ran_build/build
sudo ./nr-softmodem -O ../../../targets/PROJECTS/GENERIC-NR-5GC/CONF/oran.fh.band78.fr1.273PRB.conf --sa --reorder-thread-disable 1 --thread-pool <list of non isolated cpus>
cd ~/openairinterface5g/cmake_targets/ran_build/build
sudo ./nr-softmodem -O <configuration file> --sa --thread-pool <list of non isolated cpus>
```
**Warning**: Make sure that the configuration file you add after the `-O` option is adapted to your machine, especially to its isolated cores.
**Note**: You may run OAI with O-RAN 7.2 Fronthaul without a RU attached (e.g. for benchmarking).
In such case, you would generate artificial traffic by replacing the `--sa` option by the `--phy-test` option.
......
......@@ -440,7 +440,7 @@ static void UE_synch(void *arg) {
uint64_t dl_carrier, ul_carrier;
nr_get_carrier_frequencies(UE, &dl_carrier, &ul_carrier);
nr_initial_sync_t ret = nr_initial_sync(&syncD->proc, UE, 2, get_softmodem_params()->sa);
if (!ret.cell_notdetected) {
if (ret.cell_detected) {
syncD->rx_offset = ret.rx_offset;
freq_offset = UE->common_vars.freq_offset; // frequency offset computed with pss in initial sync
hw_slot_offset =
......@@ -538,7 +538,7 @@ void processSlotTX(void *arg)
{
nr_rxtx_thread_data_t *rxtxD = (nr_rxtx_thread_data_t *) arg;
const UE_nr_rxtx_proc_t *proc = &rxtxD->proc;
PHY_VARS_NR_UE *UE = rxtxD->UE;
PHY_VARS_NR_UE *UE = rxtxD->UE;
nr_phy_data_tx_t phy_data = {0};
if (UE->if_inst)
......@@ -767,7 +767,7 @@ void *UE_thread(void *arg)
void *rxp[NB_ANTENNAS_RX];
int start_rx_stream = 0;
fapi_nr_config_request_t *cfg = &UE->nrUE_config;
AssertFatal(0== openair0_device_load(&(UE->rfdevice), &openair0_cfg[0]), "");
AssertFatal(0 == openair0_device_load(&(UE->rfdevice), &openair0_cfg[0]), "Could not load the device\n");
UE->rfdevice.host_type = RAU_HOST;
UE->is_synchronized = 0;
AssertFatal(UE->rfdevice.trx_start_func(&UE->rfdevice) == 0, "Could not start the device\n");
......@@ -784,13 +784,13 @@ void *UE_thread(void *arg)
int timing_advance = UE->timing_advance;
NR_UE_MAC_INST_t *mac = get_mac_inst(0);
bool syncRunning=false;
bool syncRunning = false;
const int nb_slot_frame = UE->frame_parms.slots_per_frame;
int absolute_slot=0, decoded_frame_rx=INT_MAX, trashed_frames=0;
int absolute_slot = 0, decoded_frame_rx = INT_MAX, trashed_frames = 0;
int tx_wait_for_dlsch[NR_MAX_SLOTS_PER_FRAME];
int num_ind_fifo = nb_slot_frame;
for(int i=0; i < num_ind_fifo; i++) {
for(int i = 0; i < num_ind_fifo; i++) {
initNotifiedFIFO(UE->tx_resume_ind_fifo + i);
}
int shiftForNextFrame = 0;
......@@ -801,8 +801,9 @@ void *UE_thread(void *arg)
notifiedFIFO_elt_t *res=tryPullTpool(&nf,&(get_nrUE_params()->Tpool));
if (res) {
syncRunning=false;
syncRunning = false;
if (UE->is_synchronized) {
UE->synch_request.received_synch_request = 0;
decoded_frame_rx = mac->mib_frame;
LOG_A(PHY,
"UE synchronized! decoded_frame_rx=%d UE->init_sync_frame=%d trashed_frames=%d\n",
......@@ -815,7 +816,7 @@ void *UE_thread(void *arg)
intialSyncOffset = syncMsg->rx_offset;
}
delNotifiedFIFO_elt(res);
start_rx_stream=0;
start_rx_stream = 0;
} else {
if (IS_SOFTMODEM_IQPLAYER || IS_SOFTMODEM_IQRECORDER) {
// For IQ recorder-player we force synchronization to happen in 280 ms
......
......@@ -494,6 +494,7 @@ typedef struct {
uint32_t tbslbrm;
uint8_t nscid;
uint16_t dlDmrsScramblingId;
uint16_t dlDataScramblingId;
uint16_t pduBitmap;
uint32_t k1_feedback;
uint8_t ldpcBaseGraph;
......
......@@ -55,42 +55,39 @@ void nr_init_pbch_dmrs(PHY_VARS_gNB* gNB)
void nr_init_pdcch_dmrs(PHY_VARS_gNB* gNB, uint32_t Nid)
{
uint32_t x1 = 0, x2 = 0;
uint8_t reset;
NR_DL_FRAME_PARMS *fp = &gNB->frame_parms;
uint32_t ***pdcch_dmrs = gNB->nr_gold_pdcch_dmrs;
int pdcch_dmrs_init_length = (((fp->N_RB_DL<<1)*3)>>5)+1;
for (uint8_t slot=0; slot<fp->slots_per_frame; slot++) {
for (uint8_t symb=0; symb<fp->symbols_per_slot; symb++) {
reset = 1;
x2 = ((1<<17) * (fp->symbols_per_slot*slot+symb+1) * ((Nid<<1)+1) + (Nid<<1));
LOG_D(PHY,"PDCCH DMRS slot %d, symb %d, Nid %d, x2 %x\n",slot,symb,Nid,x2);
for (uint32_t n=0; n<pdcch_dmrs_init_length; n++) {
int pdcch_dmrs_init_length = (((fp->N_RB_DL << 1) * 3) >> 5) + 1;
for (int slot = 0; slot < fp->slots_per_frame; slot++) {
for (int symb = 0; symb < fp->symbols_per_slot; symb++) {
uint8_t reset = 1;
uint32_t x1 = 0;
uint64_t temp_x2 = ((1UL << 17) * (fp->symbols_per_slot * slot + symb + 1) * ((Nid << 1) + 1) + (Nid << 1));
uint32_t x2 = temp_x2 % (1U << 31);
LOG_D(PHY,"PDCCH DMRS slot %d, symb %d, Nid %d, x2 %x\n", slot, symb, Nid, x2);
for (uint32_t n = 0; n < pdcch_dmrs_init_length; n++) {
pdcch_dmrs[slot][symb][n] = lte_gold_generic(&x1, &x2, reset);
reset = 0;
}
}
}
}
void nr_init_pdsch_dmrs(PHY_VARS_gNB* gNB, uint8_t nscid, uint32_t Nid) {
uint32_t x1 = 0, x2 = 0;
uint8_t reset;
void nr_init_pdsch_dmrs(PHY_VARS_gNB* gNB, uint8_t nscid, uint32_t Nid)
{
NR_DL_FRAME_PARMS *fp = &gNB->frame_parms;
uint32_t ****pdsch_dmrs = gNB->nr_gold_pdsch_dmrs;
int pdsch_dmrs_init_length = ((fp->N_RB_DL*12)>>5)+1;
for (uint8_t slot=0; slot<fp->slots_per_frame; slot++) {
for (uint8_t symb=0; symb<fp->symbols_per_slot; symb++) {
reset = 1;
x2 = ((1<<17) * (fp->symbols_per_slot*slot+symb+1) * ((Nid<<1)+1) +((Nid<<1)+nscid));
LOG_D(PHY,"PDSCH DMRS slot %d, symb %d x2 %x, Nid %d,nscid %d\n",slot,symb,x2,Nid,nscid);
for (uint32_t n=0; n<pdsch_dmrs_init_length; n++) {
int pdsch_dmrs_init_length = ((fp->N_RB_DL * 12) >> 5) + 1;
for (int slot = 0; slot < fp->slots_per_frame; slot++) {
for (int symb = 0; symb < fp->symbols_per_slot; symb++) {
uint8_t reset = 1;
uint32_t x1 = 0;
uint64_t temp_x2 = ((1UL << 17) * (fp->symbols_per_slot * slot + symb + 1) * ((Nid << 1) + 1) + ((Nid << 1) + nscid));
uint32_t x2 = temp_x2 % (1U << 31);
LOG_D(PHY,"PDSCH DMRS slot %d, symb %d, Nid %d, nscid %d, x2 %x\n",slot, symb, Nid, nscid, x2);
for (uint32_t n = 0; n < pdsch_dmrs_init_length; n++) {
pdsch_dmrs[slot][symb][nscid][n] = lte_gold_generic(&x1, &x2, reset);
reset = 0;
}
......@@ -99,22 +96,18 @@ void nr_init_pdsch_dmrs(PHY_VARS_gNB* gNB, uint8_t nscid, uint32_t Nid) {
}
void nr_gold_pusch(PHY_VARS_gNB* gNB, int nscid, uint32_t nid) {
unsigned char ns;
unsigned int n = 0, x1 = 0, x2 = 0;
int reset;
void nr_gold_pusch(PHY_VARS_gNB* gNB, int nscid, uint32_t nid)
{
NR_DL_FRAME_PARMS *fp = &gNB->frame_parms;
unsigned short l;
int pusch_dmrs_init_length = ((fp->N_RB_UL*12)>>5)+1;
for (ns=0; ns<fp->slots_per_frame; ns++) {
for (l=0; l<fp->symbols_per_slot; l++) {
reset = 1;
x2 = ((1<<17) * (fp->symbols_per_slot*ns+l+1) * ((nid<<1)+1) +((nid<<1)+nscid));
LOG_D(PHY,"DMRS slot %d, symb %d x2 %x\n",ns,l,x2);
for (n=0; n<pusch_dmrs_init_length; n++) {
int pusch_dmrs_init_length = ((fp->N_RB_UL * 12) >> 5) + 1;
for (int ns = 0; ns < fp->slots_per_frame; ns++) {
for (int l = 0; l < fp->symbols_per_slot; l++) {
int reset = 1;
uint32_t x1 = 0;
uint64_t temp_x2 = ((1UL << 17) * (fp->symbols_per_slot * ns + l + 1) * ((nid << 1) + 1) + ((nid << 1) + nscid));
uint32_t x2 = temp_x2 % (1U << 31);
LOG_D(PHY,"DMRS slot %d, symb %d, nscid %d, nid %d, x2 %x\n", ns, l, nscid, nid, x2);
for (int n = 0; n < pusch_dmrs_init_length; n++) {
gNB->nr_gold_pusch_dmrs[nscid][ns][l][n] = lte_gold_generic(&x1, &x2, reset);
reset = 0;
}
......
......@@ -54,17 +54,17 @@ void nr_gold_pbch(PHY_VARS_NR_UE* ue)
void nr_gold_pdcch(PHY_VARS_NR_UE* ue,
unsigned short nid)
{
unsigned int n = 0, x1 = 0, x2 = 0, x2tmp0 = 0;
uint8_t reset;
int pdcch_dmrs_init_length = (((ue->frame_parms.N_RB_DL << 1) * 3) >> 5) + 1;
for (int ns = 0; ns < ue->frame_parms.slots_per_frame; ns++) {
for (int l = 0; l < ue->frame_parms.symbols_per_slot; l++) {
reset = 1;
x2tmp0 = ((ue->frame_parms.symbols_per_slot * ns + l + 1) * ((nid << 1) + 1));
uint8_t reset = 1;
uint64_t x2tmp0 = ((ue->frame_parms.symbols_per_slot * ns + l + 1) * ((nid << 1) + 1));
x2tmp0 <<= 17;
x2 = (x2tmp0 + (nid << 1)) % (1U << 31); //cinit
for (n=0; n<pdcch_dmrs_init_length; n++) {
x2tmp0 += (nid << 1);
uint32_t x1 = 0;
uint32_t x2 = x2tmp0 % (1U << 31); //cinit
LOG_D(PHY,"PDCCH DMRS slot %d, symb %d, Nid %d, x2 %x\n", ns, l, nid, x2);
for (int n = 0; n < pdcch_dmrs_init_length; n++) {
ue->nr_gold_pdcch[0][ns][l][n] = lte_gold_generic(&x1, &x2, reset);
reset = 0;
}
......@@ -74,21 +74,17 @@ void nr_gold_pdcch(PHY_VARS_NR_UE* ue,
void nr_gold_pdsch(PHY_VARS_NR_UE* ue,
int nscid,
uint32_t nid) {
unsigned int x1 = 0, x2 = 0, x2tmp0 = 0;
uint8_t reset;
int pdsch_dmrs_init_length = ((ue->frame_parms.N_RB_DL*12)>>5)+1;
uint32_t nid)
{
int pdsch_dmrs_init_length = ((ue->frame_parms.N_RB_DL * 12) >> 5) + 1;
for (int ns=0; ns<ue->frame_parms.slots_per_frame; ns++) {
for (int l=0; l<ue->frame_parms.symbols_per_slot; l++) {
reset = 1;
x2tmp0 = ((ue->frame_parms.symbols_per_slot*ns+l+1)*((nid<<1)+1))<<17;
x2 = (x2tmp0+(nid<<1)+nscid)%(1U<<31); //cinit
LOG_D(PHY,"UE DMRS slot %d, symb %d, x2 %x, nscid %d\n",ns,l,x2,nscid);
for (int n=0; n<pdsch_dmrs_init_length; n++) {
uint8_t reset = 1;
uint64_t x2tmp0 = ((ue->frame_parms.symbols_per_slot * ns + l + 1) * ((nid << 1) + 1)) << 17;
uint32_t x1 = 0;
uint32_t x2 = (x2tmp0 + (nid << 1) + nscid) % (1U << 31); //cinit
LOG_D(PHY,"UE DMRS slot %d, symb %d, nscid %d, x2 %x\n", ns, l, nscid, x2);
for (int n = 0; n < pdsch_dmrs_init_length; n++) {
ue->nr_gold_pdsch[0][ns][l][nscid][n] = lte_gold_generic(&x1, &x2, reset);
reset = 0;
}
......@@ -96,21 +92,19 @@ void nr_gold_pdsch(PHY_VARS_NR_UE* ue,
}
}
void nr_init_pusch_dmrs(PHY_VARS_NR_UE* ue,
uint16_t N_n_scid,
uint8_t n_scid)
void nr_init_pusch_dmrs(PHY_VARS_NR_UE* ue, uint16_t N_n_scid, uint8_t n_scid)
{
uint32_t x1 = 0, x2 = 0, n = 0;
NR_DL_FRAME_PARMS *fp = &ue->frame_parms;
uint32_t ****pusch_dmrs = ue->nr_gold_pusch_dmrs;
int pusch_dmrs_init_length = ((fp->N_RB_UL * 12) >> 5) + 1;
for (int slot = 0; slot < fp->slots_per_frame; slot++) {
for (int symb = 0; symb < fp->symbols_per_slot; symb++) {
int reset = 1;
x2 = ((1U << 17) * (fp->symbols_per_slot*slot + symb + 1) * ((N_n_scid << 1) + 1) + ((N_n_scid << 1) + n_scid));
LOG_D(PHY,"DMRS slot %d, symb %d x2 %x\n", slot, symb, x2);
for (n=0; n<pusch_dmrs_init_length; n++) {
uint32_t x1 = 0;
uint64_t t_x2 = ((1UL << 17) * (fp->symbols_per_slot*slot + symb + 1) * ((N_n_scid << 1) + 1) + ((N_n_scid << 1) + n_scid));
uint32_t x2 = t_x2 % (1U << 31);
LOG_D(PHY,"DMRS slot %d, symb %d, N_n_scid %d, n_scid %d, x2 %x\n", slot, symb, N_n_scid, n_scid, x2);
for (int n = 0; n < pusch_dmrs_init_length; n++) {
pusch_dmrs[slot][symb][n_scid][n] = lte_gold_generic(&x1, &x2, reset);
reset = 0;
}
......
......@@ -100,13 +100,12 @@ void free_list(NR_UE_SSB *node) {
free(node);
}
int nr_pbch_detection(const UE_nr_rxtx_proc_t *proc,
PHY_VARS_NR_UE *ue,
int pbch_initial_symbol,
c16_t rxdataF[][ue->frame_parms.samples_per_slot_wCP])
static bool nr_pbch_detection(const UE_nr_rxtx_proc_t *proc,
PHY_VARS_NR_UE *ue,
int pbch_initial_symbol,
c16_t rxdataF[][ue->frame_parms.samples_per_slot_wCP])
{
NR_DL_FRAME_PARMS *frame_parms=&ue->frame_parms;
int ret =-1;
NR_DL_FRAME_PARMS *frame_parms = &ue->frame_parms;
NR_UE_SSB *best_ssb = NULL;
NR_UE_SSB *current_ssb;
......@@ -138,8 +137,9 @@ int nr_pbch_detection(const UE_nr_rxtx_proc_t *proc,
}
}
NR_UE_SSB *temp_ptr=best_ssb;
while (ret!=0 && temp_ptr != NULL) {
NR_UE_SSB *temp_ptr = best_ssb;
bool ret = false;
while (!ret && temp_ptr != NULL) {
start_meas(&ue->dlsch_channel_estimation_stats);
// computing channel estimation for selected best ssb
......@@ -153,11 +153,18 @@ int nr_pbch_detection(const UE_nr_rxtx_proc_t *proc,
stop_meas(&ue->dlsch_channel_estimation_stats);
fapiPbch_t result = {0};
ret = nr_rx_pbch(ue, proc, estimateSz, dl_ch_estimates, frame_parms, temp_ptr->i_ssb, &result, rxdataF);
if (DUMP_PBCH_CH_ESTIMATES && (ret == 0)) {
int pbch_res = nr_rx_pbch(ue, proc, estimateSz, dl_ch_estimates, frame_parms, temp_ptr->i_ssb, &result, rxdataF);
ret = pbch_res == 0;
if (DUMP_PBCH_CH_ESTIMATES && ret) {
write_output("pbch_ch_estimates.m", "pbch_ch_estimates", dl_ch_estimates, frame_parms->nb_antennas_rx*estimateSz, 1, 1);
write_output("pbch_ch_estimates_time.m", "pbch_ch_estimates_time", dl_ch_estimates_time, frame_parms->nb_antennas_rx*frame_parms->ofdm_symbol_size, 1, 1);
write_output("pbch_ch_estimates_time.m",
"pbch_ch_estimates_time",
dl_ch_estimates_time,
frame_parms->nb_antennas_rx * frame_parms->ofdm_symbol_size,
1,
1);
}
temp_ptr=temp_ptr->next_ssb;
......@@ -165,14 +172,10 @@ int nr_pbch_detection(const UE_nr_rxtx_proc_t *proc,
free_list(best_ssb);
if (ret == 0)
if (ret) {
frame_parms->nb_antenna_ports_gNB = 1; // pbch_tx_ant;
// set initial transmission mode to 1 or 2 depending on number of detected TX antennas
// frame_parms->mode1_flag = (pbch_tx_ant==1);
// openair_daq_vars.dlsch_transmission_mode = (pbch_tx_ant>1) ? 2 : 1;
LOG_I(PHY, "[UE%d] Initial sync: pbch decoded sucessfully, ssb index %d\n", ue->Mod_id, frame_parms->ssb_index);
LOG_I(PHY, "[UE%d] Initial sync: pbch decoded sucessfully, ssb index %d\n", ue->Mod_id, frame_parms->ssb_index);
}
return ret;
}
......@@ -262,7 +265,7 @@ nr_initial_sync_t nr_initial_sync(UE_nr_rxtx_proc_t *proc, PHY_VARS_NR_UE *ue, i
int freq_offset_sss = 0;
bool ret_sss = rx_sss_nr(ue, proc, &metric_tdd_ncp, &phase_tdd_ncp, &freq_offset_sss, rxdataF);
ret.cell_notdetected = !ret_sss; // rx_sss_nr returns true if success
ret.cell_detected = ret_sss; // rx_sss_nr returns true if success
// digital compensation of FFO for SSB symbols
if (ue->UE_fo_compensation) {
double s_time = 1 / (1.0e3 * fp->samples_per_subframe); // sampling time
......@@ -282,12 +285,12 @@ nr_initial_sync_t nr_initial_sync(UE_nr_rxtx_proc_t *proc, PHY_VARS_NR_UE *ue, i
ue->common_vars.freq_offset += freq_offset_sss;
}
if (ret.cell_notdetected == 0) { // we got sss channel
if (ret.cell_detected) { // we got sss channel
nr_gold_pbch(ue);
ret.cell_notdetected = nr_pbch_detection(proc, ue, 1, rxdataF); // start pbch detection at first symbol after pss
ret.cell_detected = nr_pbch_detection(proc, ue, 1, rxdataF); // start pbch detection at first symbol after pss
}
if (ret.cell_notdetected == 0) {
if (ret.cell_detected) {
// sync at symbol ue->symbol_offset
// computing the offset wrt the beginning of the frame
int mu = fp->numerology_index;
......@@ -347,7 +350,7 @@ nr_initial_sync_t nr_initial_sync(UE_nr_rxtx_proc_t *proc, PHY_VARS_NR_UE *ue, i
fp->Nid_cell,
metric_tdd_ncp,
phase_tdd_ncp,
!ret.cell_notdetected,
ret.cell_detected,
ret.rx_offset);
#endif
......@@ -356,11 +359,11 @@ nr_initial_sync_t nr_initial_sync(UE_nr_rxtx_proc_t *proc, PHY_VARS_NR_UE *ue, i
LOG_I(PHY, "TDD Normal prefix: SSS error condition: sync_pos %d\n", sync_pos);
#endif
}
if (ret.cell_notdetected == 0)
if (ret.cell_detected)
break;
}
} else {
ret.cell_notdetected = true;
ret.cell_detected = false;
}
/* Consider this is a false detection if the offset is > 1000 Hz
......@@ -371,7 +374,7 @@ nr_initial_sync_t nr_initial_sync(UE_nr_rxtx_proc_t *proc, PHY_VARS_NR_UE *ue, i
LOG_E(HW, "Ignore MIB with high freq offset [%d Hz] estimation \n",ue->common_vars.freq_offset);
}*/
if (ret.cell_notdetected == 0) { // PBCH found so indicate sync to higher layers and configure frame parameters
if (ret.cell_detected) { // PBCH found so indicate sync to higher layers and configure frame parameters
//#ifdef DEBUG_INITIAL_SYNCH
......@@ -406,7 +409,7 @@ nr_initial_sync_t nr_initial_sync(UE_nr_rxtx_proc_t *proc, PHY_VARS_NR_UE *ue, i
}
// gain control
if (ret.cell_notdetected != 0) { // we are not synched, so we cannot use rssi measurement (which is based on channel estimates)
if (!ret.cell_detected) { // 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
......@@ -429,6 +432,8 @@ nr_initial_sync_t nr_initial_sync(UE_nr_rxtx_proc_t *proc, PHY_VARS_NR_UE *ue, i
#ifdef DEBUG_INITIAL_SYNCH
LOG_I(PHY, "[UE%d] Initial sync : Estimated power: %d dB\n", ue->Mod_id, ue->measurements.rx_power_avg_dB[0]);
#endif
} else {
LOG_A(PHY, "Initial sync successful\n");
}
// exit_fun("debug exit");
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_NR_INITIAL_UE_SYNC, VCD_FUNCTION_OUT);
......
......@@ -319,7 +319,7 @@ int dump_ue_stats(PHY_VARS_NR_UE *phy_vars_ue,
@param sa current running mode
*/
typedef struct {
bool cell_notdetected;
bool cell_detected;
int rx_offset;
} nr_initial_sync_t;
nr_initial_sync_t nr_initial_sync(UE_nr_rxtx_proc_t *proc, PHY_VARS_NR_UE *phy_vars_ue, int n_frames, int sa);
......
......@@ -55,11 +55,7 @@
//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)
void nr_pusch_codeword_scrambling_uci(uint8_t *in, uint32_t size, uint32_t Nid, uint32_t n_RNTI, uint32_t* out)
{
uint8_t reset, b_idx;
uint32_t x1 = 0, x2 = 0, s = 0, temp_out = 0;
......@@ -93,12 +89,7 @@ void nr_pusch_codeword_scrambling_uci(uint8_t *in,
}
}
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, uint32_t* out)
{
if (uci_on_pusch)
nr_pusch_codeword_scrambling_uci(in, size, Nid, n_RNTI, out);
......@@ -221,7 +212,7 @@ void nr_ue_ulsch_procedures(PHY_VARS_NR_UE *UE,
nr_pusch_codeword_scrambling(harq_process_ul_ue->f,
available_bits,
ulsch_ue->Nid_cell,
pusch_pdu->data_scrambling_id,
rnti,
false,
scrambled_output);
......
......@@ -691,7 +691,7 @@ static bool nr_ue_dlsch_procedures(PHY_VARS_NR_UE *ue, const UE_nr_rxtx_proc_t *
nr_dlsch_unscrambling(llr[0],
dl_harq0->G,
0,
ue->frame_parms.Nid_cell,
dlsch[0].dlsch_config.dlDataScramblingId,
dlsch[0].rnti);
......@@ -787,7 +787,7 @@ static bool nr_ue_dlsch_procedures(PHY_VARS_NR_UE *ue, const UE_nr_rxtx_proc_t *
nr_dlsch_unscrambling(llr[1],
dl_harq1->G,
0,
ue->frame_parms.Nid_cell,
dlsch[1].dlsch_config.dlDataScramblingId,
dlsch[1].rnti);
stop_meas(&ue->dlsch_unscrambling_stats);
......
......@@ -766,10 +766,10 @@ int main(int argc, char **argv)
}
if (UE->is_synchronized == 0) {
UE_nr_rxtx_proc_t proc={0};
nr_initial_sync_t ret = nr_initial_sync(&proc, UE, 1, 0);
printf("nr_initial_sync1 returns %d\n", ret.cell_notdetected);
if (ret.cell_notdetected)
n_errors++;
nr_initial_sync_t ret = nr_initial_sync(&proc, UE, 1, 0);
printf("nr_initial_sync1 returns %s\n", ret.cell_detected ? "cell detected" : "cell not detected");
if (!ret.cell_detected)
n_errors++;
}
else {
UE_nr_rxtx_proc_t proc={0};
......
add_library(e2_ran_func_cuup STATIC
init_ran_func.c
read_setup_ran.c
../flexric/test/rnd/fill_rnd_data_e2_setup_req.c # this is not rnd data; it is used to fill E2 Node Component Configuration Addition List in E2 Setup Request message
CUSTOMIZED/ran_func_gtp.c # current implementation doesn't take split architecture into account, neither CU/DU nor CU-UP/CU-CP
CUSTOMIZED/ran_func_pdcp.c # current implementation doesn't take split architecture into account, neither CU/DU nor CU-UP/CU-CP
O-RAN/ran_e2sm_ue_id.c
O-RAN/ran_func_kpm.c
O-RAN/ran_func_kpm_subs.c
O-RAN/ran_func_rc.c
O-RAN/ran_func_rc_subs.c
CUSTOMIZED/ran_func_gtp.c # GTP SM not yet implemented in CU-UP
CUSTOMIZED/ran_func_pdcp.c
CUSTOMIZED/ran_func_tc.c # currently, not implemented; therefore, filling rnd data
../flexric/test/rnd/fill_rnd_data_tc.c
O-RAN/ran_func_kpm.c # this file should only contain PDCP-U/GTP; to be done in the future
../flexric/test/rnd/fill_rnd_data_kpm.c # this dependancy will be taken out once RAN Function Definition is implemented
O-RAN/ran_func_rc.c # this file should only contain PDCP-U/GTP; to be done in the future
O-RAN/ran_func_rc_subs.c
../flexric/test/rnd/fill_rnd_data_rc.c # this dependancy will be taken out once RAN Function Definition is implemented
)
target_link_libraries(e2_ran_func_cuup PUBLIC asn1_nr_rrc nr_rrc asn1_nr_rrc_hdrs e2_time_obj kpm_ric_info_common_obj 3gpp_derived_ie_obj)
target_link_libraries(e2_ran_func_cuup PUBLIC asn1_nr_rrc nr_rrc asn1_nr_rrc_hdrs e2_time_obj kpm_ric_info_common_obj 3gpp_derived_ie_obj sm_common_ie_obj)
target_compile_definitions(e2_ran_func_cuup PUBLIC ${E2AP_VERSION} ${KPM_VERSION} NGRAN_GNB_CUUP)
add_library(e2_ran_func_du_cucp_cuup STATIC
init_ran_func.c
read_setup_ran.c
../flexric/test/rnd/fill_rnd_data_e2_setup_req.c # this is not rnd data; it is used to fill E2 Node Component Configuration Addition List in E2 Setup Request message
CUSTOMIZED/ran_func_gtp.c # current implementation doesn't take split architecture into account, neither CU/DU nor CU-UP/CU-CP
CUSTOMIZED/ran_func_pdcp.c # current implementation doesn't take split architecture into account, neither CU/DU nor CU-UP/CU-CP
O-RAN/ran_func_kpm.c # this file should only contain RRC/PDCP-C; to be done in the future
# when nr-softmodem is divided in separate executables
../flexric/test/rnd/fill_rnd_data_kpm.c # this dependancy will be taken out once RAN Function Definition is implemented
O-RAN/ran_func_rc.c # this file should only contain RRC/PDCP-C; to be done in the future
# when nr-softmodem is divided in separate executables
O-RAN/ran_e2sm_ue_id.c
O-RAN/ran_func_kpm.c
O-RAN/ran_func_kpm_subs.c
O-RAN/ran_func_rc.c
O-RAN/ran_func_rc_subs.c
../flexric/test/rnd/fill_rnd_data_rc.c # this dependancy will be taken out once RAN Function Definition is implemented
../flexric/src/sm/rc_sm/ie/rc_data_ie.c
CUSTOMIZED/ran_func_gtp.c
CUSTOMIZED/ran_func_pdcp.c
CUSTOMIZED/ran_func_mac.c
CUSTOMIZED/ran_func_rlc.c
CUSTOMIZED/ran_func_slice.c
CUSTOMIZED/ran_func_tc.c
../flexric/test/rnd/fill_rnd_data_tc.c
CUSTOMIZED/ran_func_slice.c # currently, not implemented; therefore, filling rnd data
../flexric/test/rnd/fill_rnd_data_slice.c
CUSTOMIZED/ran_func_tc.c # currently, not implemented; therefore, filling rnd data
../flexric/test/rnd/fill_rnd_data_tc.c
)
target_link_libraries(e2_ran_func_du_cucp_cuup PUBLIC asn1_nr_rrc nr_rrc asn1_nr_rrc_hdrs e2_time_obj kpm_ric_info_common_obj 3gpp_derived_ie_obj e2sm_rc_ir_obj sm_common_ie_obj e2_agent)
target_compile_definitions(e2_ran_func_du_cucp_cuup PUBLIC ${E2AP_VERSION} ${KPM_VERSION} NGRAN_GNB_DU NGRAN_GNB_CUCP NGRAN_GNB_CUUP)
target_link_libraries(e2_ran_func_du_cucp_cuup PUBLIC asn1_nr_rrc nr_rrc asn1_nr_rrc_hdrs e2_time_obj kpm_ric_info_common_obj 3gpp_derived_ie_obj e2sm_rc_ir_obj sm_common_ie_obj)
target_compile_definitions(e2_ran_func_du_cucp_cuup PUBLIC ${E2AP_VERSION} ${KPM_VERSION} NGRAN_GNB_DU NGRAN_GNB_CUCP NGRAN_GNB_CUUP)
# Current implementation:
# - we only have one executable nr-softmodem for 4 node types: DU, CU, gNB-mono, CU-CP
# In the future, when nr-softmodem is separated, linking should be done as following:
# - DU: e2_ran_func_du
# - CU-CP : e2_ran_func_cucp
# - CU-UP: e2_ran_func_cuup (this is available at the moment, executable nr-cuup)
# - CU: e2_ran_func_cucp + e2_ran_func_cuup
# - gNB-mono: e2_ran_func_du + e2_ran_func_cucp + e2_ran_func_cuup
/*
* 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 "ran_e2sm_ue_id.h"
ue_id_e2sm_t fill_e2sm_gnb_ue_id_data(const gNB_RRC_UE_t *rrc_ue_context, __attribute__((unused))const uint32_t rrc_ue_id, __attribute__((unused))const ue_id_t cucp_ue_id)
{
ue_id_e2sm_t ue_id = {0};
ue_id.type = GNB_UE_ID_E2SM;
// 6.2.3.16
// Mandatory
// AMF UE NGAP ID
ue_id.gnb.amf_ue_ngap_id = rrc_ue_context->amf_ue_ngap_id;
// Mandatory
//GUAMI 6.2.3.17
ue_id.gnb.guami.plmn_id = (e2sm_plmn_t) {
.mcc = rrc_ue_context->ue_guami.mcc,
.mnc = rrc_ue_context->ue_guami.mnc,
.mnc_digit_len = rrc_ue_context->ue_guami.mnc_len
};
ue_id.gnb.guami.amf_region_id = rrc_ue_context->ue_guami.amf_region_id;
ue_id.gnb.guami.amf_set_id = rrc_ue_context->ue_guami.amf_set_id;
ue_id.gnb.guami.amf_ptr = rrc_ue_context->ue_guami.amf_pointer;
// RAN UE ID
// Optional
// 6.2.3.25
// OCTET STRING (SIZE (8))
// Defined in TS 38.473 (F1AP)
// clause 9.2.2.1
// UE CONTEXT SETUP REQUEST
ue_id.gnb.ran_ue_id = calloc(1, sizeof(uint64_t));
assert(ue_id.gnb.ran_ue_id != NULL);
*ue_id.gnb.ran_ue_id = rrc_ue_context->rrc_ue_id;
return ue_id;
}
ue_id_e2sm_t fill_e2sm_cu_ue_id_data(const gNB_RRC_UE_t *rrc_ue_context, const uint32_t rrc_ue_id, const ue_id_t cucp_ue_id)
{
ue_id_e2sm_t ue_id = fill_e2sm_gnb_ue_id_data(rrc_ue_context, rrc_ue_id, cucp_ue_id);
// gNB-CU UE F1AP ID List
// C-ifCUDUseparated
ue_id.gnb.gnb_cu_ue_f1ap_lst_len = 1;
ue_id.gnb.gnb_cu_ue_f1ap_lst = calloc(ue_id.gnb.gnb_cu_ue_f1ap_lst_len, sizeof(uint32_t));
assert(ue_id.gnb.gnb_cu_ue_f1ap_lst != NULL && "Memory exhausted");
ue_id.gnb.gnb_cu_ue_f1ap_lst[0] = rrc_ue_context->rrc_ue_id;
return ue_id;
}
ue_id_e2sm_t fill_e2sm_du_ue_id_data(__attribute__((unused))const gNB_RRC_UE_t *rrc_ue_context, const uint32_t rrc_ue_id, __attribute__((unused))const ue_id_t cucp_ue_id)
{
ue_id_e2sm_t ue_id = {0};
ue_id.type = GNB_DU_UE_ID_E2SM;
// 6.2.3.21
// gNB CU UE F1AP
// Mandatory
ue_id.gnb_du.gnb_cu_ue_f1ap = rrc_ue_id;
// 6.2.3.25
// RAN UE ID
// Optional
ue_id.gnb_du.ran_ue_id = calloc(1, sizeof(uint64_t));
assert(ue_id.gnb_du.ran_ue_id != NULL);
*ue_id.gnb_du.ran_ue_id = rrc_ue_id;
return ue_id;
}
ue_id_e2sm_t fill_e2sm_cucp_ue_id_data(const gNB_RRC_UE_t *rrc_ue_context, const uint32_t rrc_ue_id, const ue_id_t cucp_ue_id)
{
ue_id_e2sm_t ue_id = fill_e2sm_gnb_ue_id_data(rrc_ue_context, rrc_ue_id, cucp_ue_id);
//gNB-CU-CP UE E1AP ID List
//C-ifCPUPseparated
ue_id.gnb.gnb_cu_cp_ue_e1ap_lst_len = 1;
ue_id.gnb.gnb_cu_cp_ue_e1ap_lst = calloc(ue_id.gnb.gnb_cu_cp_ue_e1ap_lst_len, sizeof(uint32_t));
assert(ue_id.gnb.gnb_cu_cp_ue_e1ap_lst != NULL && "Memory exhausted");
ue_id.gnb.gnb_cu_cp_ue_e1ap_lst[0] = rrc_ue_context->rrc_ue_id;
return ue_id;
}
ue_id_e2sm_t fill_e2sm_cuup_ue_id_data(__attribute__((unused))const gNB_RRC_UE_t *rrc_ue_context, __attribute__((unused))const uint32_t rrc_ue_id, const ue_id_t cucp_ue_id)
{
ue_id_e2sm_t ue_id = {0};
ue_id.type = GNB_CU_UP_UE_ID_E2SM;
// 6.2.3.20
// Mandatory
ue_id.gnb_cu_up.gnb_cu_cp_ue_e1ap = cucp_ue_id; // RAN UE NGAP ID = gNB UE NGAP ID = rrc_ue_id
// 6.2.3.25
// RAN UE ID
// Optional
ue_id.gnb_cu_up.ran_ue_id = calloc(1, sizeof(uint64_t));
assert(ue_id.gnb_cu_up.ran_ue_id != NULL);
*ue_id.gnb_cu_up.ran_ue_id = cucp_ue_id; // RAN UE NGAP ID = gNB UE NGAP ID = rrc_ue_id
return ue_id;
}
get_ue_id fill_ue_id_data[END_NGRAN_NODE_TYPE] =
{
NULL,
NULL,
fill_e2sm_gnb_ue_id_data,
NULL,
NULL,
fill_e2sm_cu_ue_id_data,
NULL,
fill_e2sm_du_ue_id_data,
NULL,
fill_e2sm_cucp_ue_id_data,
fill_e2sm_cuup_ue_id_data,
};
/*
* 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 RAN_E2SM_UE_ID_H
#define RAN_E2SM_UE_ID_H
#include "openair2/E2AP/flexric/src/agent/../sm/sm_io.h"
#include "openair2/RRC/NR/rrc_gNB_UE_context.h"
ue_id_e2sm_t fill_e2sm_gnb_ue_id_data(const gNB_RRC_UE_t *rrc_ue_context, const uint32_t rrc_ue_id, const ue_id_t cucp_ue_id);
ue_id_e2sm_t fill_e2sm_cu_ue_id_data(const gNB_RRC_UE_t *rrc_ue_context, const uint32_t rrc_ue_id, const ue_id_t cucp_ue_id);
ue_id_e2sm_t fill_e2sm_du_ue_id_data(const gNB_RRC_UE_t *rrc_ue_context, const uint32_t rrc_ue_id, const ue_id_t cucp_ue_id);
ue_id_e2sm_t fill_e2sm_cucp_ue_id_data(const gNB_RRC_UE_t *rrc_ue_context, const uint32_t rrc_ue_id, const ue_id_t cucp_ue_id);
ue_id_e2sm_t fill_e2sm_cuup_ue_id_data(const gNB_RRC_UE_t *rrc_ue_context, const uint32_t rrc_ue_id, const ue_id_t cucp_ue_id);
typedef ue_id_e2sm_t (*get_ue_id)(const gNB_RRC_UE_t *rrc_ue_context, const uint32_t rrc_ue_id, const ue_id_t cucp_ue_id);
extern get_ue_id fill_ue_id_data[END_NGRAN_NODE_TYPE];
#endif
/*
* 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 "ran_func_kpm_subs.h"
#include <search.h>
/* measurements that need to store values from previous reporting period have a limitation
when it comes to multiple subscriptions to the same UEs; ric_req_id is unique per subscription */
typedef struct uldlcounter {
uint32_t dl;
uint32_t ul;
} uldlcounter_t;
static uldlcounter_t last_pdcp_sdu_total_bytes[MAX_MOBILES_PER_GNB] = {0};
static nr_pdcp_statistics_t get_pdcp_stats_per_drb(const uint32_t rrc_ue_id, const int rb_id)
{
nr_pdcp_statistics_t pdcp = {0};
const int srb_flag = 0;
// Get PDCP stats for specific DRB
const bool rc = nr_pdcp_get_statistics(rrc_ue_id, srb_flag, rb_id, &pdcp);
assert(rc == true && "Cannot get PDCP stats\n");
return pdcp;
}
/* 3GPP TS 28.522 - section 5.1.2.1.1.1
note: this measurement is calculated as per spec */
static meas_record_lst_t fill_DRB_PdcpSduVolumeDL(__attribute__((unused))uint32_t gran_period_ms, cudu_ue_info_pair_t ue_info, const size_t ue_idx)
{
meas_record_lst_t meas_record = {0};
// Get PDCP stats per DRB
const int rb_id = 1; // at the moment, only 1 DRB is supported
nr_pdcp_statistics_t pdcp = get_pdcp_stats_per_drb(ue_info.rrc_ue_id, rb_id);
meas_record.value = INTEGER_MEAS_VALUE;
// Get DL data volume delivered to PDCP layer
meas_record.int_val = (pdcp.rxsdu_bytes - last_pdcp_sdu_total_bytes[ue_idx].dl)*8/1000; // [kb]
last_pdcp_sdu_total_bytes[ue_idx].dl = pdcp.rxsdu_bytes;
return meas_record;
}
/* 3GPP TS 28.522 - section 5.1.2.1.2.1
note: this measurement is calculated as per spec */
static meas_record_lst_t fill_DRB_PdcpSduVolumeUL(__attribute__((unused))uint32_t gran_period_ms, cudu_ue_info_pair_t ue_info, const size_t ue_idx)
{
meas_record_lst_t meas_record = {0};
// Get PDCP stats per DRB
const int rb_id = 1; // at the moment, only 1 DRB is supported
nr_pdcp_statistics_t pdcp = get_pdcp_stats_per_drb(ue_info.rrc_ue_id, rb_id);
meas_record.value = INTEGER_MEAS_VALUE;
// Get UL data volume delivered from PDCP layer
meas_record.int_val = (pdcp.txsdu_bytes - last_pdcp_sdu_total_bytes[ue_idx].ul)*8/1000; // [kb]
last_pdcp_sdu_total_bytes[ue_idx].ul = pdcp.txsdu_bytes;
return meas_record;
}
#if defined (NGRAN_GNB_DU)
static uldlcounter_t last_rlc_pdu_total_bytes[MAX_MOBILES_PER_GNB] = {0};
static uldlcounter_t last_total_prbs[MAX_MOBILES_PER_GNB] = {0};
static nr_rlc_statistics_t get_rlc_stats_per_drb(const rnti_t rnti, const int rb_id)
{
nr_rlc_statistics_t rlc = {0};
const int srb_flag = 0;
// Get RLC stats for specific DRB
const bool rc = nr_rlc_get_statistics(rnti, srb_flag, rb_id, &rlc);
assert(rc == true && "Cannot get RLC stats\n");
// Activate average sojourn time at the RLC buffer for specific DRB
nr_rlc_activate_avg_time_to_tx(rnti, rb_id+3, 1);
return rlc;
}
/* 3GPP TS 28.522 - section 5.1.3.3.3
note: by default this measurement is calculated for previous 100ms (openair2/LAYER2/nr_rlc/nr_rlc_entity.c:118, 173, 213); please, update according to your needs */
static meas_record_lst_t fill_DRB_RlcSduDelayDl(__attribute__((unused))uint32_t gran_period_ms, cudu_ue_info_pair_t ue_info, __attribute__((unused))const size_t ue_idx)
{
meas_record_lst_t meas_record = {0};
// Get RLC stats per DRB
const int rb_id = 1; // at the moment, only 1 DRB is supported
nr_rlc_statistics_t rlc = get_rlc_stats_per_drb(ue_info.ue->rnti, rb_id);
meas_record.value = REAL_MEAS_VALUE;
// Get the value of sojourn time at the RLC buffer
meas_record.real_val = rlc.txsdu_avg_time_to_tx; // [μs]
return meas_record;
}
/* 3GPP TS 28.522 - section 5.1.1.3.1
note: per spec, average UE throughput in DL (taken into consideration values from all UEs, and averaged)
here calculated as: UE specific throughput in DL */
static meas_record_lst_t fill_DRB_UEThpDl(uint32_t gran_period_ms, cudu_ue_info_pair_t ue_info, const size_t ue_idx)
{
meas_record_lst_t meas_record = {0};
// Get RLC stats per DRB
const int rb_id = 1; // at the moment, only 1 DRB is supported
nr_rlc_statistics_t rlc = get_rlc_stats_per_drb(ue_info.ue->rnti, rb_id);
meas_record.value = REAL_MEAS_VALUE;
// Calculate DL Thp
meas_record.real_val = (double)(rlc.txpdu_bytes - last_rlc_pdu_total_bytes[ue_idx].dl)*8/gran_period_ms; // [kbps]
last_rlc_pdu_total_bytes[ue_idx].dl = rlc.txpdu_bytes;
return meas_record;
}
/* 3GPP TS 28.522 - section 5.1.1.3.3
note: per spec, average UE throughput in UL (taken into consideration values from all UEs, and averaged)
here calculated as: UE specific throughput in UL */
static meas_record_lst_t fill_DRB_UEThpUl(uint32_t gran_period_ms, cudu_ue_info_pair_t ue_info, const size_t ue_idx)
{
meas_record_lst_t meas_record = {0};
// Get RLC stats per DRB
const int rb_id = 1; // at the moment, only 1 DRB is supported
nr_rlc_statistics_t rlc = get_rlc_stats_per_drb(ue_info.ue->rnti, rb_id);
meas_record.value = REAL_MEAS_VALUE;
// Calculate UL Thp
meas_record.real_val = (double)(rlc.rxpdu_bytes - last_rlc_pdu_total_bytes[ue_idx].ul)*8/gran_period_ms; // [kbps]
last_rlc_pdu_total_bytes[ue_idx].ul = rlc.rxpdu_bytes;
return meas_record;
}
/* 3GPP TS 28.522 - section 5.1.1.2.1
note: per spec, DL PRB usage [%] = (total used PRBs for DL traffic / total available PRBs for DL traffic) * 100
here calculated as: aggregated DL PRBs (t) - aggregated DL PRBs (t-gran_period) */
static meas_record_lst_t fill_RRU_PrbTotDl(__attribute__((unused))uint32_t gran_period_ms, cudu_ue_info_pair_t ue_info, const size_t ue_idx)
{
meas_record_lst_t meas_record = {0};
meas_record.value = INTEGER_MEAS_VALUE;
// Get the number of DL PRBs
meas_record.int_val = ue_info.ue->mac_stats.dl.total_rbs - last_total_prbs[ue_idx].dl; // [PRBs]
last_total_prbs[ue_idx].dl = ue_info.ue->mac_stats.dl.total_rbs;
return meas_record;
}
/* 3GPP TS 28.522 - section 5.1.1.2.2
note: per spec, UL PRB usage [%] = (total used PRBs for UL traffic / total available PRBs for UL traffic) * 100
here calculated as: aggregated UL PRBs (t) - aggregated UL PRBs (t-gran_period) */
static meas_record_lst_t fill_RRU_PrbTotUl(__attribute__((unused))uint32_t gran_period_ms, cudu_ue_info_pair_t ue_info, const size_t ue_idx)
{
meas_record_lst_t meas_record = {0};
meas_record.value = INTEGER_MEAS_VALUE;
// Get the number of UL PRBs
meas_record.int_val = ue_info.ue->mac_stats.ul.total_rbs - last_total_prbs[ue_idx].ul; // [PRBs]
last_total_prbs[ue_idx].ul = ue_info.ue->mac_stats.ul.total_rbs;
return meas_record;
}
#endif
static kv_measure_t lst_measure[] = {
{.key = "DRB.PdcpSduVolumeDL", .value = fill_DRB_PdcpSduVolumeDL },
{.key = "DRB.PdcpSduVolumeUL", .value = fill_DRB_PdcpSduVolumeUL },
#if defined (NGRAN_GNB_DU)
{.key = "DRB.RlcSduDelayDl", .value = fill_DRB_RlcSduDelayDl },
{.key = "DRB.UEThpDl", .value = fill_DRB_UEThpDl },
{.key = "DRB.UEThpUl", .value = fill_DRB_UEThpUl },
{.key = "RRU.PrbTotDl", .value = fill_RRU_PrbTotDl },
{.key = "RRU.PrbTotUl", .value = fill_RRU_PrbTotUl },
#endif
};
void init_kpm_subs_data(void)
{
const size_t ht_len = sizeof(lst_measure) / sizeof(lst_measure[0]);
hcreate(ht_len);
ENTRY kv_pair;
for (size_t i = 0; i < ht_len; i++) {
kv_pair.key = lst_measure[i].key;
kv_pair.data = &lst_measure[i];
hsearch(kv_pair, ENTER);
}
}
meas_record_lst_t get_kpm_meas_value(char* kpm_meas_name, uint32_t gran_period_ms, cudu_ue_info_pair_t ue_info, const size_t ue_idx)
{
assert(kpm_meas_name != NULL);
ENTRY search_entry = {.key = kpm_meas_name};
ENTRY *found_entry = hsearch(search_entry, FIND);
assert(found_entry != NULL && "Unsupported KPM measurement name");
kv_measure_t *kv_found = (kv_measure_t *)found_entry->data;
meas_record_lst_t meas_record = kv_found->value(gran_period_ms, ue_info, ue_idx);
return meas_record;
}
/*
* 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 RAN_FUNC_SM_KPM_SUBSCRIPTION_AGENT_H
#define RAN_FUNC_SM_KPM_SUBSCRIPTION_AGENT_H
#include "openair2/E2AP/flexric/src/sm/kpm_sm/kpm_data_ie_wrapper.h"
#include "openair2/LAYER2/NR_MAC_gNB/mac_proto.h"
#include "openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.h"
#include "openair2/LAYER2/nr_rlc/nr_rlc_oai_api.h"
typedef struct {
uint32_t rrc_ue_id;
NR_UE_info_t* ue;
} cudu_ue_info_pair_t;
typedef meas_record_lst_t (*kpm_meas_fp)(uint32_t gran_period_ms, cudu_ue_info_pair_t ue_info, const size_t ue_idx);
typedef struct{
char* key;
kpm_meas_fp value;
} kv_measure_t;
void init_kpm_subs_data(void);
meas_record_lst_t get_kpm_meas_value(char* kpm_meas_name, uint32_t gran_period_ms, cudu_ue_info_pair_t ue_info, const size_t ue_idx);
#endif
......@@ -21,10 +21,109 @@
#include "read_setup_ran.h"
#include "../../E2AP/flexric/src/lib/e2ap/e2ap_node_component_config_add_wrapper.h"
#include "../../E2AP/flexric/test/rnd/fill_rnd_data_e2_setup_req.h"
#include <assert.h>
#include <stdlib.h>
#if defined(E2AP_V2) || defined(E2AP_V3)
// NGAP
static e2ap_node_component_config_add_t fill_ngap_e2ap_node_component_config_add(void)
{
e2ap_node_component_config_add_t dst = {0};
// Mandatory
// 9.2.26
dst.e2_node_comp_interface_type = NG_E2AP_NODE_COMP_INTERFACE_TYPE;
// Bug!! Optional in the standard, mandatory in ASN.1
// 9.2.32
dst.e2_node_comp_id.type = NG_E2AP_NODE_COMP_INTERFACE_TYPE;
const char ng_msg[] = "Dummy message";
dst.e2_node_comp_id.ng_amf_name = cp_str_to_ba(ng_msg);
// Mandatory
// 9.2.27
const char req[] = "NGAP Request Message sent";
const char res[] = "NGAP Response Message reveived";
dst.e2_node_comp_conf.request = cp_str_to_ba(req);
dst.e2_node_comp_conf.response = cp_str_to_ba(res);
return dst;
}
// F1AP
static e2ap_node_component_config_add_t fill_f1ap_e2ap_node_component_config_add(void)
{
e2ap_node_component_config_add_t dst = {0};
// Mandatory
// 9.2.26
dst.e2_node_comp_interface_type = F1_E2AP_NODE_COMP_INTERFACE_TYPE;
// Bug!! Optional in the standard, mandatory in ASN.1
// 9.2.32
dst.e2_node_comp_id.type = F1_E2AP_NODE_COMP_INTERFACE_TYPE;
dst.e2_node_comp_id.f1_gnb_du_id = 1023;
// Mandatory
// 9.2.27
const char req[] = "F1AP Request Message sent";
const char res[] = "F1AP Response Message reveived";
dst.e2_node_comp_conf.request = cp_str_to_ba(req);
dst.e2_node_comp_conf.response = cp_str_to_ba(res);
return dst;
}
// E1AP
static e2ap_node_component_config_add_t fill_e1ap_e2ap_node_component_config_add(void)
{
e2ap_node_component_config_add_t dst = {0};
// Mandatory
// 9.2.26
dst.e2_node_comp_interface_type = E1_E2AP_NODE_COMP_INTERFACE_TYPE;
// Bug!! Optional in the standard, mandatory in ASN.1
// 9.2.32
dst.e2_node_comp_id.type = E1_E2AP_NODE_COMP_INTERFACE_TYPE;
dst.e2_node_comp_id.e1_gnb_cu_up_id = 1025;
// Mandatory
// 9.2.27
const char req[] = "E1AP Request Message sent";
const char res[] = "E1AP Response Message reveived";
dst.e2_node_comp_conf.request = cp_str_to_ba(req);
dst.e2_node_comp_conf.response = cp_str_to_ba(res);
return dst;
}
// S1AP
static e2ap_node_component_config_add_t fill_s1ap_e2ap_node_component_config_add(void)
{
e2ap_node_component_config_add_t dst = {0};
// Mandatory
// 9.2.26
dst.e2_node_comp_interface_type = S1_E2AP_NODE_COMP_INTERFACE_TYPE;
// Bug!! Optional in the standard, mandatory in ASN.1
// 9.2.32
dst.e2_node_comp_id.type = S1_E2AP_NODE_COMP_INTERFACE_TYPE;
const char str[] = "S1 NAME";
dst.e2_node_comp_id.s1_mme_name = cp_str_to_ba(str);
// Mandatory
// 9.2.27
const char req[] = "S1AP Request Message sent";
const char res[] = "S1AP Response Message reveived";
dst.e2_node_comp_conf.request = cp_str_to_ba(req);
dst.e2_node_comp_conf.response = cp_str_to_ba(res);
return dst;
}
#endif
void read_setup_ran(void* data, const ngran_node_t node_type)
{
assert(data != NULL);
......
This diff is collapsed.
flexric @ 34d6810f
Subproject commit 7c424e882adae6ad72a24470d8c3e731189062c0
Subproject commit 34d6810f9ab435ac3a4023d5e1917669e24341da
......@@ -63,11 +63,6 @@
#define RAR_PAYLOAD_SIZE_MAX 128
#define MAX_CSI_REPORTCONFIG 48
#define NR_BSR_TRIGGER_NONE (0) /* No BSR Trigger */
#define NR_BSR_TRIGGER_REGULAR (1) /* For Regular and ReTxBSR Expiry Triggers */
#define NR_BSR_TRIGGER_PERIODIC (2) /* For BSR Periodic Timer Expiry Trigger */
#define NR_BSR_TRIGGER_PADDING (4) /* For Padding BSR Trigger */
// For both DL/UL-SCH
// Except:
// - UL/DL-SCH: fixed-size MAC CE(known by LCID)
......
This diff is collapsed.
......@@ -68,6 +68,13 @@
// NR UE defs
// ==========
#define NR_BSR_TRIGGER_NONE (0) /* No BSR Trigger */
#define NR_BSR_TRIGGER_REGULAR (1) /* For Regular and ReTxBSR Expiry Triggers */
#define NR_BSR_TRIGGER_PERIODIC (2) /* For BSR Periodic Timer Expiry Trigger */
#define NR_BSR_TRIGGER_PADDING (4) /* For Padding BSR Trigger */
#define NR_INVALID_LCGID (NR_MAX_NUM_LCGID)
#define MAX_NUM_BWP_UE 5
#define NUM_SLOT_FRAME 10
......@@ -185,6 +192,7 @@ typedef struct {
long LCGID;
// Bj bucket usage per lcid
int32_t Bj;
NR_timer_t Bj_timer;
} NR_LC_SCHEDULING_INFO;
typedef struct {
......@@ -200,18 +208,20 @@ typedef struct {
NR_LC_SCHEDULING_INFO lc_sched_info[NR_MAX_NUM_LCID];
// lcg scheduling info
NR_LCG_SCHEDULING_INFO lcg_sched_info[NR_MAX_NUM_LCGID];
/// BSR report flag management
uint8_t BSR_reporting_active;
// LCID triggering BSR
NR_LogicalChannelIdentity_t regularBSR_trigger_lcid;
/// SR pending as defined in 38.321
uint8_t SR_pending;
/// SR_COUNTER as defined in 38.321
uint16_t SR_COUNTER;
/// retxBSR-Timer, default value is sf2560
uint16_t retxBSR_Timer;
/// retxBSR_SF, number of subframe before triggering a regular BSR
uint16_t retxBSR_SF;
/// periodicBSR-Timer, default to infinity
uint16_t periodicBSR_Timer;
/// periodicBSR_SF, number of subframe before triggering a periodic BSR
uint16_t periodicBSR_SF;
// logicalChannelSR-DelayTimer
NR_timer_t sr_DelayTimer;
/// retxBSR-Timer
NR_timer_t retxBSR_Timer;
/// periodicBSR-Timer
NR_timer_t periodicBSR_Timer;
/// default value is 0: not configured
uint16_t sr_ProhibitTimer;
/// sr ProhibitTime running
......@@ -231,10 +241,6 @@ typedef struct {
int16_t prohibitPHR_SF;
///DL Pathloss Change in db
uint16_t PathlossChange_db;
/// default value is false
uint16_t extendedBSR_Sizes_r10;
/// default value is false
uint16_t extendedPHR_r10;
} NR_UE_SCHEDULING_INFO;
typedef enum {
......@@ -441,9 +447,11 @@ typedef struct nr_lcordered_info_s {
// logical channels ids ordered as per priority
NR_LogicalChannelIdentity_t lcid;
long priority;
long prioritisedBitRate;
uint32_t pbr; // in B/s (UINT_MAX = infinite)
// Bucket size per lcid
uint32_t bucket_size;
bool sr_DelayTimerApplied;
bool lc_SRMask;
} nr_lcordered_info_t;
......@@ -521,9 +529,6 @@ typedef struct NR_UE_MAC_INST_s {
nr_phy_config_t phy_config;
nr_synch_request_t synch_request;
/// BSR report flag management
uint8_t BSR_reporting_active;
// order lc info
A_SEQUENCE_OF(nr_lcordered_info_t) lc_ordered_list;
......
......@@ -47,6 +47,7 @@ void nr_ue_init_mac(NR_UE_MAC_INST_t *mac);
void send_srb0_rrc(int ue_id, const uint8_t *sdu, sdu_size_t sdu_len, void *data);
void update_mac_timers(NR_UE_MAC_INST_t *mac);
NR_LC_SCHEDULING_INFO *get_scheduling_info_from_lcid(NR_UE_MAC_INST_t *mac, NR_LogicalChannelIdentity_t lcid);
/**\brief apply default configuration values in nr_mac instance
\param mac mac instance */
......@@ -119,46 +120,6 @@ subframe number \param[in] slotP slot number
*/
int8_t nr_ue_get_SR(NR_UE_MAC_INST_t *mac, frame_t frameP, slot_t slotP);
/*! \fn nr_update_bsr
\brief get the rlc stats and update the bsr level for each lcid
\param[in] mac pointer to UE MAC instance
\param[in] frameP Frame index
\param[in] slotP number
\param[in] gNB_index
*/
bool nr_update_bsr(NR_UE_MAC_INST_t *mac, frame_t frameP, slot_t slotP, uint8_t gNB_index);
/*! \fn nr_locate_BsrIndexByBufferSize (int *table, int size, int value)
\brief locate the BSR level in the table as defined in 38.321. This function requires that he values in table to be monotonic, either increasing or decreasing. The returned value is not less than 0, nor greater than n-1, where n is the size of table.
\param[in] *table Pointer to BSR table
\param[in] size Size of the table
\param[in] value Value of the buffer
\return the index in the BSR_LEVEL table
*/
uint8_t nr_locate_BsrIndexByBufferSize(const uint32_t *table, int size,
int value);
/*! \fn int nr_get_pbr(long prioritizedbitrate)
\brief get the rate in kbps from the rate configured by the higher layer
\param[in] prioritizedbitrate
\return the rate in kbps
*/
uint32_t nr_get_pbr(long prioritizedbitrate);
/*! \fn int nr_get_sf_periodicBSRTimer(uint8_t periodicBSR_Timer)
\brief get the number of subframe from the periodic BSR timer configured by the higher layers
\param[in] periodicBSR_Timer timer for periodic BSR
\return the number of subframe
*/
int nr_get_sf_periodicBSRTimer(uint8_t bucketSize);
/*! \fn int nr_get_sf_retxBSRTimer(uint8_t retxBSR_Timer)
\brief get the number of subframe form the bucket size duration configured by the higher layer
\param[in] retxBSR_Timer timer for regular BSR
\return the time in sf
*/
int nr_get_sf_retxBSRTimer(uint8_t retxBSR_Timer);
int8_t nr_ue_process_dci(NR_UE_MAC_INST_t *mac,
int cc_id,
frame_t frame,
......@@ -413,6 +374,7 @@ int nr_config_pusch_pdu(NR_UE_MAC_INST_t *mac,
dci_pdu_rel15_t *dci,
RAR_grant_t *rar_grant,
uint16_t rnti,
int ss_type,
const nr_dci_format_t dci_format);
int nr_rrc_mac_config_req_sl_preconfig(module_id_t module_id,
......
......@@ -72,6 +72,9 @@ void nr_ue_init_mac(NR_UE_MAC_INST_t *mac)
mac->p_Max_alt = INT_MIN;
reset_mac_inst(mac);
// need to inizialize because might not been setup (optional timer)
nr_timer_stop(&mac->scheduling_info.sr_DelayTimer);
memset(&mac->ssb_measurements, 0, sizeof(mac->ssb_measurements));
memset(&mac->ul_time_alignment, 0, sizeof(mac->ul_time_alignment));
memset(mac->ssb_list, 0, sizeof(mac->ssb_list));
......@@ -81,8 +84,13 @@ void nr_ue_init_mac(NR_UE_MAC_INST_t *mac)
void nr_ue_mac_default_configs(NR_UE_MAC_INST_t *mac)
{
// default values as defined in 38.331 sec 9.2.2
mac->scheduling_info.retxBSR_Timer = NR_BSR_Config__retxBSR_Timer_sf80;
mac->scheduling_info.periodicBSR_Timer = NR_BSR_Config__periodicBSR_Timer_sf10;
// sf80 default for retxBSR_Timer sf10 for periodicBSR_Timer
int mu = mac->current_UL_BWP ? mac->current_UL_BWP->scs : get_softmodem_params()->numerology;
int subframes_per_slot = nr_slots_per_frame[mu] / 10;
nr_timer_setup(&mac->scheduling_info.retxBSR_Timer, 80 * subframes_per_slot, 1); // 1 slot update rate
nr_timer_setup(&mac->scheduling_info.periodicBSR_Timer, 10 * subframes_per_slot, 1); // 1 slot update rate
mac->scheduling_info.periodicPHR_Timer = NR_PHR_Config__phr_PeriodicTimer_sf10;
mac->scheduling_info.prohibitPHR_Timer = NR_PHR_Config__phr_ProhibitTimer_sf10;
}
......@@ -144,13 +152,20 @@ void reset_mac_inst(NR_UE_MAC_INST_t *nr_mac)
// initialize Bj for each logical channel to zero
// TODO reset also other status variables of LC, is this ok?
for (int i = 0; i < NR_MAX_NUM_LCID; i++) {
LOG_D(NR_MAC, "Applying default logical channel config for LCID %d\n", i);
nr_mac->scheduling_info.lc_sched_info[i].Bj = 0;
nr_mac->scheduling_info.lc_sched_info[i].LCID_buffer_with_data = false;
nr_mac->scheduling_info.lc_sched_info[i].LCID_buffer_remain = 0;
}
// TODO stop all running timers
for (int i = 0; i < NR_MAX_NUM_LCID; i++) {
nr_mac->scheduling_info.lc_sched_info[i].Bj = 0;
nr_timer_stop(&nr_mac->scheduling_info.lc_sched_info[i].Bj_timer);
}
nr_timer_stop(&nr_mac->ra.contention_resolution_timer);
nr_timer_stop(&nr_mac->scheduling_info.sr_DelayTimer);
nr_timer_stop(&nr_mac->scheduling_info.retxBSR_Timer);
// consider all timeAlignmentTimers as expired and perform the corresponding actions in clause 5.2
// TODO
......@@ -177,9 +192,7 @@ void reset_mac_inst(NR_UE_MAC_INST_t *nr_mac)
nr_mac->scheduling_info.sr_id = -1; // invalid init value
// cancel any triggered Buffer Status Reporting procedure
nr_mac->scheduling_info.periodicBSR_SF = NR_MAC_UE_BSR_TIMER_NOT_RUNNING;
nr_mac->scheduling_info.retxBSR_SF = NR_MAC_UE_BSR_TIMER_NOT_RUNNING;
nr_mac->BSR_reporting_active = NR_BSR_TRIGGER_NONE;
nr_mac->scheduling_info.BSR_reporting_active = NR_BSR_TRIGGER_NONE;
// cancel any triggered Power Headroom Reporting procedure
// TODO PHR not implemented yet
......
......@@ -86,26 +86,26 @@ void init_RA(NR_UE_MAC_INST_t *mac,
if (rach_ConfigDedicated) {
if (rach_ConfigDedicated->cfra){
LOG_I(MAC, "Initialization of 2-step contention-free random access procedure\n");
LOG_I(NR_MAC, "Initialization of 2-step contention-free random access procedure\n");
prach_resources->RA_TYPE = RA_2STEP;
ra->cfra = 1;
} else if (rach_ConfigDedicated->ext1){
if (rach_ConfigDedicated->ext1->cfra_TwoStep_r16){
LOG_I(MAC, "Setting RA type to 2-step...\n");
LOG_I(NR_MAC, "Setting RA type to 2-step...\n");
prach_resources->RA_TYPE = RA_2STEP;
ra->cfra = 1;
} else {
LOG_E(MAC, "Config not handled\n");
LOG_E(NR_MAC, "Config not handled\n");
}
} else {
LOG_E(MAC, "Config not handled\n");
LOG_E(NR_MAC, "Config not handled\n");
}
} else if (nr_rach_ConfigCommon){
LOG_I(MAC, "Initialization of 4-step contention-based random access procedure\n");
LOG_I(NR_MAC, "Initialization of 4-step contention-based random access procedure\n");
prach_resources->RA_TYPE = RA_4STEP;
ra->cfra = 0;
} else {
LOG_E(MAC, "Config not handled\n");
LOG_E(NR_MAC, "Config not handled\n");
}
switch (rach_ConfigGeneric->powerRampingStep){ // in dB
......
......@@ -189,10 +189,8 @@ int get_rnti_type(const NR_UE_MAC_INST_t *mac, const uint16_t rnti)
} else {
AssertFatal(1 == 0, "Not identified/handled rnti %d \n", rnti);
}
LOG_D(MAC, "Returning rnti_type %s \n", rnti_types(rnti_type));
return rnti_type;
LOG_D(MAC, "Returning rnti_type %s \n", rnti_types(rnti_type));
return rnti_type;
}
void nr_ue_decode_mib(NR_UE_MAC_INST_t *mac, int cc_id)
......@@ -447,7 +445,7 @@ static int nr_ue_process_dci_ul_00(NR_UE_MAC_INST_t *mac,
if (!pdu)
return -1;
int ret = nr_config_pusch_pdu(mac, &tda_info, &pdu->pusch_config_pdu, dci, NULL, dci_ind->rnti, NR_UL_DCI_FORMAT_0_0);
int ret = nr_config_pusch_pdu(mac, &tda_info, &pdu->pusch_config_pdu, dci, NULL, dci_ind->rnti, dci_ind->ss_type, NR_UL_DCI_FORMAT_0_0);
if (ret != 0)
remove_ul_config_last_item(pdu);
release_ul_config(pdu, false);
......@@ -520,7 +518,7 @@ static int nr_ue_process_dci_ul_01(NR_UE_MAC_INST_t *mac,
fapi_nr_ul_config_request_pdu_t *pdu = lockGet_ul_config(mac, frame_tx, slot_tx, FAPI_NR_UL_CONFIG_TYPE_PUSCH);
if (!pdu)
return -1;
int ret = nr_config_pusch_pdu(mac, &tda_info, &pdu->pusch_config_pdu, dci, NULL, dci_ind->rnti, NR_UL_DCI_FORMAT_0_1);
int ret = nr_config_pusch_pdu(mac, &tda_info, &pdu->pusch_config_pdu, dci, NULL, dci_ind->rnti, dci_ind->ss_type, NR_UL_DCI_FORMAT_0_1);
if (ret != 0)
remove_ul_config_last_item(pdu);
release_ul_config(pdu, false);
......@@ -664,6 +662,13 @@ static int nr_ue_process_dci_dl_10(NR_UE_MAC_INST_t *mac,
else
dlsch_pdu->dlDmrsScramblingId = mac->physCellId;
if (get_rnti_type(mac, dci_ind->rnti) == TYPE_C_RNTI_
&& dci_ind->ss_type != NR_SearchSpace__searchSpaceType_PR_common
&& pdsch_config->dataScramblingIdentityPDSCH)
dlsch_pdu->dlDataScramblingId = *pdsch_config->dataScramblingIdentityPDSCH;
else
dlsch_pdu->dlDataScramblingId = mac->physCellId;
/* dmrs symbol positions*/
dlsch_pdu->dlDmrsSymbPos = fill_dmrs_mask(pdsch_config,
NR_DL_DCI_FORMAT_1_0,
......@@ -975,6 +980,11 @@ static int nr_ue_process_dci_dl_11(NR_UE_MAC_INST_t *mac,
return -1;
}
if (pdsch_Config->dataScramblingIdentityPDSCH)
dlsch_pdu->dlDataScramblingId = *pdsch_Config->dataScramblingIdentityPDSCH;
else
dlsch_pdu->dlDataScramblingId = mac->physCellId;
dlsch_pdu->dmrsConfigType = dl_dmrs_config->dmrs_Type == NULL ? NFAPI_NR_DMRS_TYPE1 : NFAPI_NR_DMRS_TYPE2;
/* TODO: fix number of DM-RS CDM groups without data according to subclause 5.1.6.2 of 3GPP TS 38.214,
......@@ -2511,8 +2521,7 @@ int8_t nr_ue_get_SR(NR_UE_MAC_INST_t *mac, frame_t frameP, slot_t slot)
// release all pucch resource
//mac->physicalConfigDedicated = NULL; // todo
//mac->ul_active = 0; // todo
mac->BSR_reporting_active =
NR_BSR_TRIGGER_NONE;
si->BSR_reporting_active = NR_BSR_TRIGGER_NONE;
LOG_I(NR_MAC, "[UE %d] Release all SRs \n", mac->ue_id);
}
si->SR_pending = 0;
......@@ -3980,7 +3989,14 @@ static void nr_ue_process_rar(NR_UE_MAC_INST_t *mac, nr_downlink_indication_t *d
if (!pdu)
return;
// Config Msg3 PDU
int ret = nr_config_pusch_pdu(mac, &tda_info, &pdu->pusch_config_pdu, NULL, &rar_grant, rnti, NR_DCI_NONE);
int ret = nr_config_pusch_pdu(mac,
&tda_info,
&pdu->pusch_config_pdu,
NULL,
&rar_grant,
rnti,
NR_SearchSpace__searchSpaceType_PR_common,
NR_DCI_NONE);
if (ret != 0)
remove_ul_config_last_item(pdu);
release_ul_config(pdu, false);
......
This diff is collapsed.
......@@ -241,7 +241,7 @@ void gNB_dlsch_ulsch_scheduler(module_id_t module_idP, frame_t frame, sub_frame_
}
if ((slot == 0) && (frame & 127) == 0) {
char stats_output[16000] = {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);
}
......
......@@ -875,6 +875,9 @@ static void nr_fr1_dlsch_preprocessor(module_id_t module_id, frame_t frame, sub_
int average_agg_level = 4; // TODO find a better estimation
int max_sched_ues = 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);
/* proportional fair scheduling algorithm */
pf_dl(module_id,
frame,
......
......@@ -678,24 +678,24 @@ int get_mcs_from_bler(const NR_bler_options_t *bler_options,
return old_mcs; // no update
// last update is longer than x frames ago
const int dtx = (int)(stats->rounds[0] - bler_stats->rounds[0]);
const int dretx = (int)(stats->rounds[1] - bler_stats->rounds[1]);
const float bler_window = dtx > 0 ? (float) dretx / dtx : bler_stats->bler;
const int num_dl_sched = (int)(stats->rounds[0] - bler_stats->rounds[0]);
const int num_dl_retx = (int)(stats->rounds[1] - bler_stats->rounds[1]);
const float bler_window = num_dl_sched > 0 ? (float) num_dl_retx / num_dl_sched : bler_stats->bler;
bler_stats->bler = BLER_FILTER * bler_stats->bler + (1 - BLER_FILTER) * bler_window;
int new_mcs = old_mcs;
if (bler_stats->bler < bler_options->lower && old_mcs < max_mcs && dtx > 9)
if (bler_stats->bler < bler_options->lower && old_mcs < max_mcs && num_dl_sched > 3)
new_mcs += 1;
else if ((bler_stats->bler > bler_options->upper && old_mcs > 6) // above threshold
|| (dtx <= 3 && old_mcs > 9)) // no activity
|| (num_dl_sched <= 3 && old_mcs > 9)) // no activity
new_mcs -= 1;
// else we are within threshold boundaries
bler_stats->last_frame = frame;
bler_stats->mcs = new_mcs;
memcpy(bler_stats->rounds, stats->rounds, sizeof(stats->rounds));
LOG_D(MAC, "frame %4d MCS %d -> %d (dtx %d, dretx %d, BLER wnd %.3f avg %.6f)\n",
frame, old_mcs, new_mcs, dtx, dretx, bler_window, bler_stats->bler);
LOG_D(MAC, "frame %4d MCS %d -> %d (num_dl_sched %d, num_dl_retx %d, BLER wnd %.3f avg %.6f)\n",
frame, old_mcs, new_mcs, num_dl_sched, num_dl_retx, bler_window, bler_stats->bler);
return new_mcs;
}
......
......@@ -1109,7 +1109,8 @@ void handle_nr_uci_pucch_2_3_4(module_id_t mod_id,
}
free(uci_234->harq.harq_payload);
}
if ((uci_234->pduBitmap >> 2) & 0x01) {
/* phy-test has hardcoded allocation, so no use to handle CSI reports */
if ((uci_234->pduBitmap >> 2) & 0x01 && !get_softmodem_params()->phy_test) {
//API to parse the csi report and store it into sched_ctrl
extract_pucch_csi_report(csi_MeasConfig, uci_234, frame, slot, UE, nrmac->common_channels->ServingCellConfigCommon);
//TCI handling function
......
......@@ -2035,6 +2035,9 @@ static bool nr_fr1_ulsch_preprocessor(module_id_t module_id, frame_t frame, sub_
int average_agg_level = 4; // TODO find a better estimation
int max_sched_ues = 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);
/* proportional fair scheduling algorithm */
pf_ul(module_id,
frame,
......
......@@ -45,7 +45,7 @@
extern RAN_CONTEXT_t RC;
#define MACSTATSSTRLEN 16000
#define MACSTATSSTRLEN 36256
void *nrmac_stats_thread(void *arg) {
......
......@@ -41,10 +41,8 @@
#include <asn_application.h>
#include "RRC/NR/nr_rrc_defs.h"
#include "RRC/NR/nr_rrc_config.h"
/*
* The variant of the above function which dumps the BASIC-XER (XER_F_BASIC)
* output into the chosen string buffer.
......
......@@ -50,7 +50,21 @@ static void ue_context_setup_request_f1ap(sctp_assoc_t assoc_id, const f1ap_ue_c
msg->ittiMsgHeader.originInstance = assoc_id;
f1ap_ue_context_setup_t *f1ap_msg = &F1AP_UE_CONTEXT_SETUP_REQ(msg);
*f1ap_msg = *req;
AssertFatal(req->cu_to_du_rrc_information == NULL, "cu_to_du_rrc_information not supported yet\n");
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);
}
}
if (req->drbs_to_be_setup_length > 0) {
int n = req->drbs_to_be_setup_length;
f1ap_msg->drbs_to_be_setup_length = n;
......
......@@ -616,7 +616,7 @@ static void nr_rrc_handle_msg3_indication(NR_UE_RRC_INST_t *rrc, rnti_t rnti)
{
NR_UE_Timers_Constants_t *tac = &rrc->timers_and_constants;
switch (rrc->ra_trigger) {
case INITIAL_ACCESS_FROM_RRC_IDLE:
case RRC_CONNECTION_SETUP:
// After SIB1 is received, prepare RRCConnectionRequest
rrc->rnti = rnti;
// start timer T300
......@@ -744,7 +744,7 @@ static int8_t nr_rrc_ue_decode_NR_BCCH_DL_SCH_Message(NR_UE_RRC_INST_t *rrc,
LOG_A(NR_RRC, "SIB1 decoded\n");
nr_timer_start(&SI_info->sib1_timer);
if (rrc->nrRrcState == RRC_STATE_IDLE_NR) {
rrc->ra_trigger = INITIAL_ACCESS_FROM_RRC_IDLE;
rrc->ra_trigger = RRC_CONNECTION_SETUP;
// preparing RRC setup request payload in advance
nr_rrc_ue_prepare_RRCSetupRequest(rrc);
}
......@@ -2221,6 +2221,9 @@ void nr_rrc_going_to_IDLE(NR_UE_RRC_INST_t *rrc,
void handle_t300_expiry(NR_UE_RRC_INST_t *rrc)
{
rrc->ra_trigger = RRC_CONNECTION_SETUP;
nr_rrc_ue_prepare_RRCSetupRequest(rrc);
// reset MAC, release the MAC configuration
NR_UE_MAC_reset_cause_t cause = T300_EXPIRY;
nr_rrc_mac_config_req_reset(rrc->ue_id, cause);
......
......@@ -105,7 +105,7 @@ typedef enum requested_SI_List_e {
// 3GPP TS 38.300 Section 9.2.6
typedef enum RA_trigger_e {
RA_NOT_RUNNING,
INITIAL_ACCESS_FROM_RRC_IDLE,
RRC_CONNECTION_SETUP,
RRC_CONNECTION_REESTABLISHMENT,
DURING_HANDOVER,
NON_SYNCHRONISED,
......
......@@ -1038,7 +1038,7 @@ static void rfsimulator_end(openair0_device *device) {
for (int i = 0; i < MAX_FD_RFSIMU; i++) {
buffer_t *b = &s->buf[i];
if (b->conn_sock >= 0 )
close(b->conn_sock);
removeCirBuf(s, b->conn_sock);
}
close(s->epollfd);
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment