From 9fce798a0ee768caa3c4a62470a97e8d44ad169c Mon Sep 17 00:00:00 2001 From: Shruthi Date: Wed, 3 Mar 2021 23:09:02 +0530 Subject: [PATCH 01/91] Fixed errors in nFAPI after first merge --- executables/nr-gnb.c | 40 +- executables/nr-ru.c | 32 +- executables/nr-ru_Original.c | 2514 +++++++++++++++++ nfapi/oai_integration/nfapi_pnf.c | 2 + nfapi/open-nFAPI/nfapi/src/nfapi_p7.c | 16 +- nfapi/open-nFAPI/pnf/src/pnf_p7.c | 5 +- nfapi/open-nFAPI/vnf/src/vnf_p7.c | 1 + openair1/PHY/NR_TRANSPORT/nr_dlsch_tools.c | 22 +- .../PHY/NR_UE_TRANSPORT/nr_dlsch_decoding.c | 4 +- openair1/SCHED_NR/fapi_nr_l1.c | 31 +- openair1/SCHED_NR/phy_frame_config_nr.c | 2 +- openair1/SCHED_NR/phy_procedures_nr_gNB.c | 1 + openair1/SCHED_NR_UE/fapi_nr_ue_l1.c | 1 + openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c | 26 +- .../LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c | 16 +- .../NR_MAC_gNB/gNB_scheduler_primitives.c | 1 + .../LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c | 11 + .../LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c | 3 + openair2/NR_PHY_INTERFACE/NR_IF_Module.c | 10 +- 19 files changed, 2682 insertions(+), 56 deletions(-) create mode 100644 executables/nr-ru_Original.c diff --git a/executables/nr-gnb.c b/executables/nr-gnb.c index cd1bfd14b6..8ed4ac2e1c 100644 --- a/executables/nr-gnb.c +++ b/executables/nr-gnb.c @@ -252,8 +252,25 @@ static inline int rxtx(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx, int frame_t pthread_mutex_unlock(&gNB->UL_INFO_mutex); // RX processing - int tx_slot_type = nr_slot_select(cfg,frame_tx,slot_tx); - int rx_slot_type = nr_slot_select(cfg,frame_rx,slot_rx); + int tx_slot_type; int rx_slot_type; + if(NFAPI_MODE == NFAPI_MODE_VNF) { + if ((slot_tx==8) || (slot_rx==8) || (slot_tx==9) || (slot_rx==9) || (slot_tx==18) || (slot_rx==18) || (slot_tx==19) || (slot_rx==19)) { + tx_slot_type = NR_UPLINK_SLOT; + rx_slot_type = NR_UPLINK_SLOT; + } + else if ((slot_tx==7) || (slot_rx==7) || (slot_tx==17) || (slot_rx==17)) { + tx_slot_type = NR_MIXED_SLOT; + rx_slot_type = NR_MIXED_SLOT; + } + else { + tx_slot_type = NR_DOWNLINK_SLOT; + rx_slot_type = NR_DOWNLINK_SLOT; + } + } + else { + tx_slot_type = nr_slot_select(cfg,frame_tx,slot_tx); + rx_slot_type = nr_slot_select(cfg,frame_rx,slot_rx); + } if (rx_slot_type == NR_UPLINK_SLOT || rx_slot_type == NR_MIXED_SLOT) { // UE-specific RX processing for subframe n @@ -400,15 +417,21 @@ static void *gNB_L1_thread( void *param ) { while (!oai_exit) { - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_gNB_PROC_RXTX0, 0 ); - if (wait_on_condition(&L1_proc->mutex,&L1_proc->cond,&L1_proc->instance_cnt,thread_name)<0) break; - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_gNB_PROC_RXTX0, 1 ); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_gNB_PROC_RXTX0, 0 ); int frame_rx = L1_proc->frame_rx; int slot_rx = L1_proc->slot_rx; int frame_tx = L1_proc->frame_tx; int slot_tx = L1_proc->slot_tx; uint64_t timestamp_tx = L1_proc->timestamp_tx; + if(NFAPI_MODE==NFAPI_MODE_VNF) + if (gNB->CC_id==0) { + int next_slot; + next_slot = (slot_rx + 1) % 20; + if (rxtx(gNB,frame_rx,next_slot,frame_tx,next_slot,thread_name) < 0) break + } + if (wait_on_condition(&L1_proc->mutex,&L1_proc->cond,&L1_proc->instance_cnt,thread_name)<0) break; + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_gNB_PROC_RXTX0, 1 ); VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_SLOT_NUMBER_TX0_GNB,slot_tx); @@ -422,9 +445,12 @@ static void *gNB_L1_thread( void *param ) { if (rxtx(gNB,frame_rx,slot_rx,frame_tx,slot_tx,thread_name) < 0) break; } + clock_gettime(CLOCK_MONOTONIC,&t); + //printf("\n %d.%d",t.tv_sec,t.tv_nsec); + if (release_thread(&L1_proc->mutex,&L1_proc->instance_cnt,thread_name)<0) break; - - if(get_thread_parallel_conf() == PARALLEL_RU_L1_TRX_SPLIT) wakeup_tx(gNB,frame_rx,slot_rx,frame_tx,slot_tx,timestamp_tx); + + if (get_thread_parallel_conf() == PARALLEL_RU_L1_TRX_SPLIT) wakeup_tx(gNB,frame_rx,slot_rx,frame_tx,slot_tx,timestamp_tx); else if(get_thread_parallel_conf() == PARALLEL_RU_L1_SPLIT) wakeup_txfh(gNB,L1_proc,frame_tx,slot_tx,timestamp_tx); } // while !oai_exit diff --git a/executables/nr-ru.c b/executables/nr-ru.c index 73421d8ed7..1184a9d80c 100644 --- a/executables/nr-ru.c +++ b/executables/nr-ru.c @@ -97,7 +97,8 @@ static int DEFBFW[] = {0x00007fff}; extern volatile int oai_exit; - +extern struct timespec timespec_sub(struct timespec lhs, struct timespec rhs); +extern struct timespec timespec_add(struct timespec lhs, struct timespec rhs); extern void nr_phy_free_RU(RU_t *); extern void nr_phy_config_request(NR_PHY_Config_t *gNB); #include "executables/thread-common.h" @@ -710,6 +711,7 @@ void rx_rf(RU_t *ru,int *frame,int *slot) { void tx_rf(RU_t *ru,int frame,int slot, uint64_t timestamp) { + RU_proc_t *proc = &ru->proc; NR_DL_FRAME_PARMS *fp = ru->nr_frame_parms; nfapi_nr_config_request_scf_t *cfg = &ru->config; @@ -1541,9 +1543,35 @@ void *ru_thread( void *param ) { pthread_cond_signal(&proc->cond_FH1); // 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); + + struct timespec slot_duration; + slot_duration.tv_sec = 0; + //slot_duration.tv_nsec = 0.5e6; + slot_duration.tv_nsec = 0.5e6; + + + while (!oai_exit) { // these are local subframe/frame counters to check that we are in synch with the fronthaul timing. // They are set on the first rx/tx in the underly FH routines. + slot_start = timespec_add(slot_start,slot_duration); + struct timespec curr_time; + clock_gettime(CLOCK_MONOTONIC, &curr_time); + + struct timespec sleep_time; + + if((slot_start.tv_sec > curr_time.tv_sec) || (slot_start.tv_sec == curr_time.tv_sec && slot_start.tv_nsec > curr_time.tv_nsec)){ + sleep_time = timespec_sub(slot_start,curr_time); + + usleep(sleep_time.tv_nsec * 1e-3); + } + else{//continue + } + + // clock_gettime(CLOCK_MONOTONIC, &curr_time); + //printf("sfn:%d, slot:%d, start time %d.%d slot start %d.%d \n",frame,slot,curr_time.tv_sec,curr_time.tv_nsec,slot_start.tv_sec,slot_start.tv_nsec); if (slot==(fp->slots_per_frame-1)) { slot=0; frame++; @@ -1562,7 +1590,7 @@ void *ru_thread( void *param ) { proc->frame_rx,proc->tti_rx, proc->frame_tx,proc->tti_tx, RC.gNB[0]->proc.frame_rx,RC.gNB[0]->proc.slot_rx, - RC.gNB[0]->proc.frame_tx); + RC.gNB[0]->proc.frame_tx); /* LOG_D(PHY,"RU thread (do_prach %d, is_prach_subframe %d), received frame %d, subframe %d\n", ru->do_prach, diff --git a/executables/nr-ru_Original.c b/executables/nr-ru_Original.c new file mode 100644 index 0000000000..73421d8ed7 --- /dev/null +++ b/executables/nr-ru_Original.c @@ -0,0 +1,2514 @@ +/* + * 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 + */ + +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#undef MALLOC //there are two conflicting definitions, so we better make sure we don't use it at all + +#include "common/utils/assertions.h" +#include "common/utils/system.h" +#include "msc.h" + +#include "../../ARCH/COMMON/common_lib.h" +#include "../../ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.h" + +#include "PHY/LTE_TRANSPORT/if4_tools.h" +#include "PHY/LTE_TRANSPORT/if5_tools.h" + +#include "PHY/types.h" +#include "PHY/defs_nr_common.h" +#include "PHY/phy_extern.h" +#include "PHY/LTE_TRANSPORT/transport_proto.h" +#include "PHY/NR_TRANSPORT/nr_transport_proto.h" +#include "PHY/INIT/phy_init.h" +#include "SCHED/sched_eNB.h" +#include "SCHED_NR/sched_nr.h" + +#include "LAYER2/NR_MAC_COMMON/nr_mac_extern.h" +#include "RRC/LTE/rrc_extern.h" +#include "PHY_INTERFACE/phy_interface.h" + +#include "common/utils/LOG/log.h" +#include "common/utils/LOG/vcd_signal_dumper.h" + +#include "enb_config.h" +#include + +#ifdef SMBV +#include "PHY/TOOLS/smbv.h" +unsigned short config_frames[4] = {2,9,11,13}; +#endif + +/* these variables have to be defined before including ENB_APP/enb_paramdef.h and GNB_APP/gnb_paramdef.h */ +static int DEFBANDS[] = {7}; +static int DEFENBS[] = {0}; +static int DEFBFW[] = {0x00007fff}; + +//static int DEFNRBANDS[] = {7}; +//static int DEFGNBS[] = {0}; + +#include "ENB_APP/enb_paramdef.h" +#include "GNB_APP/gnb_paramdef.h" +#include "common/config/config_userapi.h" + +#ifndef OPENAIR2 + #include "UTIL/OTG/otg_extern.h" +#endif + +#include "s1ap_eNB.h" +#include "SIMULATION/ETH_TRANSPORT/proto.h" + + + +#include "T.h" +#include "nfapi_interface.h" + +extern volatile int oai_exit; + + +extern void nr_phy_free_RU(RU_t *); +extern void nr_phy_config_request(NR_PHY_Config_t *gNB); +#include "executables/thread-common.h" +//extern PARALLEL_CONF_t get_thread_parallel_conf(void); +//extern WORKER_CONF_t get_thread_worker_conf(void); + +void init_NR_RU(char *); +void stop_RU(int nb_ru); +void do_ru_sync(RU_t *ru); + +void configure_ru(int idx, void *arg); +void configure_rru(int idx, void *arg); +int attach_rru(RU_t *ru); +int connect_rau(RU_t *ru); + +uint16_t sf_ahead; +uint16_t slot_ahead; +uint16_t sl_ahead; + +extern int emulate_rf; +extern int numerology; +extern int usrp_tx_thread; + +/*************************************************************/ +/* Functions to attach and configure RRU */ + +extern void wait_gNBs(void); + +int attach_rru(RU_t *ru) +{ + ssize_t msg_len,len; + 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; + LOG_I(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); + + // wait for answer with timeout + if ((len = ru->ifdevice.trx_ctlrecv_func(&ru->ifdevice, + &rru_config_msg, + msg_len))<0) { + LOG_I(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]); + received_capabilities=1; + } else { + LOG_E(PHY,"Received incorrect message %d from RRU %d\n",rru_config_msg.type,ru->idx); + } + } + + configure_ru(ru->idx, + (RRU_capabilities_t *)&rru_config_msg.msg[0]); + 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]); + 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) { + 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"); + } else { + LOG_E(PHY,"Received incorrect message %d from RRU %d\n",rru_config_msg.type,ru->idx); + } + + return 0; +} + +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; + + // wait for RAU_tick + 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) { + 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); + } + } + + // 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); + + switch (ru->function) { + case NGFI_RRU_IF4p5: + cap->FH_fmt = OAI_IF4p5_only; + break; + + case NGFI_RRU_IF5: + cap->FH_fmt = OAI_IF5_only; + break; + + case MBP_RRU_IF5: + cap->FH_fmt = MBP_IF5; + break; + + default: + AssertFatal(1==0,"RU_function is unknown %d\n",RC.ru[0]->function); + break; + } + + cap->num_bands = ru->num_bands; + + for (i=0; inum_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]; + cap->nb_rx[i] = ru->nb_rx; + cap->nb_tx[i] = ru->nb_tx; + cap->max_pdschReferenceSignalPower[i] = ru->max_pdschReferenceSignalPower; + cap->max_rxgain[i] = ru->max_rxgain; + } + + AssertFatal((ru->ifdevice.trx_ctlsend_func(&ru->ifdevice,&rru_config_msg,rru_config_msg.len)!=-1), + "RU %d failed send capabilities to RAU\n",ru->idx); + // wait for configuration + rru_config_msg.len = sizeof(RRU_CONFIG_msg_t)-MAX_RRU_CONFIG_SIZE+sizeof(RRU_config_t); + + while (configuration_received == 0) { + if ((len = ru->ifdevice.trx_ctlrecv_func(&ru->ifdevice, + &rru_config_msg, + rru_config_msg.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->idx, + (void *)&rru_config_msg.msg[0]); + configuration_received = 1; + } + } + + return 0; +} +/*************************************************************/ +/* Southbound Fronthaul functions, RCC/RAU */ + +// 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 ); + + send_IF5(ru, timestamp, slot, &ru->seqno, IF5_RRH_GW_DL); +} + +// 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 ); + + 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) + send_IF4p5(ru,frame, slot, IF4p5_PDLFFT); +} + +/*************************************************************/ +/* Input Fronthaul from south RCC/RAU */ + +// Synchronous if5 from south +void fh_if5_south_in(RU_t *ru, + int *frame, + int *tti) +{ + NR_DL_FRAME_PARMS *fp = ru->nr_frame_parms; + RU_proc_t *proc = &ru->proc; + recv_IF5(ru, &proc->timestamp_rx, *tti, IF5_RRH_GW_UL); + proc->frame_rx = (proc->timestamp_rx / (fp->samples_per_subframe*10))&1023; + uint32_t idx_sf = proc->timestamp_rx / fp->samples_per_subframe; + proc->tti_rx = (idx_sf * fp->slots_per_subframe + (int)round((float)(proc->timestamp_rx % fp->samples_per_subframe) / fp->samples_per_slot0))%(fp->slots_per_frame); + + if (proc->first_rx == 0) { + if (proc->tti_rx != *tti) { + LOG_E(PHY,"Received Timestamp doesn't correspond to the time we think it is (proc->tti_rx %d, subframe %d)\n",proc->tti_rx,*tti); + exit_fun("Exiting"); + } + + if (proc->frame_rx != *frame) { + LOG_E(PHY,"Received Timestamp doesn't correspond to the time we think it is (proc->frame_rx %d frame %d)\n",proc->frame_rx,*frame); + exit_fun("Exiting"); + } + } else { + proc->first_rx = 0; + *frame = proc->frame_rx; + *tti = proc->tti_rx; + } + + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TS, proc->timestamp_rx&0xffffffff ); +} + +// Synchronous if4p5 from south +void fh_if4p5_south_in(RU_t *ru, + int *frame, + int *slot) +{ + NR_DL_FRAME_PARMS *fp = ru->nr_frame_parms; + RU_proc_t *proc = &ru->proc; + int f,sl; + uint16_t packet_type; + 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) && (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) { + // nothing in RU for RAU + } + + LOG_D(PHY,"rx_fh_if4p5: subframe %d symbol mask %x\n",*slot,proc->symbol_mask[sl]); + } while(proc->symbol_mask[sl] != symbol_mask_full); + + //caculate timestamp_rx, timestamp_tx based on frame and subframe + proc->tti_rx = sl; + proc->frame_rx = f; + 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+(fp->slots_per_subframe*sf_ahead))%fp->slots_per_frame; + proc->frame_tx = (sl>(fp->slots_per_frame-1-(fp->slots_per_subframe*sf_ahead))) ? (f+1)&1023 : f; + + if (proc->first_rx == 0) { + if (proc->tti_rx != *slot) { + LOG_E(PHY,"Received Timestamp (IF4p5) doesn't correspond to the time we think it is (proc->tti_rx %d, subframe %d)\n",proc->tti_rx,*slot); + exit_fun("Exiting"); + } + + if (proc->frame_rx != *frame) { + LOG_E(PHY,"Received Timestamp (IF4p5) doesn't correspond to the time we think it is (proc->frame_rx %d frame %d)\n",proc->frame_rx,*frame); + exit_fun("Exiting"); + } + } else { + proc->first_rx = 0; + *frame = proc->frame_rx; + *slot = proc->tti_rx; + } + + if (ru == RC.ru[0]) { + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_RX0_RU, f ); + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TTI_NUMBER_RX0_RU, sl); + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_TX0_RU, proc->frame_tx ); + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TTI_NUMBER_TX0_RU, proc->tti_tx ); + } + + proc->symbol_mask[proc->tti_rx] = 0; + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TS, proc->timestamp_rx&0xffffffff ); + LOG_D(PHY,"RU %d: fh_if4p5_south_in sleeping ...\n",ru->idx); +} + +// asynchronous inbound if4p5 fronthaul from south +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; + + 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; + proc->first_rx = 0; + } else { + if (proc->frame_rx != *frame) { + 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 +} + + + + + +/*************************************************************/ +/* Input Fronthaul from North RRU */ + +// RRU IF4p5 TX fronthaul receiver. Assumes an if_device on input and if or rf device on output +// receives one subframe's worth of IF4p5 OFDM symbols and OFDM modulates +void fh_if4p5_north_in(RU_t *ru,int *frame,int *slot) { + uint32_t symbol_number=0; + uint32_t symbol_mask, symbol_mask_full; + uint16_t packet_type; + /// **** incoming IF4p5 from remote RCC/RAU **** /// + symbol_number = 0; + symbol_mask = 0; + symbol_mask_full = (1<<(ru->nr_frame_parms->symbols_per_slot))-1; + + do { + recv_IF4p5(ru, frame, slot, &packet_type, &symbol_number); + symbol_mask = symbol_mask | (1<nr_frame_parms; + RU_proc_t *proc = &ru->proc; + int tti_tx,frame_tx; + openair0_timestamp timestamp_tx; + recv_IF5(ru, ×tamp_tx, *slot, IF5_RRH_GW_DL); + // printf("Received subframe %d (TS %llu) from RCC\n",tti_tx,timestamp_tx); + 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) { + NR_DL_FRAME_PARMS *fp = ru->nr_frame_parms; + 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; + int slot_tx,frame_tx; + LOG_D(PHY, "%s(ru:%p frame, subframe)\n", __FUNCTION__, ru); + symbol_number = 0; + 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); + + 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); + + if (proc->first_tx != 0) { + *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); + AssertFatal(slot_tx == *slot, + "slot_tx %d is not what we expect %d\n",slot_tx,*slot); + } + + if (packet_type == IF4p5_PDLFFT) { + symbol_mask = symbol_mask | (1<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; + + 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); + + // dump VCD output for first RU in list + if (ru == RC.ru[0]) { + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_TX0_RU, frame_tx ); + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TTI_NUMBER_TX0_RU, slot_tx ); + } + + if (ru->feptx_ofdm) ru->feptx_ofdm(ru,frame_tx,slot_tx); + + if (ru->fh_south_out) ru->fh_south_out(ru,frame_tx,slot_tx,proc->timestamp_tx); +} + +void fh_if5_north_out(RU_t *ru) { + RU_proc_t *proc=&ru->proc; + uint8_t seqno=0; + /// **** send_IF5 of rxdata to BBU **** /// + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_SEND_IF5, 1 ); + send_IF5(ru, proc->timestamp_rx, proc->tti_rx, &seqno, IF5_RRH_GW_UL); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_SEND_IF5, 0 ); +} + +// RRU IF4p5 northbound interface (RX) +void fh_if4p5_north_out(RU_t *ru) { + RU_proc_t *proc=&ru->proc; + + //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); +} + +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; +} + +void rx_rf(RU_t *ru,int *frame,int *slot) { + RU_proc_t *proc = &ru->proc; + NR_DL_FRAME_PARMS *fp = ru->nr_frame_parms; + void *rxp[ru->nb_rx]; + unsigned int rxs; + int i; + uint32_t samples_per_slot = fp->get_samples_per_slot(*slot,fp); + uint32_t samples_per_slot_prev ; + openair0_timestamp ts,old_ts; + AssertFatal(*slotslots_per_frame && *slot>=0, "slot %d is illegal (%d)\n",*slot,fp->slots_per_frame); + + for (i=0; inb_rx; i++) + rxp[i] = (void *)&ru->common.rxdata[i][fp->get_samples_slot_timestamp(*slot,fp,0)]; + + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ, 1 ); + old_ts = proc->timestamp_rx; + LOG_D(PHY,"Reading %d samples for slot %d (%p)\n",samples_per_slot,*slot,rxp[0]); + + 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, + ru->nb_rx); + } + + + 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); + + if (proc->first_rx == 1) { + ru->ts_offset = proc->timestamp_rx; + proc->timestamp_rx = 0; + } else { + samples_per_slot_prev = fp->get_samples_per_slot((*slot-1)%fp->slots_per_frame,fp); + if (proc->timestamp_rx - old_ts != samples_per_slot_prev) { + LOG_D(PHY,"rx_rf: rfdevice timing drift of %"PRId64" samples (ts_off %"PRId64")\n",proc->timestamp_rx - old_ts - samples_per_slot_prev,ru->ts_offset); + ru->ts_offset += (proc->timestamp_rx - old_ts - samples_per_slot_prev); + proc->timestamp_rx = ts-ru->ts_offset; + } + } + + 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 %llu (off %d), frame %d, slot %d.%d / %d\n", + ru->idx, + 0, + (unsigned long long int)proc->timestamp_rx, + (int)ru->ts_offset,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]) { + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_RX0_RU, proc->frame_rx ); + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TTI_NUMBER_RX0_RU, proc->tti_rx ); + } + + 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); + 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, slot %d)\n",(long long unsigned int)proc->timestamp_rx,proc->frame_rx,*frame,proc->tti_rx,*slot); + exit_fun("Exiting"); + } + } else { + proc->first_rx = 0; + *frame = proc->frame_rx; + *slot = proc->tti_rx; + } + + //printf("timestamp_rx %lu, frame %d(%d), subframe %d(%d)\n",ru->timestamp_rx,proc->frame_rx,frame,proc->tti_rx,subframe); + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TS, proc->timestamp_rx&0xffffffff ); + + if (rxs != samples_per_slot) { + //exit_fun( "problem receiving samples" ); + LOG_E(PHY, "problem receiving samples\n"); + } +} + + +void tx_rf(RU_t *ru,int frame,int slot, uint64_t timestamp) { + RU_proc_t *proc = &ru->proc; + NR_DL_FRAME_PARMS *fp = ru->nr_frame_parms; + nfapi_nr_config_request_scf_t *cfg = &ru->config; + void *txp[ru->nb_tx]; + unsigned int txs; + int i,txsymb; + T(T_ENB_PHY_OUTPUT_SIGNAL, T_INT(0), T_INT(0), T_INT(frame), T_INT(slot), + T_INT(0), T_BUFFER(&ru->common.txdata[0][fp->get_samples_slot_timestamp(slot,fp,0)], fp->samples_per_subframe * 4)); + + int slot_type = nr_slot_select(cfg,frame,slot%fp->slots_per_frame); + int prevslot_type = nr_slot_select(cfg,frame,(slot+(fp->slots_per_frame-1))%fp->slots_per_frame); + int nextslot_type = nr_slot_select(cfg,frame,(slot+1)%fp->slots_per_frame); + int sf_extension = 0; //sf_extension = ru->sf_extension; + int siglen=fp->get_samples_per_slot(slot,fp); + int flags=1; + + //nr_subframe_t SF_type = nr_slot_select(cfg,slot%fp->slots_per_frame); + if (slot_type == NR_DOWNLINK_SLOT || slot_type == NR_MIXED_SLOT || IS_SOFTMODEM_RFSIM) { + + if (cfg->cell_config.frame_duplex_type.value == TDD){ + if(slot_type == NR_MIXED_SLOT) { + txsymb = 0; + for(int symbol_count = 0; symbol_counttdd_table.max_tdd_periodicity_list[slot].max_num_of_symbol_per_slot_list[symbol_count].slot_config.value == 0) + txsymb++; + } + AssertFatal(txsymb>0,"illegal txsymb %d\n",txsymb); + if(slot%(fp->slots_per_subframe/2)) + siglen = txsymb * (fp->ofdm_symbol_size + fp->nb_prefix_samples); + else + siglen = (fp->ofdm_symbol_size + fp->nb_prefix_samples0) + (txsymb - 1) * (fp->ofdm_symbol_size + fp->nb_prefix_samples); + //+ ru->end_of_burst_delay; + flags = 3; // end of burst + } + + if (slot_type == NR_DOWNLINK_SLOT && prevslot_type == NR_UPLINK_SLOT) + flags = 2; // start of burst + + if (slot_type == NR_DOWNLINK_SLOT && nextslot_type == NR_UPLINK_SLOT) + flags = 3; // end of burst + } + + if (fp->freq_range==nr_FR2) { + // the beam index is written in bits 8-10 of the flags + // bit 11 enables the gpio programming + int beam=0; + //if (slot==0) beam = 11; //3 for boresight & 8 to enable + /* + if (slot==0 || slot==40) beam=0&8; + if (slot==10 || slot==50) beam=1&8; + if (slot==20 || slot==60) beam=2&8; + if (slot==30 || slot==70) beam=3&8; + */ + flags |= beam<<8; + } + + 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 ); + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TTI_NUMBER_TX0_RU, slot ); + for (i=0; inb_tx; i++) + txp[i] = (void *)&ru->common.txdata[i][fp->get_samples_slot_timestamp(slot,fp,0)-sf_extension]; + + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TST, (timestamp-ru->openair0_cfg.tx_sample_advance)&0xffffffff ); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE, 1 ); + // prepare tx buffer pointers + txs = ru->rfdevice.trx_write_func(&ru->rfdevice, + timestamp+ru->ts_offset-ru->openair0_cfg.tx_sample_advance-sf_extension, + txp, + siglen+sf_extension, + ru->nb_tx, + flags); + LOG_D(PHY,"[TXPATH] RU %d tx_rf, writing to TS %llu, frame %d, unwrapped_frame %d, slot %di, returned %d\n",ru->idx, + (long long unsigned int)timestamp,frame,proc->frame_tx_unwrap,slot, txs); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE, 0 ); + //AssertFatal(txs == 0,"trx write function error %d\n", txs); + } +} + + + +/*! + * \brief The Asynchronous RX/TX FH thread of RAU/RCC/gNB/RRU. + * This handles the RX FH for an asynchronous RRU/UE + * \param param is a \ref gNB_L1_proc_t structure which contains the info what to process. + * \returns a pointer to an int. The storage is not on the heap and must not be freed. + */ +void *ru_thread_asynch_rxtx( void *param ) { + static int ru_thread_asynch_rxtx_status; + RU_t *ru = (RU_t *)param; + RU_proc_t *proc = &ru->proc; + nfapi_nr_config_request_scf_t *cfg = &ru->config; + int slot=0, frame=0; + // wait for top-level synchronization and do one acquisition to get timestamp for setting frame/subframe + wait_sync("ru_thread_asynch_rxtx"); + // wait for top-level synchronization and do one acquisition to get timestamp for setting frame/subframe + printf( "waiting for devices (ru_thread_asynch_rx)\n"); + wait_on_condition(&proc->mutex_asynch_rxtx,&proc->cond_asynch_rxtx,&proc->instance_cnt_asynch_rxtx,"thread_asynch"); + printf( "devices ok (ru_thread_asynch_rx)\n"); + + while (!oai_exit) { + + if (slot==ru->nr_frame_parms->slots_per_frame) { + slot=0; + frame++; + frame&=1023; + } else { + slot++; + } + + LOG_D(PHY,"ru_thread_asynch_rxtx: Waiting on incoming fronthaul\n"); + + // asynchronous receive from north (RRU IF4/IF5) + if (ru->fh_north_asynch_in) { + if ((nr_slot_select(cfg,frame,slot) & NR_DOWNLINK_SLOT)>0) + ru->fh_north_asynch_in(ru,&frame,&slot); + } else AssertFatal(1==0,"Unknown function in ru_thread_asynch_rxtx\n"); + } + + ru_thread_asynch_rxtx_status=0; + return(&ru_thread_asynch_rxtx_status); +} + + + + +/*! + * \brief The prach receive thread of RU. + * \param param is a \ref RU_proc_t structure which contains the info what to process. + * \returns a pointer to an int. The storage is not on the heap and must not be freed. + */ +void *ru_thread_prach( void *param ) { + static int ru_thread_prach_status; + RU_t *ru = (RU_t *)param; + RU_proc_t *proc = (RU_proc_t *)&ru->proc; + // set default return value + ru_thread_prach_status = 0; + + while (RC.ru_mask>0) { + usleep(1e6); + LOG_I(PHY,"%s() RACH waiting for RU to be configured\n", __FUNCTION__); + } + + LOG_I(PHY,"%s() RU configured - RACH processing thread running\n", __FUNCTION__); + + while (!oai_exit) { + + + if (wait_on_condition(&proc->mutex_prach,&proc->cond_prach,&proc->instance_cnt_prach,"ru_prach_thread") < 0) break; + + /*VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_RU_PRACH_RX, 1 ); + + if (ru->gNB_list[0]){ + prach_procedures( + ru->gNB_list[0],0 + ); + } + else { + rx_prach(NULL, + ru, + NULL, + NULL, + NULL, + proc->frame_prach, + 0,0 + ); + } + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_RU_PRACH_RX, 0 );*/ + if (release_thread(&proc->mutex_prach,&proc->instance_cnt_prach,"ru_prach_thread") < 0) break; + } + + LOG_I(PHY, "Exiting RU thread PRACH\n"); + ru_thread_prach_status = 0; + return &ru_thread_prach_status; +} + + +int wakeup_synch(RU_t *ru) { + struct timespec wait; + wait.tv_sec=0; + wait.tv_nsec=5000000L; + + // wake up synch thread + // lock the synch mutex and make sure the thread is ready + if (pthread_mutex_timedlock(&ru->proc.mutex_synch,&wait) != 0) { + LOG_E( PHY, "[RU] ERROR pthread_mutex_lock for RU synch thread (IC %d)\n", ru->proc.instance_cnt_synch ); + exit_fun( "error locking mutex_synch" ); + return(-1); + } + + ++ru->proc.instance_cnt_synch; + + // the thread can now be woken up + if (pthread_cond_signal(&ru->proc.cond_synch) != 0) { + LOG_E( PHY, "[RU] ERROR pthread_cond_signal for RU synch thread\n"); + exit_fun( "ERROR pthread_cond_signal" ); + return(-1); + } + + pthread_mutex_unlock( &ru->proc.mutex_synch ); + return(0); +} + +void do_ru_synch(RU_t *ru) { + NR_DL_FRAME_PARMS *fp = ru->nr_frame_parms; + RU_proc_t *proc = &ru->proc; + int i; + void *rxp[2],*rxp2[2]; + int32_t dummy_rx[ru->nb_rx][fp->samples_per_subframe] __attribute__((aligned(32))); + int rxs; + int ic; + + // initialize the synchronization buffer to the common_vars.rxdata + for (int i=0; inb_rx; i++) + rxp[i] = &ru->common.rxdata[i][0]; + + double temp_freq1 = ru->rfdevice.openair0_cfg->rx_freq[0]; + double temp_freq2 = ru->rfdevice.openair0_cfg->tx_freq[0]; + + for (i=0; i<4; i++) { + ru->rfdevice.openair0_cfg->rx_freq[i] = ru->rfdevice.openair0_cfg->tx_freq[i]; + ru->rfdevice.openair0_cfg->tx_freq[i] = temp_freq1; + } + + ru->rfdevice.trx_set_freq_func(&ru->rfdevice,ru->rfdevice.openair0_cfg,0); + + while ((ru->in_synch ==0)&&(!oai_exit)) { + // read in frame + rxs = ru->rfdevice.trx_read_func(&ru->rfdevice, + &(proc->timestamp_rx), + rxp, + fp->samples_per_subframe*10, + ru->nb_rx); + + if (rxs != fp->samples_per_subframe*10) LOG_E(PHY,"requested %d samples, got %d\n",fp->samples_per_subframe*10,rxs); + + // wakeup synchronization processing thread + wakeup_synch(ru); + ic=0; + + while ((ic>=0)&&(!oai_exit)) { + // continuously read in frames, 1ms at a time, + // until we are done with the synchronization procedure + for (i=0; inb_rx; i++) + rxp2[i] = (void *)&dummy_rx[i][0]; + + for (i=0; i<10; i++) + rxs = ru->rfdevice.trx_read_func(&ru->rfdevice, + &(proc->timestamp_rx), + rxp2, + fp->samples_per_subframe, + ru->nb_rx); + + pthread_mutex_lock(&ru->proc.mutex_synch); + ic = ru->proc.instance_cnt_synch; + pthread_mutex_unlock(&ru->proc.mutex_synch); + } // ic>=0 + } // in_synch==0 + + // read in rx_offset samples + LOG_I(PHY,"Resynchronizing by %d samples\n",ru->rx_offset); + rxs = ru->rfdevice.trx_read_func(&ru->rfdevice, + &(proc->timestamp_rx), + rxp, + ru->rx_offset, + ru->nb_rx); + + for (i=0; i<4; i++) { + ru->rfdevice.openair0_cfg->rx_freq[i] = temp_freq1; + ru->rfdevice.openair0_cfg->tx_freq[i] = temp_freq2; + } + + ru->rfdevice.trx_set_freq_func(&ru->rfdevice,ru->rfdevice.openair0_cfg,0); +} + + + +void wakeup_gNB_L1s(RU_t *ru) { + int i; + PHY_VARS_gNB **gNB_list = ru->gNB_list; + LOG_D(PHY,"wakeup_gNB_L1s (num %d) for RU %d ru->gNB_top:%p\n",ru->num_gNB,ru->idx, ru->gNB_top); + + if (ru->num_gNB==1 && ru->gNB_top!=0 && get_thread_parallel_conf() == PARALLEL_SINGLE_THREAD) { + // call gNB function directly + char string[20]; + sprintf(string,"Incoming RU %u",ru->idx); + LOG_D(PHY,"RU %d Call gNB_top\n",ru->idx); + ru->gNB_top(gNB_list[0],ru->proc.frame_rx,ru->proc.tti_rx,string,ru); + } else { + LOG_D(PHY,"ru->num_gNB:%d\n", ru->num_gNB); + + for (i=0; inum_gNB; i++) { + LOG_D(PHY,"ru->wakeup_rxtx:%p\n", ru->nr_wakeup_rxtx); + + if (ru->nr_wakeup_rxtx!=0 && ru->nr_wakeup_rxtx(gNB_list[i],ru) < 0) { + LOG_E(PHY,"could not wakeup gNB rxtx process for subframe %d\n", ru->proc.tti_rx); + } + } + } +} + +int wakeup_prach_ru(RU_t *ru) { + struct timespec wait; + wait.tv_sec=0; + wait.tv_nsec=5000000L; + + if (pthread_mutex_timedlock(&ru->proc.mutex_prach,&wait) !=0) { + LOG_E( PHY, "[RU] ERROR pthread_mutex_lock for RU prach thread (IC %d)\n", ru->proc.instance_cnt_prach); + exit_fun( "error locking mutex_rxtx" ); + return(-1); + } + + if (ru->proc.instance_cnt_prach==-1) { + ++ru->proc.instance_cnt_prach; + ru->proc.frame_prach = ru->proc.frame_rx; + ru->proc.subframe_prach = ru->proc.tti_rx; + + // DJP - think prach_procedures() is looking at gNB frame_prach + if (ru->gNB_list[0]) { + ru->gNB_list[0]->proc.frame_prach = ru->proc.frame_rx; + ru->gNB_list[0]->proc.slot_prach = ru->proc.tti_rx; + } + + LOG_I(PHY,"RU %d: waking up PRACH thread\n",ru->idx); + // the thread can now be woken up + AssertFatal(pthread_cond_signal(&ru->proc.cond_prach) == 0, "ERROR pthread_cond_signal for RU prach thread\n"); + } else LOG_W(PHY,"RU prach thread busy, skipping\n"); + + pthread_mutex_unlock( &ru->proc.mutex_prach ); + return(0); +} + +// this is for RU with local RF unit +void fill_rf_config(RU_t *ru, char *rf_config_file) { + int i; + NR_DL_FRAME_PARMS *fp = ru->nr_frame_parms; + nfapi_nr_config_request_scf_t *config = &ru->config; //tmp index + openair0_config_t *cfg = &ru->openair0_cfg; + int mu = config->ssb_config.scs_common.value; + int N_RB = config->carrier_config.dl_grid_size[config->ssb_config.scs_common.value].value; + + if (mu == NR_MU_0) { //or if LTE + if(N_RB == 100) { + if (fp->threequarter_fs) { + cfg->sample_rate=23.04e6; + cfg->samples_per_frame = 230400; + cfg->tx_bw = 10e6; + cfg->rx_bw = 10e6; + } else { + cfg->sample_rate=30.72e6; + cfg->samples_per_frame = 307200; + cfg->tx_bw = 10e6; + cfg->rx_bw = 10e6; + } + } else if(N_RB == 50) { + cfg->sample_rate=15.36e6; + cfg->samples_per_frame = 153600; + cfg->tx_bw = 5e6; + cfg->rx_bw = 5e6; + } else if (N_RB == 25) { + cfg->sample_rate=7.68e6; + cfg->samples_per_frame = 76800; + cfg->tx_bw = 2.5e6; + cfg->rx_bw = 2.5e6; + } else if (N_RB == 6) { + cfg->sample_rate=1.92e6; + cfg->samples_per_frame = 19200; + cfg->tx_bw = 1.5e6; + cfg->rx_bw = 1.5e6; + } else AssertFatal(1==0,"Unknown N_RB %d\n",N_RB); + } else if (mu == NR_MU_1) { + if(N_RB == 273) { + if (fp->threequarter_fs) { + AssertFatal(0 == 1,"three quarter sampling not supported for N_RB 273\n"); + } else { + cfg->sample_rate=122.88e6; + cfg->samples_per_frame = 1228800; + cfg->tx_bw = 100e6; + cfg->rx_bw = 100e6; + } + } else if(N_RB == 217) { + if (fp->threequarter_fs) { + cfg->sample_rate=92.16e6; + cfg->samples_per_frame = 921600; + cfg->tx_bw = 80e6; + cfg->rx_bw = 80e6; + } else { + cfg->sample_rate=122.88e6; + cfg->samples_per_frame = 1228800; + cfg->tx_bw = 80e6; + cfg->rx_bw = 80e6; + } + } else if(N_RB == 106) { + if (fp->threequarter_fs) { + cfg->sample_rate=46.08e6; + cfg->samples_per_frame = 460800; + cfg->tx_bw = 40e6; + cfg->rx_bw = 40e6; + } + else { + cfg->sample_rate=61.44e6; + cfg->samples_per_frame = 614400; + cfg->tx_bw = 40e6; + cfg->rx_bw = 40e6; + } + } else { + AssertFatal(0==1,"N_RB %d not yet supported for numerology %d\n",N_RB,mu); + } + } else if (mu == NR_MU_3) { + if (N_RB == 66) { + cfg->sample_rate = 122.88e6; + cfg->samples_per_frame = 1228800; + cfg->tx_bw = 100e6; + cfg->rx_bw = 100e6; + } else if(N_RB == 32) { + cfg->sample_rate=61.44e6; + cfg->samples_per_frame = 614400; + cfg->tx_bw = 50e6; + cfg->rx_bw = 50e6; + } + } else { + AssertFatal(0 == 1,"Numerology %d not supported for the moment\n",mu); + } + + if (config->cell_config.frame_duplex_type.value==TDD) + cfg->duplex_mode = duplex_mode_TDD; + else //FDD + cfg->duplex_mode = duplex_mode_FDD; + + cfg->Mod_id = 0; + cfg->num_rb_dl=N_RB; + cfg->tx_num_channels=ru->nb_tx; + cfg->rx_num_channels=ru->nb_rx; + + for (i=0; inb_tx; i++) { + if (ru->if_frequency == 0) { + cfg->tx_freq[i] = (double)fp->dl_CarrierFreq; + cfg->rx_freq[i] = (double)fp->ul_CarrierFreq; + } else if (ru->if_freq_offset){ + cfg->tx_freq[i] = (double)(ru->if_frequency); + cfg->rx_freq[i] = (double)(ru->if_frequency + ru->if_freq_offset); + LOG_I(PHY, "Setting IF TX frequency to %lu Hz with IF RX frequency offset %d Hz\n", ru->if_frequency, ru->if_freq_offset); + } else { + cfg->tx_freq[i] = (double)ru->if_frequency; + cfg->rx_freq[i] = (double)(ru->if_frequency+fp->ul_CarrierFreq-fp->dl_CarrierFreq); + } + cfg->tx_gain[i] = ru->att_tx; + cfg->rx_gain[i] = ru->max_rxgain-ru->att_rx; + cfg->configFilename = rf_config_file; + LOG_I(PHY, "Channel %d: setting tx_gain offset %f, rx_gain offset %f, tx_freq %lu Hz, rx_freq %lu Hz\n", + i, cfg->tx_gain[i], + cfg->rx_gain[i], + (unsigned long)cfg->tx_freq[i], + (unsigned long)cfg->rx_freq[i]); + } +} + +/* this function maps the RU tx and rx buffers to the available rf chains. + Each rf chain is is addressed by the card number and the chain on the card. The + rf_map specifies for each antenna port, on which rf chain the mapping should start. Multiple + antennas are mapped to successive RF chains on the same card. */ +int setup_RU_buffers(RU_t *ru) { + int i,j; + int card,ant; + //uint16_t N_TA_offset = 0; + NR_DL_FRAME_PARMS *frame_parms; + nfapi_nr_config_request_scf_t *config = &ru->config; + + if (ru) { + frame_parms = ru->nr_frame_parms; + printf("setup_RU_buffers: frame_parms = %p\n",frame_parms); + } else { + printf("ru pointer is NULL\n"); + 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; + + + if (config->cell_config.frame_duplex_type.value == TDD) { + int N_TA_offset = config->carrier_config.uplink_frequency.value < 6000000 ? 400 : 431; // reference samples for 25600Tc @ 30.72 Ms/s for FR1, same @ 61.44 Ms/s for FR2 + + double factor=1; + + switch (mu) { + case 0: //15 kHz scs + AssertFatal(N_TA_offset == 400,"scs_common 15kHz only for FR1\n"); + if (N_RB <= 25) factor = .25; // 7.68 Ms/s + else if (N_RB <=50) factor = .5; // 15.36 Ms/s + else if (N_RB <=75) factor = 1.0; // 30.72 Ms/s + else if (N_RB <=100) factor = 1.0; // 30.72 Ms/s + else AssertFatal(1==0,"Too many PRBS for mu=0\n"); + break; + case 1: //30 kHz sc + AssertFatal(N_TA_offset == 400,"scs_common 30kHz only for FR1\n"); + if (N_RB <= 106) factor = 2.0; // 61.44 Ms/s + else if (N_RB <= 275) factor = 4.0; // 122.88 Ms/s + break; + case 2: //60 kHz scs + AssertFatal(1==0,"scs_common should not be 60 kHz\n"); + break; + case 3: //120 kHz scs + AssertFatal(N_TA_offset == 431,"scs_common 120kHz only for FR2\n"); + break; + case 4: //240 kHz scs + AssertFatal(1==0,"scs_common should not be 60 kHz\n"); + if (N_RB <= 32) factor = 1.0; // 61.44 Ms/s + else if (N_RB <= 66) factor = 2.0; // 122.88 Ms/s + else AssertFatal(1==0,"N_RB %d is too big for curretn FR2 implementation\n",N_RB); + break; + + if (N_RB == 100) ru->N_TA_offset = 624; + else if (N_RB == 50) ru->N_TA_offset = 624/2; + else if (N_RB == 25) ru->N_TA_offset = 624/4; + } + if (frame_parms->threequarter_fs == 1) factor = factor*.75; + ru->N_TA_offset = (int)(N_TA_offset * factor); + LOG_I(PHY,"RU %d Setting N_TA_offset to %d samples (factor %f, UL Freq %d, N_RB %d)\n",ru->idx,ru->N_TA_offset,factor, + config->carrier_config.uplink_frequency.value, N_RB); + } + else ru->N_TA_offset = 0; + + + if (ru->openair0_cfg.mmapped_dma == 1) { + // replace RX signal buffers with mmaped HW versions + for (i=0; inb_rx; i++) { + card = i/4; + ant = i%4; + printf("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]; + printf("rxdata[%d] @ %p\n",i,ru->common.rxdata[i]); + + for (j=0; j<16; j++) { + printf("rxbuffer %d: %x\n",j,ru->common.rxdata[i][j]); + ru->common.rxdata[i][j] = 16-j; + } + } + + for (i=0; inb_tx; i++) { + card = i/4; + ant = i%4; + printf("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]; + printf("txdata[%d] @ %p\n",i,ru->common.txdata[i]); + + for (j=0; j<16; j++) { + printf("txbuffer %d: %x\n",j,ru->common.txdata[i][j]); + ru->common.txdata[i][j] = 16-j; + } + } + } else { // not memory-mapped DMA + //nothing to do, everything already allocated in lte_init + } + + 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 (opp_enabled == 1) { + + if (ru->feprx) print_meas(&ru->ofdm_demod_stats,"feprx",NULL,NULL); + + if (ru->feptx_ofdm) { + print_meas(&ru->precoding_stats,"feptx_prec",NULL,NULL); + print_meas(&ru->txdataF_copy_stats,"txdataF_copy",NULL,NULL); + print_meas(&ru->ofdm_mod_stats,"feptx_ofdm",NULL,NULL); + print_meas(&ru->ofdm_total_stats,"feptx_total",NULL,NULL); + } + + if (ru->fh_north_asynch_in) print_meas(&ru->rx_fhaul,"rx_fhaul",NULL,NULL); + + 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_thread_tx( void *param ) { + RU_t *ru = (RU_t *)param; + RU_proc_t *proc = &ru->proc; + NR_DL_FRAME_PARMS *fp = ru->nr_frame_parms; + PHY_VARS_gNB *gNB; + gNB_L1_proc_t *gNB_proc; + gNB_L1_rxtx_proc_t *L1_proc; + char filename[40]; + int print_frame = 8; + int i = 0; + int ret; + + + wait_on_condition(&proc->mutex_FH1,&proc->cond_FH1,&proc->instance_cnt_FH1,"ru_thread_tx"); + printf( "ru_thread_tx ready\n"); + + while (!oai_exit) { + + LOG_D(PHY,"ru_thread_tx: Waiting for TX processing\n"); + // wait until eNBs are finished subframe RX n and TX n+4 + + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_RU_TX_WAIT, 1 ); + wait_on_condition(&proc->mutex_gNBs,&proc->cond_gNBs,&proc->instance_cnt_gNBs,"ru_thread_tx"); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_RU_TX_WAIT, 0 ); + + ret = pthread_mutex_lock(&proc->mutex_gNBs); + AssertFatal(ret == 0,"mutex_lock return %d\n",ret); + int frame_tx=proc->frame_tx; + int tti_tx =proc->tti_tx; + uint64_t timestamp_tx = proc->timestamp_tx; + + ret = pthread_mutex_unlock(&proc->mutex_gNBs); + AssertFatal(ret == 0,"mutex_lock returns %d\n",ret); + + if (oai_exit) break; + + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_TX0_RU, frame_tx ); + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TTI_NUMBER_TX0_RU, tti_tx ); + + // do TX front-end processing if needed (precoding and/or IDFTs) + if (ru->feptx_prec) ru->feptx_prec(ru,frame_tx,tti_tx); + + // do OFDM with/without TX front-end processing if needed + if ((ru->fh_north_asynch_in == NULL) && (ru->feptx_ofdm)) ru->feptx_ofdm(ru,frame_tx,tti_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,tti_tx,timestamp_tx); + + if (ru->fh_north_out) ru->fh_north_out(ru); + } else { + if(proc->frame_tx == print_frame) { + for (i=0; inb_tx; i++) { + + if(proc->tti_tx == 0) { + sprintf(filename,"gNBdataF_frame%d_sl%d.m", print_frame, proc->tti_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, proc->tti_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, proc->tti_tx); + LOG_M(filename,"txdataF_BF_frame",&ru->common.txdataF_BF[i][0],fp->samples_per_subframe_wCP, 1, 1); + } + + if(proc->tti_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(proc->tti_tx == 9) + }//for (i=0; inb_tx; i++) + }//if(proc->frame_tx == print_frame) + }//else emulate_rf + + release_thread(&proc->mutex_gNBs,&proc->instance_cnt_gNBs,"ru_thread_tx"); + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_RX1_UE, proc->instance_cnt_gNBs); + + for(i = 0; inum_gNB; i++) { + gNB = ru->gNB_list[i]; + gNB_proc = &gNB->proc; + L1_proc = (get_thread_parallel_conf() == PARALLEL_RU_L1_TRX_SPLIT)? &gNB_proc->L1_proc_tx : &gNB_proc->L1_proc; + ret = pthread_mutex_lock(&gNB_proc->mutex_RU_tx); + AssertFatal(ret == 0,"mutex_lock returns %d\n",ret); + + for (int j=0; jnum_RU; j++) { + if (ru == gNB->RU_list[j]) { + if ((gNB_proc->RU_mask_tx&(1< 0) + LOG_E(PHY,"gNB %d frame %d, subframe %d : previous information from RU tx %d (num_RU %d,mask %x) has not been served yet!\n", + gNB->Mod_id,gNB_proc->frame_rx,gNB_proc->slot_rx,ru->idx,gNB->num_RU,gNB_proc->RU_mask_tx); + + gNB_proc->RU_mask_tx |= (1<RU_mask_tx != (1<num_RU)-1) { // not all RUs have provided their information so return + ret = pthread_mutex_unlock(&gNB_proc->mutex_RU_tx); + AssertFatal(ret == 0,"mutex_unlock returns %d\n",ret); + } else { // all RUs TX are finished so send the ready signal to gNB processing + gNB_proc->RU_mask_tx = 0; + ret = pthread_mutex_unlock(&gNB_proc->mutex_RU_tx); + AssertFatal(ret == 0,"mutex_unlock returns %d\n",ret); + + ret = pthread_mutex_lock(&L1_proc->mutex_RUs_tx); + AssertFatal(ret == 0,"mutex_lock returns %d\n",ret); + // the thread can now be woken up + if (L1_proc->instance_cnt_RUs == -1) { + L1_proc->instance_cnt_RUs = 0; + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_RX0_UE,L1_proc->instance_cnt_RUs); + AssertFatal(pthread_cond_signal(&L1_proc->cond_RUs) == 0, + "ERROR pthread_cond_signal for gNB_L1_thread\n"); + } //else AssertFatal(1==0,"gNB TX thread is not ready\n"); + ret = pthread_mutex_unlock(&L1_proc->mutex_RUs_tx); + AssertFatal(ret == 0,"mutex_unlock returns %d\n",ret); + } + } + } + + release_thread(&proc->mutex_FH1,&proc->instance_cnt_FH1,"ru_thread_tx"); + return 0; +} + +void *ru_thread( void *param ) { + static int ru_thread_status; + RU_t *ru = (RU_t *)param; + RU_proc_t *proc = &ru->proc; + NR_DL_FRAME_PARMS *fp = ru->nr_frame_parms; + int ret; + int slot = fp->slots_per_frame-1; + int frame = 1023; + char filename[40], threadname[40]; + int print_frame = 8; + int i = 0; + int aa; + + nfapi_nr_config_request_scf_t *cfg = &ru->config; + + // set default return value + ru_thread_status = 0; + // set default return value + sprintf(threadname,"ru_thread %u",ru->idx); + + + LOG_I(PHY,"Starting RU %d (%s,%s),\n",ru->idx,NB_functions[ru->function],NB_timing[ru->if_timing]); + + memcpy((void*)&ru->config,(void*)&RC.gNB[0]->gNB_config,sizeof(ru->config)); + + if(emulate_rf) { + fill_rf_config(ru,ru->rf_config_file); + nr_init_frame_parms(&ru->config, fp); + nr_dump_frame_parms(fp); + nr_phy_init_RU(ru); + + if (setup_RU_buffers(ru)!=0) { + printf("Exiting, cannot initialize RU Buffers\n"); + exit(-1); + } + } else { + // Start IF device if any + if (ru->nr_start_if) { + LOG_I(PHY,"Starting IF interface for RU %d\n",ru->idx); + AssertFatal(ru->nr_start_if(ru,NULL) == 0, "Could not start the IF device\n"); + + if (ru->if_south == LOCAL_RF) ret = connect_rau(ru); + else ret = attach_rru(ru); + + AssertFatal(ret==0,"Cannot connect to remote radio\n"); + } + + if (ru->if_south == LOCAL_RF) { // configure RF parameters only + nr_init_frame_parms(&ru->config, fp); + nr_dump_frame_parms(fp); + fill_rf_config(ru,ru->rf_config_file); + nr_phy_init_RU(ru); + ret = openair0_device_load(&ru->rfdevice,&ru->openair0_cfg); + AssertFatal(ret==0,"Cannot connect to local radio\n"); + } + + if (setup_RU_buffers(ru)!=0) { + printf("Exiting, cannot initialize RU Buffers\n"); + exit(-1); + } + } + + sf_ahead = (uint16_t) ceil((float)6/(0x01<numerology_index)); + LOG_I(PHY, "Signaling main thread that RU %d is ready\n",ru->idx); + pthread_mutex_lock(&RC.ru_mutex); + RC.ru_mask &= ~(1<idx); + pthread_cond_signal(&RC.ru_cond); + 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); + + // if an asnych_rxtx thread exists + // wakeup the thread because the devices are ready at this point + + if ((ru->fh_south_asynch_in)||(ru->fh_north_asynch_in)) { + pthread_mutex_lock(&proc->mutex_asynch_rxtx); + proc->instance_cnt_asynch_rxtx=0; + pthread_mutex_unlock(&proc->mutex_asynch_rxtx); + pthread_cond_signal(&proc->cond_asynch_rxtx); + } else LOG_I(PHY,"RU %d no asynch_south interface\n",ru->idx); + + // if this is a slave RRU, try to synchronize on the DL frequency + if ((ru->is_slave) && (ru->if_south == LOCAL_RF)) do_ru_synch(ru); + + // 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"); + } + } + } + } + + pthread_mutex_lock(&proc->mutex_FH1); + proc->instance_cnt_FH1 = 0; + pthread_mutex_unlock(&proc->mutex_FH1); + pthread_cond_signal(&proc->cond_FH1); + + // This is a forever while loop, it loops over subframes which are scheduled by incoming samples from HW devices + while (!oai_exit) { + // these are local subframe/frame counters to check that we are in synch with the fronthaul timing. + // They are set on the first rx/tx in the underly FH routines. + if (slot==(fp->slots_per_frame-1)) { + slot=0; + frame++; + frame&=1023; + } else { + slot++; + } + + // 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"); + + LOG_D(PHY,"AFTER fh_south_in - SFN/SL:%d%d RU->proc[RX:%d.%d TX:%d.%d] RC.gNB[0]:[RX:%d%d TX(SFN):%d]\n", + frame,slot, + proc->frame_rx,proc->tti_rx, + proc->frame_tx,proc->tti_tx, + RC.gNB[0]->proc.frame_rx,RC.gNB[0]->proc.slot_rx, + RC.gNB[0]->proc.frame_tx); + /* + LOG_D(PHY,"RU thread (do_prach %d, is_prach_subframe %d), received frame %d, subframe %d\n", + ru->do_prach, + is_prach_subframe(fp, proc->frame_rx, proc->tti_rx), + proc->frame_rx,proc->tti_rx); + + if ((ru->do_prach>0) && (is_prach_subframe(fp, proc->frame_rx, proc->tti_rx)==1)) { + wakeup_prach_ru(ru); + }*/ + + // adjust for timing offset between RU + //printf("~~~~~~~~~~~~~~~~~~~~~~~~~~%d.%d in ru_thread is in process\n", proc->frame_rx, proc->tti_rx); + if (ru->idx!=0) proc->frame_tx = (proc->frame_tx+proc->frame_offset)&1023; + + // do RX front-end processing (frequency-shift, dft) if needed + + int slot_type = nr_slot_select(cfg,proc->frame_rx,proc->tti_rx); + if (slot_type == NR_UPLINK_SLOT || slot_type == NR_MIXED_SLOT) { + //if (proc->tti_rx==8) { + + if (ru->feprx) { + ru->feprx(ru,proc->tti_rx); + //LOG_M("rxdata.m","rxs",ru->common.rxdata[0],1228800,1,1); + + LOG_D(PHY,"RU proc: frame_rx = %d, tti_rx = %d\n", proc->frame_rx, proc->tti_rx); + LOG_D(PHY,"Copying rxdataF from RU to gNB\n"); + + for (aa=0;aanb_rx;aa++) + memcpy((void*)RC.gNB[0]->common_vars.rxdataF[aa], + (void*)ru->common.rxdataF[aa], fp->symbols_per_slot*fp->ofdm_symbol_size*sizeof(int32_t)); + + // Do PRACH RU processing + + int prach_id=find_nr_prach_ru(ru,proc->frame_rx,proc->tti_rx,SEARCH_EXIST); + uint8_t prachStartSymbol,N_dur; + if (prach_id>=0) { + N_dur = get_nr_prach_duration(ru->prach_list[prach_id].fmt); + /* + get_nr_prach_info_from_index(ru->config.prach_config.prach_ConfigurationIndex.value, + proc->frame_rx,proc->tti_rx, + ru->config.carrier_config.dl_frequency.value, + fp->numerology_index, + fp->frame_type, + &format, + &start_symbol, + &N_t_slot, + &N_dur, + &RA_sfn_index, + &N_RA_slot, + &config_period); + */ + for (int prach_oc = 0; prach_ocprach_list[prach_id].num_prach_ocas; prach_oc++) { + prachStartSymbol = ru->prach_list[prach_id].prachStartSymbol+prach_oc*N_dur; + //comment FK: the standard 38.211 section 5.3.2 has one extra term +14*N_RA_slot. This is because there prachStartSymbol is given wrt to start of the 15kHz slot or 60kHz slot. Here we work slot based, so this function is anyway only called in slots where there is PRACH. Its up to the MAC to schedule another PRACH PDU in the case there are there N_RA_slot \in {0,1}. + + rx_nr_prach_ru(ru, + ru->prach_list[prach_id].fmt, //could also use format + ru->prach_list[prach_id].numRA, + prachStartSymbol, + prach_oc, + proc->frame_rx,proc->tti_rx); + } + free_nr_ru_prach_entry(ru,prach_id); + } + } + } + + // At this point, all information for subframe has been received on FH interface + + // wakeup all gNB processes waiting for this RU + if (ru->num_gNB>0) wakeup_gNB_L1s(ru); + + if(get_thread_parallel_conf() == PARALLEL_SINGLE_THREAD || ru->num_gNB==0) { + // do TX front-end processing if needed (precoding and/or IDFTs) + if (ru->feptx_prec) ru->feptx_prec(ru,proc->frame_tx,proc->tti_tx); + + // do OFDM with/without TX front-end processing if needed + if ((ru->fh_north_asynch_in == NULL) && (ru->feptx_ofdm)) ru->feptx_ofdm(ru,proc->frame_tx,proc->tti_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,proc->frame_tx,proc->tti_tx,proc->timestamp_tx); + + if (ru->fh_north_out) ru->fh_north_out(ru); + } else { + if(proc->frame_tx == print_frame) { + for (i=0; inb_tx; i++) { + sprintf(filename,"tx%ddataF_frame%d_sl%d.m", i, print_frame, proc->tti_tx); + LOG_M(filename,"txdataF_frame",&ru->common.txdataF_BF[i][0],fp->samples_per_slot_wCP, 1, 1); + + if(proc->tti_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(proc->tti_tx == 9) + }//for (i=0; inb_tx; i++) + }//if(proc->frame_tx == print_frame) + }//else emulate_rf + + proc->emulate_rf_busy = 0; + }//if(get_thread_parallel_conf() == PARALLEL_SINGLE_THREAD) + } + + printf( "Exiting ru_thread \n"); + + 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); + } + + ru_thread_status = 0; + return &ru_thread_status; +} +/* +// This thread run the initial synchronization like a UE +void *ru_thread_synch(void *arg) { + + RU_t *ru = (RU_t*)arg; + NR_DL_FRAME_PARMS *fp=ru->nr_frame_parms; + int32_t sync_pos,sync_pos2; + uint32_t peak_val; + uint32_t sync_corr[307200] __attribute__((aligned(32))); + static int ru_thread_synch_status; + + + + wait_sync("ru_thread_synch"); + + // initialize variables for PSS detection + lte_sync_time_init(ru->nr_frame_parms); + + while (!oai_exit) { + + // wait to be woken up + if (wait_on_condition(&ru->proc.mutex_synch,&ru->proc.cond_synch,&ru->proc.instance_cnt_synch,"ru_thread_synch")<0) break; + + // if we're not in synch, then run initial synch + if (ru->in_synch == 0) { + // run intial synch like UE + LOG_I(PHY,"Running initial synchronization\n"); + + sync_pos = lte_sync_time_gNB(ru->common.rxdata, + fp, + fp->samples_per_subframe*5, + &peak_val, + sync_corr); + LOG_I(PHY,"RU synch: %d, val %d\n",sync_pos,peak_val); + + if (sync_pos >= 0) { + if (sync_pos >= fp->nb_prefix_samples) + sync_pos2 = sync_pos - fp->nb_prefix_samples; + else + sync_pos2 = sync_pos + (fp->samples_per_subframe*10) - fp->nb_prefix_samples; + + if (fp->frame_type == FDD) { + + // PSS is hypothesized in last symbol of first slot in Frame + int sync_pos_slot = (fp->samples_per_subframe>>1) - fp->ofdm_symbol_size - fp->nb_prefix_samples; + + if (sync_pos2 >= sync_pos_slot) + ru->rx_offset = sync_pos2 - sync_pos_slot; + else + ru->rx_offset = (fp->samples_per_subframe*10) + sync_pos2 - sync_pos_slot; + } + else { + + } + + LOG_I(PHY,"Estimated sync_pos %d, peak_val %d => timing offset %d\n",sync_pos,peak_val,ru->rx_offset); + + if ((peak_val > 300000) && (sync_pos > 0)) { + // if (sync_pos++ > 3) { + write_output("ru_sync.m","sync",(void*)&sync_corr[0],fp->samples_per_subframe*5,1,2); + write_output("ru_rx.m","rxs",(void*)ru->ru_time.rxdata[0][0],fp->samples_per_subframe*10,1,1); + exit(-1); + } + + ru->in_synch=1; + } + } + + if (release_thread(&ru->proc.mutex_synch,&ru->proc.instance_cnt_synch,"ru_synch_thread") < 0) break; + } // oai_exit + + ru_thread_synch_status = 0; + return &ru_thread_synch_status; + +} +*/ + +int nr_start_if(struct RU_t_s *ru, struct PHY_VARS_gNB_s *gNB) { + return(ru->ifdevice.trx_start_func(&ru->ifdevice)); +} + +int start_rf(RU_t *ru) { + return(ru->rfdevice.trx_start_func(&ru->rfdevice)); +} + +int stop_rf(RU_t *ru) { + ru->rfdevice.trx_end_func(&ru->rfdevice); + return 0; +} + +int start_write_thread(RU_t *ru) { + return(ru->rfdevice.trx_write_init(&ru->rfdevice)); +} + +void init_RU_proc(RU_t *ru) { + int i=0; + RU_proc_t *proc; + char name[100]; + LOG_I(PHY,"Initializing RU proc %d (%s,%s),\n",ru->idx,NB_functions[ru->function],NB_timing[ru->if_timing]); + proc = &ru->proc; + memset((void *)proc,0,sizeof(RU_proc_t)); + proc->ru = ru; + proc->instance_cnt_prach = -1; + proc->instance_cnt_synch = -1; + proc->instance_cnt_FH = -1; + proc->instance_cnt_FH1 = -1; + proc->instance_cnt_gNBs = -1; + proc->instance_cnt_asynch_rxtx = -1; + 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; + proc->feptx_mask = 0; + + for (i=0; i<10; i++) proc->symbol_mask[i]=0; + + pthread_mutex_init( &proc->mutex_prach, NULL); + pthread_mutex_init( &proc->mutex_asynch_rxtx, NULL); + 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_gNBs, 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_gNBs, NULL); + threadCreate( &proc->pthread_FH, ru_thread, (void *)ru, "thread_FH", -1, OAI_PRIORITY_RT_MAX ); + + if (get_thread_parallel_conf() == PARALLEL_RU_L1_SPLIT || get_thread_parallel_conf() == PARALLEL_RU_L1_TRX_SPLIT) + threadCreate( &proc->pthread_FH1, ru_thread_tx, (void *)ru, "thread_FH1", -1, OAI_PRIORITY_RT ); + + if(emulate_rf) + threadCreate( &proc->pthread_emulateRF, emulatedRF_thread, (void *)proc, "emulateRF", -1, OAI_PRIORITY_RT ); + + if (ru->function == NGFI_RRU_IF4p5) { + threadCreate( &proc->pthread_prach, ru_thread_prach, (void *)ru, "RACH", -1, OAI_PRIORITY_RT ); + ///tmp deactivation of synch thread + // if (ru->is_slave == 1) pthread_create( &proc->pthread_synch, attr_synch, ru_thread_synch, (void*)ru); + + if ((ru->if_timing == synch_to_other) || + (ru->function == NGFI_RRU_IF5) || + (ru->function == NGFI_RRU_IF4p5)) threadCreate( &proc->pthread_asynch_rxtx, ru_thread_asynch_rxtx, (void *)ru, "asynch_rxtx", -1, OAI_PRIORITY_RT ); + + snprintf( name, sizeof(name), "ru_thread_FH %d", ru->idx ); + pthread_setname_np( proc->pthread_FH, name ); + } else if (ru->function == gNodeB_3GPP && ru->if_south == LOCAL_RF) { // DJP - need something else to distinguish between monolithic and PNF + LOG_I(PHY,"%s() DJP - added creation of pthread_prach\n", __FUNCTION__); + threadCreate( &proc->pthread_prach, ru_thread_prach, (void *)ru,"RACH", -1, OAI_PRIORITY_RT ); + } + + if (get_thread_worker_conf() == WORKER_ENABLE) { + if (ru->feprx) nr_init_feprx_thread(ru); + + if (ru->feptx_ofdm) nr_init_feptx_thread(ru); + } + + if (opp_enabled == 1) threadCreate(&ru->ru_stats_thread,ru_stats_thread,(void *)ru, "emulateRF", -1, OAI_PRIORITY_RT_LOW); +} + +void kill_NR_RU_proc(int inst) { + RU_t *ru = RC.ru[inst]; + RU_proc_t *proc = &ru->proc; + pthread_mutex_lock(&proc->mutex_FH); + proc->instance_cnt_FH = 0; + pthread_mutex_unlock(&proc->mutex_FH); + pthread_cond_signal(&proc->cond_FH); + pthread_mutex_lock(&proc->mutex_prach); + proc->instance_cnt_prach = 0; + pthread_mutex_unlock(&proc->mutex_prach); + pthread_cond_signal(&proc->cond_prach); + pthread_mutex_lock(&proc->mutex_synch); + proc->instance_cnt_synch = 0; + pthread_mutex_unlock(&proc->mutex_synch); + pthread_cond_signal(&proc->cond_synch); + pthread_mutex_lock(&proc->mutex_gNBs); + proc->instance_cnt_gNBs = 0; + pthread_mutex_unlock(&proc->mutex_gNBs); + pthread_cond_signal(&proc->cond_gNBs); + pthread_mutex_lock(&proc->mutex_asynch_rxtx); + proc->instance_cnt_asynch_rxtx = 0; + pthread_mutex_unlock(&proc->mutex_asynch_rxtx); + pthread_cond_signal(&proc->cond_asynch_rxtx); + LOG_D(PHY, "Joining pthread_FH\n"); + pthread_join(proc->pthread_FH, NULL); + + if (ru->function == NGFI_RRU_IF4p5) { + LOG_D(PHY, "Joining pthread_prach\n"); + pthread_join(proc->pthread_prach, NULL); + + if (ru->is_slave) { + LOG_D(PHY, "Joining pthread_\n"); + pthread_join(proc->pthread_synch, NULL); + } + + if ((ru->if_timing == synch_to_other) || + (ru->function == NGFI_RRU_IF5) || + (ru->function == NGFI_RRU_IF4p5)) { + LOG_D(PHY, "Joining pthread_asynch_rxtx\n"); + pthread_join(proc->pthread_asynch_rxtx, NULL); + } + } + + if (get_nprocs() >= 2) { + if (ru->feprx) { + pthread_mutex_lock(&proc->mutex_fep); + proc->instance_cnt_fep = 0; + pthread_mutex_unlock(&proc->mutex_fep); + pthread_cond_signal(&proc->cond_fep); + LOG_D(PHY, "Joining pthread_fep\n"); + pthread_join(proc->pthread_fep, NULL); + pthread_mutex_destroy(&proc->mutex_fep); + pthread_cond_destroy(&proc->cond_fep); + } + + if (ru->feptx_ofdm) { + pthread_mutex_lock(&proc->mutex_feptx); + proc->instance_cnt_feptx = 0; + pthread_mutex_unlock(&proc->mutex_feptx); + pthread_cond_signal(&proc->cond_feptx); + LOG_D(PHY, "Joining pthread_feptx\n"); + pthread_join(proc->pthread_feptx, NULL); + pthread_mutex_destroy(&proc->mutex_feptx); + pthread_cond_destroy(&proc->cond_feptx); + } + } + + if (opp_enabled) { + LOG_D(PHY, "Joining ru_stats_thread\n"); + pthread_join(ru->ru_stats_thread, NULL); + } + + pthread_mutex_destroy(&proc->mutex_prach); + pthread_mutex_destroy(&proc->mutex_asynch_rxtx); + pthread_mutex_destroy(&proc->mutex_synch); + pthread_mutex_destroy(&proc->mutex_FH); + pthread_mutex_destroy(&proc->mutex_gNBs); + pthread_cond_destroy(&proc->cond_prach); + pthread_cond_destroy(&proc->cond_FH); + pthread_cond_destroy(&proc->cond_asynch_rxtx); + pthread_cond_destroy(&proc->cond_synch); + pthread_cond_destroy(&proc->cond_gNBs); +} + +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; + break; + } + } + + if (found_band == 0) { + LOG_I(PHY,"Couldn't find target NR band %d on RRU %d\n",ru->nr_frame_parms->nr_band,ru->idx); + return(-1); + } + + switch (ru->if_south) { + case LOCAL_RF: + AssertFatal(1==0, "This RU should not have a local RF, exiting\n"); + return(0); + break; + + case REMOTE_IF5: + 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); + + break; + + case REMOTE_MBP_IF5: + if (fmt == MBP_IF5) return(0); + + break; + + default: + LOG_I(PHY,"No compatible Fronthaul interface found for RRU %d\n", ru->idx); + return(-1); + } + + return(-1); +} + + +char rru_format_options[4][20] = {"OAI_IF5_only","OAI_IF4p5_only","OAI_IF5_and_IF4p5","MBP_IF5"}; + +char rru_formats[3][20] = {"OAI_IF5","MBP_IF5","OAI_IF4p5"}; +char ru_if_formats[4][20] = {"LOCAL_RF","REMOTE_OAI_IF5","REMOTE_MBP_IF5","REMOTE_OAI_IF4p5"}; + +void configure_ru(int idx, + void *arg) +{ + RU_t *ru = RC.ru[idx]; + 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",idx); + + 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", idx, ret); + // take antenna capabilities of RRU + 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]);*/ + nr_init_frame_parms(&ru->config, ru->nr_frame_parms); + nr_phy_init_RU(ru); +} + +void configure_rru(int idx, + void *arg) { + RRU_config_t *config = (RRU_config_t *)arg; + RU_t *ru = RC.ru[idx]; + 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]; + + 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]; + } else + cfg->cell_config.frame_duplex_type.value = FDD; + + 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]; + + //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]; */ + } + + fill_rf_config(ru,ru->rf_config_file); + nr_init_frame_parms(&ru->config, ru->nr_frame_parms); + nr_phy_init_RU(ru); +} + +/* +void init_precoding_weights(PHY_VARS_gNB *gNB) { + + int layer,ru_id,aa,re,ue,tb; + LTE_DL_FRAME_PARMS *fp=&gNB->frame_parms; + RU_t *ru; + LTE_gNB_DLSCH_t *dlsch; + + // init precoding weigths + for (ue=0;uedlsch[ue][tb]; + for (layer=0; layer<4; layer++) { + int nb_tx=0; + for (ru_id=0;ru_idnb_tx; + } + dlsch->ue_spec_bf_weights[layer] = (int32_t**)malloc16(nb_tx*sizeof(int32_t*)); + + for (aa=0; aaue_spec_bf_weights[layer][aa] = (int32_t *)malloc16(fp->ofdm_symbol_size*sizeof(int32_t)); + for (re=0;reofdm_symbol_size; re++) { + dlsch->ue_spec_bf_weights[layer][aa][re] = 0x00007fff; + } + } + } + } + } +}*/ + +void set_function_spec_param(RU_t *ru) { + int ret; + + switch (ru->if_south) { + case LOCAL_RF: // this is an RU with integrated RF (RRU, gNB) + if (ru->function == NGFI_RRU_IF5) { // IF5 RRU + ru->do_prach = 0; // no prach processing in RU + ru->fh_north_in = NULL; // no shynchronous incoming fronthaul from north + ru->fh_north_out = fh_if5_north_out; // need only to do send_IF5 reception + ru->fh_south_out = tx_rf; // send output to RF + ru->fh_north_asynch_in = fh_if5_north_asynch_in; // TX packets come asynchronously + ru->feprx = NULL; // nothing (this is a time-domain signal) + ru->feptx_ofdm = NULL; // nothing (this is a time-domain signal) + ru->feptx_prec = NULL; // nothing (this is a time-domain signal) + ru->nr_start_if = nr_start_if; // need to start the if interface for if5 + ru->ifdevice.host_type = RRU_HOST; + ru->rfdevice.host_type = RRU_HOST; + ru->ifdevice.eth_params = &ru->eth_params; + reset_meas(&ru->rx_fhaul); + reset_meas(&ru->tx_fhaul); + reset_meas(&ru->compression); + reset_meas(&ru->transport); + ret = openair0_transport_load(&ru->ifdevice,&ru->openair0_cfg,&ru->eth_params); + printf("openair0_transport_init returns %d for ru_id %u\n", ret, ru->idx); + + if (ret<0) { + printf("Exiting, cannot initialize transport protocol\n"); + exit(-1); + } + } else if (ru->function == NGFI_RRU_IF4p5) { + ru->do_prach = 1; // do part of prach processing in RU + ru->fh_north_in = NULL; // no synchronous incoming fronthaul from north + ru->fh_north_out = fh_if4p5_north_out; // send_IF4p5 on reception + ru->fh_south_out = tx_rf; // send output to RF + ru->fh_north_asynch_in = fh_if4p5_north_asynch_in; // TX packets come asynchronously + ru->feprx = (get_thread_worker_conf() == WORKER_ENABLE) ? nr_fep_full_2thread : nr_fep_full; // RX DFTs + ru->feptx_ofdm = (get_thread_worker_conf() == WORKER_ENABLE) ? nr_feptx_ofdm_2thread : nr_feptx_ofdm; // this is fep with idft only (no precoding in RRU) + ru->feptx_prec = NULL; + ru->nr_start_if = nr_start_if; // need to start the if interface for if4p5 + ru->ifdevice.host_type = RRU_HOST; + ru->rfdevice.host_type = RRU_HOST; + ru->ifdevice.eth_params = &ru->eth_params; + reset_meas(&ru->rx_fhaul); + reset_meas(&ru->tx_fhaul); + reset_meas(&ru->compression); + reset_meas(&ru->transport); + ret = openair0_transport_load(&ru->ifdevice,&ru->openair0_cfg,&ru->eth_params); + printf("openair0_transport_init returns %d for ru_id %u\n", ret, ru->idx); + + if (ret<0) { + printf("Exiting, cannot initialize transport protocol\n"); + exit(-1); + } + + malloc_IF4p5_buffer(ru); + } else if (ru->function == gNodeB_3GPP) { + ru->do_prach = 0; // no prach processing in RU + ru->feprx = (get_thread_worker_conf() == WORKER_ENABLE) ? nr_fep_full_2thread : nr_fep_full; // RX DFTs + ru->feptx_ofdm = (get_thread_worker_conf() == WORKER_ENABLE) ? nr_feptx_ofdm_2thread : nr_feptx_ofdm; // this is fep with idft and precoding + ru->feptx_prec = (get_thread_worker_conf() == WORKER_ENABLE) ? NULL : nr_feptx_prec; // this is fep with idft and precoding + ru->fh_north_in = NULL; // no incoming fronthaul from north + ru->fh_north_out = NULL; // no outgoing fronthaul to north + ru->nr_start_if = NULL; // no if interface + ru->rfdevice.host_type = RAU_HOST; + + // FK this here looks messed up. The following lines should be part of the if (ru->function == gNodeB_3GPP), shouldn't they? + + ru->fh_south_in = rx_rf; // local synchronous RF RX + ru->fh_south_out = tx_rf; // local synchronous RF TX + ru->start_rf = start_rf; // need to start the local RF interface + ru->stop_rf = stop_rf; + ru->start_write_thread = start_write_thread; // starting RF TX in different thread + printf("configuring ru_id %u (start_rf %p)\n", ru->idx, start_rf); + } + + /* + printf("configuring ru_id %u (start_rf %p)\n", ru->idx, start_rf); + 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) { + printf("Exiting, cannot initialize RU Buffers\n"); + exit(-1); + } + */ + break; + + case REMOTE_IF5: // the remote unit is IF5 RRU + ru->do_prach = 0; + ru->feprx = (get_thread_worker_conf() == WORKER_ENABLE) ? nr_fep_full_2thread : nr_fep_full; // this is frequency-shift + DFTs + ru->feptx_prec = (get_thread_worker_conf() == WORKER_ENABLE) ? NULL : nr_feptx_prec; // need to do transmit Precoding + IDFTs + ru->feptx_ofdm = (get_thread_worker_conf() == WORKER_ENABLE) ? nr_feptx_ofdm_2thread : nr_feptx_ofdm; // need to do transmit Precoding + IDFTs + ru->fh_south_in = fh_if5_south_in; // synchronous IF5 reception + ru->fh_south_out = fh_if5_south_out; // synchronous IF5 transmission + ru->fh_south_asynch_in = NULL; // no asynchronous UL + ru->start_rf = NULL; // no local RF + ru->stop_rf = NULL; + ru->start_write_thread = NULL; + ru->nr_start_if = nr_start_if; // need to start if interface for IF5 + ru->ifdevice.host_type = RAU_HOST; + ru->ifdevice.eth_params = &ru->eth_params; + ru->ifdevice.configure_rru = configure_ru; + ret = openair0_transport_load(&ru->ifdevice,&ru->openair0_cfg,&ru->eth_params); + printf("openair0_transport_init returns %d for ru_id %u\n", ret, ru->idx); + + if (ret<0) { + printf("Exiting, cannot initialize transport protocol\n"); + exit(-1); + } + + break; + + case REMOTE_IF4p5: + ru->do_prach = 0; + ru->feprx = NULL; // DFTs + ru->feptx_prec = nr_feptx_prec; // Precoding operation + ru->feptx_ofdm = NULL; // no OFDM mod + ru->fh_south_in = fh_if4p5_south_in; // synchronous IF4p5 reception + ru->fh_south_out = fh_if4p5_south_out; // synchronous IF4p5 transmission + ru->fh_south_asynch_in = (ru->if_timing == synch_to_other) ? fh_if4p5_south_in : NULL; // asynchronous UL if synch_to_other + ru->fh_north_out = NULL; + ru->fh_north_asynch_in = NULL; + ru->start_rf = NULL; // no local RF + ru->stop_rf = NULL; + ru->start_write_thread = NULL; + ru->nr_start_if = nr_start_if; // need to start if interface for IF4p5 + ru->ifdevice.host_type = RAU_HOST; + ru->ifdevice.eth_params = &ru->eth_params; + ru->ifdevice.configure_rru = configure_ru; + ret = openair0_transport_load(&ru->ifdevice, &ru->openair0_cfg, &ru->eth_params); + printf("openair0_transport_init returns %d for ru_id %u\n", ret, ru->idx); + + if (ret<0) { + printf("Exiting, cannot initialize transport protocol\n"); + exit(-1); + } + + if (ru->ifdevice.get_internal_parameter != NULL) { + 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; + } + + malloc_IF4p5_buffer(ru); + break; + + default: + LOG_E(PHY,"RU with invalid or unknown southbound interface type %d\n",ru->if_south); + break; + } // switch on interface type +} + +void init_NR_RU(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); + pthread_cond_init(&RC.ru_cond,NULL); + // read in configuration file) + printf("configuring RU from file\n"); + RCconfig_RU(); + 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; + // use gNB_list[0] as a reference for RU frame parameters + // NOTE: multiple CC_id are not handled here yet! + + if (ru->num_gNB > 0) { + LOG_D(PHY, "%s() RC.ru[%d].num_gNB:%d ru->gNB_list[0]:%p RC.gNB[0]:%p rf_config_file:%s\n", __FUNCTION__, ru_id, ru->num_gNB, ru->gNB_list[0], RC.gNB[0], ru->rf_config_file); + + if (ru->gNB_list[0] == 0) { + LOG_E(PHY,"%s() DJP - ru->gNB_list ru->num_gNB are not initialized - so do it manually\n", __FUNCTION__); + ru->gNB_list[0] = RC.gNB[0]; + ru->num_gNB=1; + // + // DJP - feptx_prec() / feptx_ofdm() parses the gNB_list (based on num_gNB) and copies the txdata_F to txdata in RU + // + } else { + LOG_E(PHY,"DJP - delete code above this %s:%d\n", __FILE__, __LINE__); + } + } + + gNB_RC = RC.gNB[0]; + gNB0 = ru->gNB_list[0]; + fp = ru->nr_frame_parms; + 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!=NULL,"gNB0 is null!\n"); + + if (gNB0 && gNB_RC) { + LOG_I(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); + memset((void *)fp, 0, sizeof(NR_DL_FRAME_PARMS)); + 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)); + // 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++) { + gNB0 = ru->gNB_list[i]; + gNB0->RU_list[gNB0->num_RU++] = ru; + } + } + } + + //LOG_I(PHY,"Initializing RRU descriptor %d : (%s,%s,%d)\n",ru_id,ru_if_types[ru->if_south],NB_timing[ru->if_timing],ru->function); + set_function_spec_param(ru); + LOG_I(PHY,"Starting ru_thread %d\n",ru_id); + init_RU_proc(ru); + } // for ru_id + + // sleep(1); + LOG_D(HW,"[nr-softmodem.c] RU threads created\n"); +} + + +void stop_RU(int nb_ru) +{ + for (int inst = 0; inst < nb_ru; inst++) { + LOG_I(PHY, "Stopping RU %d processing threads\n", inst); + kill_NR_RU_proc(inst); + } +} + + +/* --------------------------------------------------------*/ +/* from here function to use configuration module */ +void RCconfig_RU(void) +{ + int i = 0, j = 0; + paramdef_t RUParams[] = RUPARAMS_DESC; + paramlist_def_t RUParamList = {CONFIG_STRING_RU_LIST,NULL,0}; + config_getlist( &RUParamList, RUParams, sizeof(RUParams)/sizeof(paramdef_t), NULL); + + if ( RUParamList.numelt > 0) { + RC.ru = (RU_t **)malloc(RC.nb_RU*sizeof(RU_t *)); + RC.ru_mask=(1<idx = j; + RC.ru[j]->nr_frame_parms = (NR_DL_FRAME_PARMS *)malloc(sizeof(NR_DL_FRAME_PARMS)); + RC.ru[j]->frame_parms = (LTE_DL_FRAME_PARMS *)malloc(sizeof(LTE_DL_FRAME_PARMS)); + printf("Creating RC.ru[%d]:%p\n", j, RC.ru[j]); + RC.ru[j]->if_timing = synch_to_ext_device; + + 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 (i=0; inum_gNB; i++) RC.ru[j]->gNB_list[i] = RC.gNB[RUParamList.paramarray[j][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(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_D(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_D(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_D(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)); + } + } + else { + RC.ru[j]->openair0_cfg.clock_source = unset; + } + + 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_D(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_D(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_D(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)); + } + } + else { + RC.ru[j]->openair0_cfg.time_source = unset; + } + + 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; + printf("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; + printf("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; + printf("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; + printf("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; + printf("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]->num_bands = RUParamList.paramarray[j][RU_BAND_LIST_IDX].numelt; + + for (i=0; inum_bands; i++) RC.ru[j]->band[i] = RUParamList.paramarray[j][RU_BAND_LIST_IDX].iptr[i]; + } //strcmp(local_rf, "yes") == 0 + else { + printf("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), "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); + + if (config_isparamset(RUParamList.paramarray[j], RU_BF_WEIGHTS_LIST_IDX)) { + RC.ru[j]->nb_bfw = RUParamList.paramarray[j][RU_BF_WEIGHTS_LIST_IDX].numelt; + for (i=0; inum_gNB; i++) { + RC.ru[j]->bw_list[i] = (int32_t *)malloc16_clear((RC.ru[j]->nb_bfw)*sizeof(int32_t)); + for (int b=0; bnb_bfw; b++) RC.ru[j]->bw_list[i][b] = RUParamList.paramarray[j][RU_BF_WEIGHTS_LIST_IDX].iptr[b]; + } + } + }// j=0..num_rus + } else { + RC.nb_RU = 0; + } // setting != NULL + + return; +} + diff --git a/nfapi/oai_integration/nfapi_pnf.c b/nfapi/oai_integration/nfapi_pnf.c index 4ca02ed929..20db37b123 100644 --- a/nfapi/oai_integration/nfapi_pnf.c +++ b/nfapi/oai_integration/nfapi_pnf.c @@ -1242,6 +1242,8 @@ int pnf_phy_dl_tti_req(gNB_L1_rxtx_proc_t *proc, nfapi_pnf_p7_config_t *pnf_p7, nfapi_nr_dl_tti_request_pdu_t *dl_tti_pdu=&dl_tti_pdu_list[i]; memcpy(dl_tti_pdu,&dl_tti_pdu_list[i],sizeof(nfapi_nr_dl_tti_request_pdu_t)); int SFN=sfn+2; + //if(!&dl_tti_pdu->pdcch_pdu) + printf("interleaversize = %d, coreset_type = %d. \n",dl_tti_pdu->pdcch_pdu.pdcch_pdu_rel15.InterleaverSize,dl_tti_pdu->pdcch_pdu.pdcch_pdu_rel15.CoreSetType); handle_nfapi_nr_pdcch_pdu(gNB, SFN, slot, &dl_tti_pdu->pdcch_pdu); //dl_tti_pdu_list[i].pdcch_pdu.pdcch_pdu_rel15.numDlDci++; // ? // NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() pdcch_vars->num_dci:%d\n", __FUNCTION__, pdcch_vars->num_dci); diff --git a/nfapi/open-nFAPI/nfapi/src/nfapi_p7.c b/nfapi/open-nFAPI/nfapi/src/nfapi_p7.c index 837f33fe6f..8b1060f691 100755 --- a/nfapi/open-nFAPI/nfapi/src/nfapi_p7.c +++ b/nfapi/open-nFAPI/nfapi/src/nfapi_p7.c @@ -277,9 +277,9 @@ static uint8_t pack_dl_tti_pdcch_pdu_rel15_value(void* tlv, uint8_t **ppWritePac push8(value->dci_pdu[i].powerControlOffsetSS, ppWritePackedMsg, end) && push16(value->dci_pdu[i].PayloadSizeBits, ppWritePackedMsg, end) && - pusharray8(value->dci_pdu[i].Payload, DCI_PAYLOAD_BYTE_LEN, value->dci_pdu[i].PayloadSizeBits, ppWritePackedMsg, end)); - + pusharray8(value->dci_pdu[i].Payload, DCI_PAYLOAD_BYTE_LEN, value->dci_pdu[i].PayloadSizeBits, ppWritePackedMsg, end)) return 0; + } // TODO: resolve the packaging of array (currently sending a single element) @@ -307,6 +307,7 @@ static uint8_t pack_dl_tti_pdcch_pdu_rel15_value(void* tlv, uint8_t **ppWritePac static uint8_t pack_dl_tti_pdsch_pdu_rel15_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + printf("packing pdsch pdu. \n"); nfapi_nr_dl_tti_pdsch_pdu_rel15_t* value = (nfapi_nr_dl_tti_pdsch_pdu_rel15_t*)tlv; // TODO: resolve the packaging of array (currently sending a single element) @@ -360,6 +361,7 @@ static uint8_t pack_dl_tti_pdsch_pdu_rel15_value(void* tlv, uint8_t **ppWritePac static uint8_t pack_dl_tti_ssb_pdu_rel15_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + printf("Packing ssb. \n"); nfapi_nr_dl_tti_ssb_pdu_rel15_t* value = (nfapi_nr_dl_tti_ssb_pdu_rel15_t*)tlv; return( @@ -909,7 +911,7 @@ static uint8_t pack_dl_tti_request(void *msg, uint8_t **ppWritePackedMsg, uint8_ //pusharray8(pNfapiMsg->PduIdx[0] ,256,256, ppWritePackedMsg, end) )) return 0; - + int arr[12]; for(int i=0;idl_tti_request_body.nGroup;i++) { @@ -3394,6 +3396,7 @@ int nfapi_nr_p7_message_pack(void *pMessageBuf, void *pPackedBuf, uint32_t packe { case NFAPI_NR_PHY_MSG_TYPE_DL_TTI_REQUEST: result = pack_dl_tti_request(pMessageHeader, &pWritePackedMessage, end, config); + printf("result of pack dl_tti_req is %d. \n",result); break; case NFAPI_NR_PHY_MSG_TYPE_UL_TTI_REQUEST: @@ -3749,7 +3752,7 @@ static uint8_t unpack_dl_tti_csi_rs_pdu_rel15_value(void* tlv, uint8_t **ppReadP static uint8_t unpack_dl_tti_pdcch_pdu_rel15_value(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ +{ nfapi_nr_dl_tti_pdcch_pdu_rel15_t* value = (nfapi_nr_dl_tti_pdcch_pdu_rel15_t*)tlv; for(uint8_t i = 0; i < MAX_DCI_CORESET; ++i) @@ -3765,7 +3768,7 @@ static uint8_t unpack_dl_tti_pdcch_pdu_rel15_value(void* tlv, uint8_t **ppReadPa pull8(ppReadPackedMsg, &value->dci_pdu[i].powerControlOffsetSS, end) && pull16(ppReadPackedMsg, &value->dci_pdu[i].PayloadSizeBits, end) && - pullarray8(ppReadPackedMsg, value->dci_pdu[i].Payload, DCI_PAYLOAD_BYTE_LEN, value->dci_pdu[i].PayloadSizeBits, end)); + pullarray8(ppReadPackedMsg, value->dci_pdu[i].Payload, DCI_PAYLOAD_BYTE_LEN, value->dci_pdu[i].PayloadSizeBits, end)) return 0; } @@ -3847,7 +3850,8 @@ static uint8_t unpack_dl_tti_pdsch_pdu_rel15_value(void* tlv, uint8_t **ppReadPa static uint8_t unpack_dl_tti_ssb_pdu_rel15_value(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ +{ + printf("ssb received and unpacked. \n"); nfapi_nr_dl_tti_ssb_pdu_rel15_t* value = (nfapi_nr_dl_tti_ssb_pdu_rel15_t*)tlv; return( diff --git a/nfapi/open-nFAPI/pnf/src/pnf_p7.c b/nfapi/open-nFAPI/pnf/src/pnf_p7.c index 18891cdee9..fa919ac3a5 100644 --- a/nfapi/open-nFAPI/pnf/src/pnf_p7.c +++ b/nfapi/open-nFAPI/pnf/src/pnf_p7.c @@ -1495,7 +1495,7 @@ uint8_t is_nr_p7_request_in_window(uint16_t sfn,uint16_t slot, const char* name, { uint32_t recv_sfn_slot_dec = NFAPI_SFNSLOT2DEC(sfn,slot); uint32_t current_sfn_slot_dec = NFAPI_SFNSLOT2DEC(phy->sfn,phy->slot); - printf("p7_msg_sfn: %d, p7_msg_slot: %d, phy_sfn:%d , phy_slot:%d \n",sfn,slot,phy->sfn,phy->slot); + //printf("p7_msg_sfn: %d, p7_msg_slot: %d, phy_sfn:%d , phy_slot:%d \n",sfn,slot,phy->sfn,phy->slot); uint8_t in_window = 0; uint8_t timing_window = phy->_public.slot_buffer_size; @@ -1630,7 +1630,6 @@ void pnf_handle_dl_tti_request(void* pRecvMsg, int recvMsgLen, pnf_p7_t* pnf_p7) NFAPI_TRACE(NFAPI_TRACE_INFO, "%s failed to alloced nfapi_dl_tti_request structure\n"); return; } - int unpack_result = nfapi_nr_p7_message_unpack(pRecvMsg, recvMsgLen, req, sizeof(nfapi_nr_dl_tti_request_t), &(pnf_p7->_public.codec_config)); if(unpack_result == 0) @@ -2989,13 +2988,11 @@ void pnf_nr_nfapi_p7_read_dispatch_message(pnf_p7_t* pnf_p7, uint32_t now_hr_tim 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_P7_HEADER_LENGTH]; recvfrom_result = recvfrom(pnf_p7->p7_sock, header_buffer, NFAPI_P7_HEADER_LENGTH, MSG_DONTWAIT | MSG_PEEK, (struct sockaddr*)&remote_addr, &remote_addr_size); - if(recvfrom_result > 0) { // get the segment size diff --git a/nfapi/open-nFAPI/vnf/src/vnf_p7.c b/nfapi/open-nFAPI/vnf/src/vnf_p7.c index ffbc5819bc..8edb168e38 100644 --- a/nfapi/open-nFAPI/vnf/src/vnf_p7.c +++ b/nfapi/open-nFAPI/vnf/src/vnf_p7.c @@ -533,6 +533,7 @@ int vnf_nr_p7_pack_and_send_p7_msg(vnf_p7_t* vnf_p7, nfapi_p7_message_header_t* nfapi_p7_update_transmit_timestamp(buffer, calculate_transmit_timestamp(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); + //printf("segment %d \n", segment); } } else diff --git a/openair1/PHY/NR_TRANSPORT/nr_dlsch_tools.c b/openair1/PHY/NR_TRANSPORT/nr_dlsch_tools.c index 05d6c4c112..384ab5c9b5 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_dlsch_tools.c +++ b/openair1/PHY/NR_TRANSPORT/nr_dlsch_tools.c @@ -32,6 +32,7 @@ */ #include "nr_dlsch.h" +#include "../../../nfapi/oai_integration/vendor_ext.h" extern void set_taus_seed(unsigned int seed_type); @@ -263,13 +264,21 @@ int16_t find_nr_dlsch(uint16_t rnti, PHY_VARS_gNB *gNB,find_type_t type) { for (i=0; idlsch[i]!=NULL,"gNB->dlsch[%d] is null\n",i); AssertFatal(gNB->dlsch[i][0]!=NULL,"gNB->dlsch[%d][0] is null\n",i); - LOG_D(PHY,"searching for rnti %x : dlsch_index %d=> harq_mask %x, rnti %x, first_free_index %d\n", rnti,i, - gNB->dlsch[i][0]->harq_mask,gNB->dlsch[i][0]->rnti,first_free_index); + //LOG_D(PHY,"searching for rnti %x : dlsch_index %d=> harq_mask %x, rnti %x, first_free_index %d\n", rnti,i, + //gNB->dlsch[i][0]->harq_mask,gNB->dlsch[i][0]->rnti,first_free_index); + LOG_D(PHY,"searching for harq_mask %x, rnti %x, gNB->dlsch[i][0]->rnti %x\n", gNB->dlsch[i][0]->harq_mask, rnti, gNB->dlsch[i][0]->rnti); if ((gNB->dlsch[i][0]->harq_mask >0) && (gNB->dlsch[i][0]->rnti==rnti)) return i; - else if ((gNB->dlsch[i][0]->harq_mask == 0) && (first_free_index==-1)) first_free_index=i; + else if ((gNB->dlsch[i][0]->harq_mask == 0) && (first_free_index==-1)) { + //printf("gNB->dlsch[i][0]->harq_mask = %d \n", gNB->dlsch[i][0]->harq_mask);; + first_free_index=i; + } + + } + if (type == SEARCH_EXIST) { + printf("type = %d \n", type); + return -1; } - if (type == SEARCH_EXIST) return -1; if (first_free_index != -1) gNB->dlsch[first_free_index][0]->rnti = 0; return first_free_index; @@ -284,7 +293,10 @@ void nr_fill_dlsch(PHY_VARS_gNB *gNB, uint8_t *sdu) { nfapi_nr_dl_tti_pdsch_pdu_rel15_t *rel15 = &pdsch_pdu->pdsch_pdu_rel15; - + if (NFAPI_MODE == NFAPI_MODE_PNF) { + gNB->dlsch[0][0]->harq_mask = 1; + gNB->dlsch[0][0]->rnti = 4660; + } int dlsch_id = find_nr_dlsch(rel15->rnti,gNB,SEARCH_EXIST); AssertFatal( (dlsch_id>=0) && (dlsch_idrnti,dlsch_id); diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_decoding.c b/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_decoding.c index 429bd9a836..18ab627392 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_decoding.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_decoding.c @@ -577,7 +577,7 @@ uint32_t nr_dlsch_decoding(PHY_VARS_NR_UE *phy_vars_ue, // Fixme: correct type is unsigned, but nrLDPC_decoder and all called behind use signed int if (check_crc((uint8_t*)llrProcBuf,length_dec,harq_process->F,crc_type)) { - LOG_D(PHY,"Segment %u CRC OK\n\033[0m",r); + LOG_I(PHY,"Segment %u CRC OK\n\033[0m",r); if (r==0) { for (int i=0;i<10;i++) LOG_D(PHY,"byte %d : %x\n",i,((uint8_t*)llrProcBuf)[i]); } @@ -587,7 +587,7 @@ uint32_t nr_dlsch_decoding(PHY_VARS_NR_UE *phy_vars_ue, ret = no_iteration_ldpc; } else { - LOG_D(PHY,"CRC NOT OK\n\033[0m"); + LOG_I(PHY,"CRC NOT OK\n\033[0m"); ret = 1 + dlsch->max_ldpc_iterations; } diff --git a/openair1/SCHED_NR/fapi_nr_l1.c b/openair1/SCHED_NR/fapi_nr_l1.c index d65d3b54bb..15c2a5c988 100644 --- a/openair1/SCHED_NR/fapi_nr_l1.c +++ b/openair1/SCHED_NR/fapi_nr_l1.c @@ -104,8 +104,6 @@ void handle_nfapi_nr_pdcch_pdu(PHY_VARS_gNB *gNB, nr_fill_dci(gNB,frame,slot,pdcch_pdu); - - } void handle_nfapi_nr_ul_dci_pdu(PHY_VARS_gNB *gNB, @@ -182,26 +180,30 @@ void nr_schedule_response(NR_Sched_Rsp_t *Sched_INFO){ break; case NFAPI_NR_DL_TTI_PDCCH_PDU_TYPE: + AssertFatal(pdcch_received == 0, "pdcch_received is not 0, we can only handle one PDCCH PDU per slot\n"); - if(NFAPI_MODE != NFAPI_MODE_VNF) + if(NFAPI_MODE != NFAPI_MODE_VNF){ + LOG_D(PHY,"frame %d, slot %d, Got NFAPI_NR_DL_TTI_PDCCH_PDU_TYPE for %d.%d\n",frame,slot,DL_req->SFN,DL_req->Slot); handle_nfapi_nr_pdcch_pdu(gNB, frame, slot, &dl_tti_pdu->pdcch_pdu); - + } pdcch_received = 1; break; case NFAPI_NR_DL_TTI_PDSCH_PDU_TYPE: { - LOG_D(PHY,"frame %d, slot %d, Got NFAPI_NR_DL_TTI_PDSCH_PDU_TYPE for %d.%d\n",frame,slot,DL_req->SFN,DL_req->Slot); + LOG_I(PHY,"frame %d, slot %d, Got NFAPI_NR_DL_TTI_PDSCH_PDU_TYPE for %d.%d\n",frame,slot,DL_req->SFN,DL_req->Slot); nfapi_nr_dl_tti_pdsch_pdu_rel15_t *pdsch_pdu_rel15 = &dl_tti_pdu->pdsch_pdu.pdsch_pdu_rel15; uint16_t pduIndex = pdsch_pdu_rel15->pduIndex; AssertFatal(TX_req->pdu_list[pduIndex].num_TLV == 1, "TX_req->pdu_list[%d].num_TLV %d != 1\n", pduIndex,TX_req->pdu_list[pduIndex].num_TLV); uint8_t *sdu = (uint8_t *)TX_req->pdu_list[pduIndex].TLVs[0].value.direct; - if(NFAPI_MODE != NFAPI_MODE_VNF) + if(NFAPI_MODE != NFAPI_MODE_VNF){ + LOG_D(PHY,"frame %d, slot %d, Got NFAPI_NR_DL_TTI_PDSCH_PDU_TYPE for %d.%d\n",frame,slot,DL_req->SFN,DL_req->Slot); handle_nr_nfapi_pdsch_pdu(gNB,frame,slot,&dl_tti_pdu->pdsch_pdu, sdu); + } } } } @@ -232,15 +234,15 @@ void nr_schedule_response(NR_Sched_Rsp_t *Sched_INFO){ } } - if(NFAPI_MODE != NFAPI_MONOLITHIC && number_ul_tti_pdu>0) - { - oai_nfapi_ul_tti_req(UL_tti_req); - } + // if(NFAPI_MODE != NFAPI_MONOLITHIC && number_ul_tti_pdu>0) + // { + // oai_nfapi_ul_tti_req(UL_tti_req); + // } - if (NFAPI_MODE != NFAPI_MONOLITHIC && Sched_INFO->UL_dci_req->numPdus!=0) - { - oai_nfapi_ul_dci_req(Sched_INFO->UL_dci_req); - } + // if (NFAPI_MODE != NFAPI_MONOLITHIC && Sched_INFO->UL_dci_req->numPdus!=0) + // { + // oai_nfapi_ul_dci_req(Sched_INFO->UL_dci_req); + // } if (NFAPI_MODE != NFAPI_MONOLITHIC) { @@ -248,6 +250,7 @@ void nr_schedule_response(NR_Sched_Rsp_t *Sched_INFO){ { Sched_INFO->DL_req->SFN = frame; Sched_INFO->DL_req->Slot = slot; + printf("DL tti Frame = %d, slot = %d. \n",frame,slot); oai_nfapi_dl_tti_req(Sched_INFO->DL_req); } if (Sched_INFO->TX_req->Number_of_PDUs > 0) diff --git a/openair1/SCHED_NR/phy_frame_config_nr.c b/openair1/SCHED_NR/phy_frame_config_nr.c index 3864b2fcb2..d3b8c77eed 100644 --- a/openair1/SCHED_NR/phy_frame_config_nr.c +++ b/openair1/SCHED_NR/phy_frame_config_nr.c @@ -315,7 +315,7 @@ int nr_slot_select(nfapi_nr_config_request_scf_t *cfg, int nr_frame, int nr_slot if (cfg->cell_config.frame_duplex_type.value == FDD) { return (NR_UPLINK_SLOT | NR_DOWNLINK_SLOT ); } - + if (nr_frame%2 == 0) { for(int symbol_count=0; symbol_counttdd_table.max_tdd_periodicity_list[nr_slot].max_num_of_symbol_per_slot_list[symbol_count].slot_config.value==1) { diff --git a/openair1/SCHED_NR/phy_procedures_nr_gNB.c b/openair1/SCHED_NR/phy_procedures_nr_gNB.c index f775eb9130..55626e386e 100644 --- a/openair1/SCHED_NR/phy_procedures_nr_gNB.c +++ b/openair1/SCHED_NR/phy_procedures_nr_gNB.c @@ -547,6 +547,7 @@ void phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx) LOG_D(PHY,"phy_procedures_gNB_uespec_RX frame %d, slot %d\n",frame_rx,slot_rx); if (gNB->frame_parms.frame_type == TDD) + if(NFAPI_MODE != NFAPI_MODE_VNF) fill_ul_rb_mask(gNB, frame_rx, slot_rx); gNB_I0_measurements(gNB); diff --git a/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c b/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c index e70c353589..bdbfae58e3 100644 --- a/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c +++ b/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c @@ -121,6 +121,7 @@ int8_t nr_ue_scheduled_response(nr_scheduled_response_t *scheduled_response){ dlsch0_harq->Nl=1; dlsch0_harq->mcs_table=dlsch_config_pdu->mcs_table; dlsch0_harq->harq_ack.rx_status = downlink_harq_process(dlsch0_harq, dlsch0->current_harq_pid, dlsch_config_pdu->ndi, dlsch0->rnti_type); + dlsch0_harq->status = ACTIVE; //Gokul if (dlsch0_harq->status != ACTIVE) { // dlsch0_harq->status not ACTIVE may be due to false retransmission. Reset the // following flag to skip PDSCH procedures in that case. diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c index 7201b29596..e356afb339 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c @@ -104,7 +104,10 @@ void clear_nr_nfapi_information(gNB_MAC_INST * gNB, nfapi_nr_tx_data_request_t *TX_req = &gNB->TX_req[0]; gNB->pdu_index[CC_idP] = 0; - + if (NFAPI_MODE == NFAPI_MODE_VNF) + { + memset(pdcch, 0, sizeof(**pdcch) * MAX_NUM_BWP * MAX_NUM_CORESET); + } if (NFAPI_MODE == NFAPI_MONOLITHIC || NFAPI_MODE == NFAPI_MODE_PNF) { // monolithic or PNF DL_req[CC_idP].SFN = frameP; @@ -303,14 +306,13 @@ bool is_xlsch_in_slot(uint64_t bitmap, sub_frame_t slot) { void gNB_dlsch_ulsch_scheduler(module_id_t module_idP, frame_t frame, sub_frame_t slot){ - + gNB_MAC_INST *mac = RC.nrmac[module_idP]; + nfapi_nr_config_request_scf_t *cfg = &mac->config[0]; protocol_ctxt_t ctxt; PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, module_idP, ENB_FLAG_YES, NOT_A_RNTI, frame, slot,module_idP); - int nb_periods_per_frame; const int bwp_id = 1; - gNB_MAC_INST *gNB = RC.nrmac[module_idP]; NR_COMMON_channels_t *cc = gNB->common_channels; NR_ServingCellConfigCommon_t *scc = cc->ServingCellConfigCommon; @@ -356,7 +358,6 @@ void gNB_dlsch_ulsch_scheduler(module_id_t module_idP, int num_slots_per_tdd = (nr_slots_per_frame[*scc->ssbSubcarrierSpacing])/nb_periods_per_frame; const int nr_ulmix_slots = tdd_pattern->nrofUplinkSlots + (tdd_pattern->nrofUplinkSymbols!=0); - start_meas(&RC.nrmac[module_idP]->eNB_scheduler); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_gNB_DLSCH_ULSCH_SCHEDULER,VCD_FUNCTION_IN); @@ -387,9 +388,10 @@ void gNB_dlsch_ulsch_scheduler(module_id_t module_idP, // clear last scheduled slot's content (only)! const int num_slots = nr_slots_per_frame[*scc->ssbSubcarrierSpacing]; const int last_slot = (slot + num_slots - 1) % num_slots; + const int two_slots_back = (slot + num_slots - 2) % num_slots; uint16_t *vrb_map_UL = cc[CC_id].vrb_map_UL; memset(&vrb_map_UL[last_slot * MAX_BWP_SIZE], 0, sizeof(uint16_t) * MAX_BWP_SIZE); - + memset(&vrb_map_UL[two_slots_back * MAX_BWP_SIZE], 0, sizeof(uint16_t) * MAX_BWP_SIZE); clear_nr_nfapi_information(RC.nrmac[module_idP], CC_id, frame, slot); } @@ -434,15 +436,19 @@ void gNB_dlsch_ulsch_scheduler(module_id_t module_idP, // This schedules the DCI for Uplink and subsequently PUSCH { - nr_schedule_ulsch(module_idP, frame, slot, num_slots_per_tdd, nr_ulmix_slots, ulsch_in_slot_bitmap); + if(NFAPI_MODE == NFAPI_MODE_VNF){ + gNB->UL_tti_req_ahead[0][7].SFN = frame;//Added to set the UL_tti_req_ahead SFN in VNF mode for slot 7 + gNB->UL_tti_req_ahead[0][8].SFN = frame;//Added to set the UL_tti_req_ahead SFN in VNF mode for slot 8 + gNB->UL_tti_req_ahead[0][9].SFN = frame;//Added to set the UL_tti_req_ahead SFN in VNF mode for slot 9 + gNB->UL_tti_req[0] = &gNB->UL_tti_req_ahead[0][slot]; + } + //nr_schedule_ulsch(module_idP, frame, slot, num_slots_per_tdd, nr_ulmix_slots, ulsch_in_slot_bitmap); } - // This schedules the DCI for Downlink and PDSCH if (is_xlsch_in_slot(dlsch_in_slot_bitmap, slot)) nr_schedule_ue_spec(module_idP, frame, slot); - - nr_schedule_pucch(module_idP, frame, slot); + //nr_schedule_pucch(module_idP, frame, slot); stop_meas(&RC.nrmac[module_idP]->eNB_scheduler); diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c index 4d491b2843..92cb65aa57 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c @@ -47,6 +47,7 @@ /*Softmodem params*/ #include "executables/softmodem-common.h" +#include "../../../nfapi/oai_integration/vendor_ext.h" //////////////////////////////////////////////////////// /////* DLSCH MAC PDU generation (6.1.2 TS 38.321) *///// @@ -651,7 +652,7 @@ void nr_schedule_ue_spec(module_id_t module_id, frame_t frame, sub_frame_t slot) { gNB_MAC_INST *gNB_mac = RC.nrmac[module_id]; - + /* PREPROCESSOR */ gNB_mac->pre_processor_dl(module_id, frame, slot); @@ -716,6 +717,8 @@ void nr_schedule_ue_spec(module_id_t module_id, int8_t current_harq_pid = sched_ctrl->dl_harq_pid; if (current_harq_pid < 0) { /* PP has not selected a specific HARQ Process, get a new one */ + if (NFAPI_MODE == NFAPI_MODE_VNF) + sched_ctrl->available_dl_harq.head = 0; current_harq_pid = sched_ctrl->available_dl_harq.head; AssertFatal(current_harq_pid >= 0, "no free HARQ process available for UE %d\n", @@ -732,6 +735,9 @@ void nr_schedule_ue_spec(module_id_t module_id, remove_nr_list(&sched_ctrl->retrans_dl_harq, current_harq_pid); } NR_UE_harq_t *harq = &sched_ctrl->harq_processes[current_harq_pid]; + if (NFAPI_MODE == NFAPI_MODE_VNF) { + harq->is_waiting = false; + } DevAssert(!harq->is_waiting); add_tail_nr_list(&sched_ctrl->feedback_dl_harq, current_harq_pid); NR_sched_pucch_t *pucch = &sched_ctrl->sched_pucch[0]; @@ -765,7 +771,15 @@ void nr_schedule_ue_spec(module_id_t module_id, const int bwpid = sched_ctrl->active_bwp->bwp_Id; const int coresetid = sched_ctrl->coreset->controlResourceSetId; nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu = gNB_mac->pdcch_pdu_idx[CC_id][bwpid][coresetid]; + //nfapi_nr_dl_tti_pdcch_pdu_rel15_t temp; + // if(NFAPI_MODE == NFAPI_MODE_VNF){ + // memcpy(temp,gNB_mac->pdcch_pdu_idx[CC_id][bwpid][coresetid],sizeof(nfapi_nr_dl_tti_pdcch_pdu_rel15_t)); + // pdcch_pdu = temp; + + // } + if (!pdcch_pdu) { + printf("creating pdcch pdu, pdcch_pdu = NULL. \n"); 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(nfapi_nr_dl_tti_request_pdu_t)); dl_tti_pdcch_pdu->PDUType = NFAPI_NR_DL_TTI_PDCCH_PDU_TYPE; diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c index 20da8fa30a..e7149c5d65 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c @@ -1666,6 +1666,7 @@ int add_new_nr_ue(module_id_t mod_idP, rnti_t rntiP, NR_CellGroupConfig_t *secon const NR_PDSCH_ServingCellConfig_t *pdsch = servingCellConfig->pdsch_ServingCellConfig->choice.setup; const int nrofHARQ = pdsch->nrofHARQ_ProcessesForPDSCH ? get_nrofHARQ_ProcessesForPDSCH(*pdsch->nrofHARQ_ProcessesForPDSCH) : 8; + printf("nrofHARQ = %d\n", nrofHARQ); // add all available DL HARQ processes for this UE create_nr_list(&sched_ctrl->available_dl_harq, nrofHARQ); for (int harq = 0; harq < nrofHARQ; harq++) diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c index 629b4dc7b0..9e3a611356 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c @@ -235,6 +235,8 @@ void nr_csi_meas_reporting(int Mod_idP, // find free PUCCH that is in order with possibly existing PUCCH // schedulings (other CSI, SR) NR_sched_pucch_t *curr_pucch = &sched_ctrl->sched_pucch[2]; + if(NFAPI_MODE == NFAPI_MODE_VNF) + curr_pucch->csi_bits = 0; AssertFatal(curr_pucch->csi_bits == 0 && !curr_pucch->sr_flag && curr_pucch->dai_c == 0, @@ -458,11 +460,19 @@ bool nr_acknack_scheduling(int mod_id, "illegal number of bits in PUCCH of UE %d\n", UE_id); /* if the currently allocated PUCCH of this UE is full, allocate it */ + pucch->sr_flag = 1; pucch->dai_c = 1; if (pucch->sr_flag + pucch->dai_c == max_acknacks) { /* advance the UL slot information in PUCCH by one so we won't schedule in * the same slot again */ const int f = pucch->frame; const int s = pucch->ul_slot; + if(NFAPI_MODE == NFAPI_MODE_VNF){ + gNB_MAC_INST *gNB = RC.nrmac[mod_id]; + gNB->UL_tti_req_ahead[0][7].SFN = f;//Added to set the UL_tti_req_ahead SFN in VNF mode for slot 7 + gNB->UL_tti_req_ahead[0][8].SFN = f;//Added to set the UL_tti_req_ahead SFN in VNF mode for slot 8 + gNB->UL_tti_req_ahead[0][9].SFN = f;//Added to set the UL_tti_req_ahead SFN in VNF mode for slot 9 + gNB->UL_tti_req[0] = &gNB->UL_tti_req_ahead[0][slot]; + } nr_fill_nfapi_pucch(mod_id, frame, slot, pucch, UE_id); memset(pucch, 0, sizeof(*pucch)); pucch->frame = s == n_slots_frame - 1 ? (f + 1) % 1024 : f; @@ -481,6 +491,7 @@ bool nr_acknack_scheduling(int mod_id, UE_id); nr_fill_nfapi_pucch(mod_id, frame, slot, csi_pucch, UE_id); pucch->frame = s >= n_slots_frame - 2 ? (f + 1) % 1024 : f; + printf("pucch frame filled. \n"); pucch->ul_slot = (s + 2) % n_slots_frame; } } diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c index 574bdd95b4..4a47e4d894 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c @@ -32,6 +32,7 @@ #include "LAYER2/NR_MAC_gNB/mac_proto.h" #include "executables/softmodem-common.h" #include "common/utils/nr/nr_common.h" +#include "nfapi/oai_integration/vendor_ext.h" //38.321 Table 6.1.3.1-1 const uint32_t NR_SHORT_BSR_TABLE[32] = { @@ -882,6 +883,8 @@ void nr_schedule_ulsch(module_id_t module_id, if (harq_id < 0) { /* PP has not selected a specific HARQ Process, get a new one */ harq_id = sched_ctrl->available_ul_harq.head; + // if(NFAPI_MODE == NFAPI_MODE_VNF) + // harq_id = 1; AssertFatal(harq_id >= 0, "no free HARQ process available for UE %d\n", UE_id); diff --git a/openair2/NR_PHY_INTERFACE/NR_IF_Module.c b/openair2/NR_PHY_INTERFACE/NR_IF_Module.c index b183b32aab..d5f6bb2308 100644 --- a/openair2/NR_PHY_INTERFACE/NR_IF_Module.c +++ b/openair2/NR_PHY_INTERFACE/NR_IF_Module.c @@ -105,7 +105,7 @@ void handle_nr_uci(NR_UL_IND_t *UL_info) } UL_info->uci_ind.num_ucis = 0; - + if(NFAPI_MODE != NFAPI_MODE_PNF) // mark corresponding PUCCH resources as free // NOTE: we just assume it is BWP ID 1, to be revised for multiple BWPs RC.nrmac[mod_id]->pucch_index_used[1][slot] = 0; @@ -181,6 +181,7 @@ void NR_UL_indication(NR_UL_IND_t *UL_info) { NR_Sched_Rsp_t *sched_info = &Sched_INFO[module_id][CC_id]; NR_IF_Module_t *ifi = if_inst[module_id]; gNB_MAC_INST *mac = RC.nrmac[module_id]; + nfapi_nr_config_request_scf_t *cfg = &mac->config[CC_id]; LOG_D(PHY,"SFN/SF:%d%d module_id:%d CC_id:%d UL_info[rach_pdus:%d rx_ind:%d crcs:%d]\n", UL_info->frame,UL_info->slot, module_id,CC_id, UL_info->rach_ind.number_of_pdus, @@ -199,8 +200,9 @@ void NR_UL_indication(NR_UL_IND_t *UL_info) { } handle_nr_rach(UL_info); - + handle_nr_uci(UL_info); + // clear HI prior to handling ULSCH mac->UL_dci_req[CC_id].numPdus = 0; handle_nr_ulsch(UL_info); @@ -212,12 +214,12 @@ void NR_UL_indication(NR_UL_IND_t *UL_info) { (UL_info->frame+((UL_info->slot>(9-sl_ahead))?1:0)) % 1024, (UL_info->slot+sl_ahead)%10); */ - nfapi_nr_config_request_scf_t *cfg = &mac->config[CC_id]; + int spf = get_spf(cfg); gNB_dlsch_ulsch_scheduler(module_id, (UL_info->frame+((UL_info->slot>(spf-1-sl_ahead))?1:0)) % 1024, (UL_info->slot+sl_ahead)%spf); - + ifi->CC_mask = 0; sched_info->module_id = module_id; sched_info->CC_id = CC_id; From 86c39286524f42c20a49f2dc7805ac46b81268cb Mon Sep 17 00:00:00 2001 From: Shruthi Date: Fri, 5 Mar 2021 21:09:39 +0530 Subject: [PATCH 02/91] Minor build error fix, README improved --- executables/nr-gnb.c | 4 +--- nfapi/nrNFAPI.md | 21 +++++++++++++++------ 2 files changed, 16 insertions(+), 9 deletions(-) diff --git a/executables/nr-gnb.c b/executables/nr-gnb.c index 5a53c69063..6632289102 100644 --- a/executables/nr-gnb.c +++ b/executables/nr-gnb.c @@ -428,7 +428,7 @@ static void *gNB_L1_thread( void *param ) { if (gNB->CC_id==0) { int next_slot; next_slot = (slot_rx + 1) % 20; - if (rxtx(gNB,frame_rx,next_slot,frame_tx,next_slot,thread_name) < 0) break + if (rxtx(gNB,frame_rx,next_slot,frame_tx,next_slot,thread_name) < 0) break; } if (wait_on_condition(&L1_proc->mutex,&L1_proc->cond,&L1_proc->instance_cnt,thread_name)<0) break; VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_gNB_PROC_RXTX0, 1 ); @@ -445,8 +445,6 @@ static void *gNB_L1_thread( void *param ) { if (rxtx(gNB,frame_rx,slot_rx,frame_tx,slot_tx,thread_name) < 0) break; } - clock_gettime(CLOCK_MONOTONIC,&t); - //printf("\n %d.%d",t.tv_sec,t.tv_nsec); if (release_thread(&L1_proc->mutex,&L1_proc->instance_cnt,thread_name)<0) break; diff --git a/nfapi/nrNFAPI.md b/nfapi/nrNFAPI.md index 299a43fd93..b78a205e84 100644 --- a/nfapi/nrNFAPI.md +++ b/nfapi/nrNFAPI.md @@ -1,17 +1,24 @@ # Procedure to run nFAPI in 5G NR -## Conributed by 5G Testbed IISC -### Developers: Sudhakar B,Mahesh K,Gokul S,Aniq U.R +## Conributed by 5G Testbed IISc + +### Developers: Mahesh K,Gokul S,Aniq U R, Sai Shruthi N, Sudhakar B ## Procedure to Build gNB and UE The regular commands to build gNB and UE can be used ``` -sudo ./build_oai --gNB --UE +sudo ./build_oai --gNB --nrUE ``` ## Procedure to run NR nFAPI using RF-Simulator +### Bring up another loopback interface + +If running for the first time on your computer, or you have restarted your computer, bring up another loopback interface with this command: + +sudo ifconfig lo: 127.0.0.2 netmask 255.0.0.0 up + ### VNF command ``` sudo ./nr-softmodem -O ../../../targets/PROJECTS/GENERIC-LTE-EPC/CONF/rcc.band78.tm1.106PRB.nfapi.conf --nfapi 2 --noS1 --phy-test @@ -28,8 +35,10 @@ sudo RFSIMULATOR=127.0.0.1 ./nr-uesoftmodem --rfsim --phy-test --rrc_config_path ``` ## Procedure to run NR nFAPI using Hardware -Will be updated as we have not yet currently tested on hardware + +To be updated. ## Notes -* In order to acheive the synchronization between VNF and PNF and receive the P7 messages within the timing window the order in which we should run the modules on different terminals is UE->VNF->PNF -* Currently only downlink is functional and working as we are still working on uplink functionality +* If running for the first time on local branch, run in the following order - VNF then PNF. This is so that necessary files are generated for the UE to run. Stop this run (it's ok if it stops on its own due to an error). From every subsequent run follow the next bullet. +* In order to achieve synchronization between the VNF and PNF, and receive P7 messages within the timing window, the order in which we should run the modules on different terminals is UE->VNF->PNF. +* Currently downlink transmission from gNB to UE is partially functional and we are working on improving this. Uplink P7 messages are disabled and we will work on uplink integration after completing downlink. From 9a623a2b451e87db3ba47a663f3d6e23e0586c18 Mon Sep 17 00:00:00 2001 From: Shruthi Date: Fri, 5 Mar 2021 21:45:38 +0530 Subject: [PATCH 03/91] pdcch pdu pack/unpack fix --- nfapi/open-nFAPI/nfapi/src/nfapi_p7.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/nfapi/open-nFAPI/nfapi/src/nfapi_p7.c b/nfapi/open-nFAPI/nfapi/src/nfapi_p7.c index 8b1060f691..9f90d8852c 100755 --- a/nfapi/open-nFAPI/nfapi/src/nfapi_p7.c +++ b/nfapi/open-nFAPI/nfapi/src/nfapi_p7.c @@ -267,7 +267,7 @@ static uint8_t pack_dl_tti_pdcch_pdu_rel15_value(void* tlv, uint8_t **ppWritePac for(uint8_t i = 0; i < MAX_DCI_CORESET; ++i) { - if(!push16(value->dci_pdu[i].RNTI, ppWritePackedMsg, end) && + if(!(push16(value->dci_pdu[i].RNTI, ppWritePackedMsg, end) && push16(value->dci_pdu[i].ScramblingId, ppWritePackedMsg, end) && push16(value->dci_pdu[i].ScramblingRNTI, ppWritePackedMsg, end) && @@ -277,7 +277,7 @@ static uint8_t pack_dl_tti_pdcch_pdu_rel15_value(void* tlv, uint8_t **ppWritePac push8(value->dci_pdu[i].powerControlOffsetSS, ppWritePackedMsg, end) && push16(value->dci_pdu[i].PayloadSizeBits, ppWritePackedMsg, end) && - pusharray8(value->dci_pdu[i].Payload, DCI_PAYLOAD_BYTE_LEN, value->dci_pdu[i].PayloadSizeBits, ppWritePackedMsg, end)) + pusharray8(value->dci_pdu[i].Payload, value->dci_pdu[i].PayloadSizeBits, value->dci_pdu[i].PayloadSizeBits, ppWritePackedMsg, end))) return 0; } @@ -3757,7 +3757,7 @@ static uint8_t unpack_dl_tti_pdcch_pdu_rel15_value(void* tlv, uint8_t **ppReadPa for(uint8_t i = 0; i < MAX_DCI_CORESET; ++i) { - if(!pull16(ppReadPackedMsg, &value->dci_pdu[i].RNTI, end) && + if(!(pull16(ppReadPackedMsg, &value->dci_pdu[i].RNTI, end) && pull16(ppReadPackedMsg, &value->dci_pdu[i].ScramblingId, end) && pull16(ppReadPackedMsg, &value->dci_pdu[i].ScramblingRNTI, end) && @@ -3768,7 +3768,7 @@ static uint8_t unpack_dl_tti_pdcch_pdu_rel15_value(void* tlv, uint8_t **ppReadPa pull8(ppReadPackedMsg, &value->dci_pdu[i].powerControlOffsetSS, end) && pull16(ppReadPackedMsg, &value->dci_pdu[i].PayloadSizeBits, end) && - pullarray8(ppReadPackedMsg, value->dci_pdu[i].Payload, DCI_PAYLOAD_BYTE_LEN, value->dci_pdu[i].PayloadSizeBits, end)) + pullarray8(ppReadPackedMsg, value->dci_pdu[i].Payload, value->dci_pdu[i].PayloadSizeBits, value->dci_pdu[i].PayloadSizeBits, end))) return 0; } From 6e61393f7e22dd421ca6dd89434088ee93889135 Mon Sep 17 00:00:00 2001 From: Shruthi Date: Sat, 6 Mar 2021 15:18:02 +0530 Subject: [PATCH 04/91] DCI payload corrections in nFAPI mode --- openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c index 92cb65aa57..fb704dc964 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c @@ -57,6 +57,9 @@ #define WORD 32 //#define SIZE_OF_POINTER sizeof (void *) +int harq_rounds = 0; +int harq_pid = 0; + // Compute and write all MAC CEs and subheaders, and return number of written // bytes int nr_write_ce_dlsch_pdu(module_id_t module_idP, @@ -821,6 +824,14 @@ void nr_schedule_ue_spec(module_id_t module_id, pdsch_pdu->mcsIndex[0] = sched_ctrl->mcs; pdsch_pdu->mcsTable[0] = sched_ctrl->mcsTableIdx; pdsch_pdu->rvIndex[0] = nr_rv_round_map[harq->round]; + if (NFAPI_MODE == NFAPI_MODE_VNF){ // done since uplink isnt operational yet which means harq structures dont get filled properly + pdsch_pdu->rvIndex[0] = nr_rv_round_map[harq_rounds]; + if (harq_rounds % 5 == 0 && harq_rounds!=0){ + harq_rounds = 0; + harq_pid = (harq_pid + 1) % 16; + } + harq_rounds++; + } pdsch_pdu->TBSize[0] = TBS; pdsch_pdu->dataScramblingId = *scc->physCellId; @@ -932,6 +943,10 @@ void nr_schedule_ue_spec(module_id_t module_id, const int dci_format = f ? NR_DL_DCI_FORMAT_1_1 : NR_DL_DCI_FORMAT_1_0; const int rnti_type = NR_RNTI_C; + if (NFAPI_MODE == NFAPI_MODE_VNF){ + dci_payload.harq_pid = harq_pid; + dci_payload.tpc = 2; + } fill_dci_pdu_rel15(scc, UE_info->secondaryCellGroup[UE_id], dci_pdu, From 39577ba0d802fe3de26ee55d8807c6c92c6c403e Mon Sep 17 00:00:00 2001 From: Mahesh Date: Thu, 11 Mar 2021 12:49:40 +0530 Subject: [PATCH 05/91] UL P7 messages and UL scheduling re-enabled. Disabled HARQ from the UE side --> DL CRC OK --- nfapi/open-nFAPI/nfapi/src/nfapi.c | 2 +- nfapi/open-nFAPI/nfapi/src/nfapi_p7.c | 16 +++---- nfapi/open-nFAPI/pnf/src/pnf_p7.c | 2 +- openair1/SCHED_NR/fapi_nr_l1.c | 16 +++---- openair1/SCHED_NR_UE/harq_nr.c | 2 +- openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c | 6 +-- .../LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c | 3 +- .../LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c | 44 +++++++++++-------- 8 files changed, 49 insertions(+), 42 deletions(-) diff --git a/nfapi/open-nFAPI/nfapi/src/nfapi.c b/nfapi/open-nFAPI/nfapi/src/nfapi.c index ba800c3634..6ca64138f2 100644 --- a/nfapi/open-nFAPI/nfapi/src/nfapi.c +++ b/nfapi/open-nFAPI/nfapi/src/nfapi.c @@ -189,7 +189,7 @@ uint8_t pull8(uint8_t **in, uint8_t *out, uint8_t *end) return 1; } else - { + { NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s no space in buffer\n", __FUNCTION__); return 0; } diff --git a/nfapi/open-nFAPI/nfapi/src/nfapi_p7.c b/nfapi/open-nFAPI/nfapi/src/nfapi_p7.c index 9f90d8852c..49ecba5eac 100755 --- a/nfapi/open-nFAPI/nfapi/src/nfapi_p7.c +++ b/nfapi/open-nFAPI/nfapi/src/nfapi_p7.c @@ -2047,7 +2047,7 @@ static uint8_t pack_ul_dci_pdu_list_value(void* tlv, uint8_t **ppWritePackedMsg, for(uint8_t i = 0; i < MAX_DCI_CORESET; ++i) { - if(!push16(value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].RNTI, ppWritePackedMsg, end) && + if(!(push16(value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].RNTI, ppWritePackedMsg, end) && push16(value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].ScramblingId, ppWritePackedMsg, end) && push16(value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].ScramblingRNTI, ppWritePackedMsg, end) && @@ -2058,7 +2058,7 @@ static uint8_t pack_ul_dci_pdu_list_value(void* tlv, uint8_t **ppWritePackedMsg, push8(value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].powerControlOffsetSS, ppWritePackedMsg, end) && push16(value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].PayloadSizeBits, ppWritePackedMsg, end) && - pusharray8(value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].Payload, DCI_PAYLOAD_BYTE_LEN, value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].PayloadSizeBits, ppWritePackedMsg, end)); + pusharray8(value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].Payload, value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].PayloadSizeBits, value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].PayloadSizeBits, ppWritePackedMsg, end))) return 0; } @@ -2078,7 +2078,9 @@ static uint8_t pack_ul_dci_pdu_list_value(void* tlv, uint8_t **ppWritePackedMsg, push8(value->pdcch_pdu.pdcch_pdu_rel15.RegBundleSize, ppWritePackedMsg, end) && push8(value->pdcch_pdu.pdcch_pdu_rel15.InterleaverSize, ppWritePackedMsg, end) && push8(value->pdcch_pdu.pdcch_pdu_rel15.CoreSetType, ppWritePackedMsg, end) && - push16(value->pdcch_pdu.pdcch_pdu_rel15.ShiftIndex, ppWritePackedMsg, end)); + push16(value->pdcch_pdu.pdcch_pdu_rel15.ShiftIndex, ppWritePackedMsg, end) && + push8(value->pdcch_pdu.pdcch_pdu_rel15.precoderGranularity, ppWritePackedMsg, end) && + push16(value->pdcch_pdu.pdcch_pdu_rel15.numDlDci, ppWritePackedMsg, end)); } @@ -5834,10 +5836,9 @@ static uint8_t unpack_hi_dci0_request_body_value(void *tlv, uint8_t **ppReadPack static uint8_t unpack_ul_dci_pdu_list_value(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg) { nfapi_nr_ul_dci_request_pdus_t* value = (nfapi_nr_ul_dci_request_pdus_t*)msg; - for(uint8_t i = 0; i < MAX_DCI_CORESET; ++i) { - if(!pull16(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].RNTI, end) && + if(!(pull16(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].RNTI, end) && pull16(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].ScramblingId, end) && pull16(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].ScramblingRNTI, end) && @@ -5848,7 +5849,7 @@ static uint8_t unpack_ul_dci_pdu_list_value(uint8_t **ppReadPackedMsg, uint8_t * pull8(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].powerControlOffsetSS, end) && pull16(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].PayloadSizeBits, end) && - pullarray8(ppReadPackedMsg, value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].Payload, DCI_PAYLOAD_BYTE_LEN, value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].PayloadSizeBits, end)); + pullarray8(ppReadPackedMsg, value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].Payload, value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].PayloadSizeBits, value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].PayloadSizeBits, end))) return 0; } @@ -5869,7 +5870,6 @@ static uint8_t unpack_ul_dci_pdu_list_value(uint8_t **ppReadPackedMsg, uint8_t * pull8(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.InterleaverSize, end) && pull8(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.CoreSetType, end) && pull16(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.ShiftIndex, end) && - pull8(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.precoderGranularity, end) && pull16(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.numDlDci, end)); @@ -8052,7 +8052,7 @@ int nfapi_nr_p7_message_unpack(void *pMessageBuf, uint32_t messageBufLen, void * nfapi_p7_message_header_t *pMessageHeader = (nfapi_p7_message_header_t*)pUnpackedBuf; uint8_t *pReadPackedMessage = pMessageBuf; uint8_t *end = pMessageBuf + messageBufLen; - + if (pMessageBuf == NULL || pUnpackedBuf == NULL) { NFAPI_TRACE(NFAPI_TRACE_ERROR, "P7 unpack supplied pointers are null\n"); diff --git a/nfapi/open-nFAPI/pnf/src/pnf_p7.c b/nfapi/open-nFAPI/pnf/src/pnf_p7.c index fa919ac3a5..fefd822bb0 100644 --- a/nfapi/open-nFAPI/pnf/src/pnf_p7.c +++ b/nfapi/open-nFAPI/pnf/src/pnf_p7.c @@ -2009,7 +2009,7 @@ void pnf_handle_ul_dci_request(void* pRecvMsg, int recvMsgLen, pnf_p7_t* pnf_p7) } else { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "Failed to unpack hi_dci0_req\n"); + NFAPI_TRACE(NFAPI_TRACE_ERROR, "Failed to unpack UL DCI req\n"); deallocate_nfapi_ul_dci_request(req, pnf_p7); } } diff --git a/openair1/SCHED_NR/fapi_nr_l1.c b/openair1/SCHED_NR/fapi_nr_l1.c index 15c2a5c988..2aa09dea80 100644 --- a/openair1/SCHED_NR/fapi_nr_l1.c +++ b/openair1/SCHED_NR/fapi_nr_l1.c @@ -234,15 +234,15 @@ void nr_schedule_response(NR_Sched_Rsp_t *Sched_INFO){ } } - // if(NFAPI_MODE != NFAPI_MONOLITHIC && number_ul_tti_pdu>0) - // { - // oai_nfapi_ul_tti_req(UL_tti_req); - // } + if(NFAPI_MODE != NFAPI_MONOLITHIC && number_ul_tti_pdu>0) + { + oai_nfapi_ul_tti_req(UL_tti_req); + } - // if (NFAPI_MODE != NFAPI_MONOLITHIC && Sched_INFO->UL_dci_req->numPdus!=0) - // { - // oai_nfapi_ul_dci_req(Sched_INFO->UL_dci_req); - // } + if (NFAPI_MODE != NFAPI_MONOLITHIC && Sched_INFO->UL_dci_req->numPdus!=0) + { + oai_nfapi_ul_dci_req(Sched_INFO->UL_dci_req); + } if (NFAPI_MODE != NFAPI_MONOLITHIC) { diff --git a/openair1/SCHED_NR_UE/harq_nr.c b/openair1/SCHED_NR_UE/harq_nr.c index 85f6d90bbe..0dcc057867 100644 --- a/openair1/SCHED_NR_UE/harq_nr.c +++ b/openair1/SCHED_NR_UE/harq_nr.c @@ -472,7 +472,7 @@ harq_result_t downlink_harq_process(NR_DL_UE_HARQ_t *dl_harq, int harq_pid, int dl_harq->round = 0; dl_harq->status = ACTIVE; dl_harq->DCINdi = ndi; - dl_harq->first_tx = 0; + //dl_harq->first_tx = 0; result_harq = NEW_TRANSMISSION_HARQ; diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c index e2d5db0799..4ada9eb9f3 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c @@ -394,10 +394,8 @@ void gNB_dlsch_ulsch_scheduler(module_id_t module_idP, // clear last scheduled slot's content (only)! const int num_slots = nr_slots_per_frame[*scc->ssbSubcarrierSpacing]; const int last_slot = (slot + num_slots - 1) % num_slots; - const int two_slots_back = (slot + num_slots - 2) % num_slots; uint16_t *vrb_map_UL = cc[CC_id].vrb_map_UL; memset(&vrb_map_UL[last_slot * MAX_BWP_SIZE], 0, sizeof(uint16_t) * MAX_BWP_SIZE); - memset(&vrb_map_UL[two_slots_back * MAX_BWP_SIZE], 0, sizeof(uint16_t) * MAX_BWP_SIZE); clear_nr_nfapi_information(RC.nrmac[module_idP], CC_id, frame, slot); } @@ -448,13 +446,13 @@ void gNB_dlsch_ulsch_scheduler(module_id_t module_idP, gNB->UL_tti_req_ahead[0][9].SFN = frame;//Added to set the UL_tti_req_ahead SFN in VNF mode for slot 9 gNB->UL_tti_req[0] = &gNB->UL_tti_req_ahead[0][slot]; } - //nr_schedule_ulsch(module_idP, frame, slot, num_slots_per_tdd, nr_ulmix_slots, ulsch_in_slot_bitmap); + nr_schedule_ulsch(module_idP, frame, slot, num_slots_per_tdd, nr_ulmix_slots, ulsch_in_slot_bitmap); } // This schedules the DCI for Downlink and PDSCH if (is_xlsch_in_slot(dlsch_in_slot_bitmap, slot)) nr_schedule_ue_spec(module_idP, frame, slot); - //nr_schedule_pucch(module_idP, frame, slot); + nr_schedule_pucch(module_idP, frame, slot); stop_meas(&RC.nrmac[module_idP]->eNB_scheduler); diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c index 9e3a611356..9842d9137f 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c @@ -460,7 +460,8 @@ bool nr_acknack_scheduling(int mod_id, "illegal number of bits in PUCCH of UE %d\n", UE_id); /* if the currently allocated PUCCH of this UE is full, allocate it */ - pucch->sr_flag = 1; pucch->dai_c = 1; + if (NFAPI_MODE == NFAPI_MODE_VNF) + pucch->sr_flag = 1; pucch->dai_c = 1; if (pucch->sr_flag + pucch->dai_c == max_acknacks) { /* advance the UL slot information in PUCCH by one so we won't schedule in * the same slot again */ diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c index db7dde0140..94aa4f5159 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c @@ -883,30 +883,38 @@ void nr_schedule_ulsch(module_id_t module_id, uint16_t rnti = UE_info->rnti[UE_id]; 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; - // if(NFAPI_MODE == NFAPI_MODE_VNF) - // harq_id = 1; - AssertFatal(harq_id >= 0, - "no free HARQ process available for UE %d\n", - UE_id); - 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); + if (NFAPI_MODE == NFAPI_MODE_VNF) + harq_id = 1; + else + { + if (harq_id < 0) { + /* PP has not selected a specific HARQ Process, get a new one */ + harq_id = sched_ctrl->available_ul_harq.head; + // if(NFAPI_MODE == NFAPI_MODE_VNF) + // harq_id = 1; + AssertFatal(harq_id >= 0, + "no free HARQ process available for UE %d\n", + UE_id); + 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); add_tail_nr_list(&sched_ctrl->feedback_ul_harq, harq_id); cur_harq->feedback_slot = sched_pusch->slot; cur_harq->is_waiting = true; + if (NFAPI_MODE == NFAPI_MODE_VNF) + cur_harq->is_waiting = 0; + int rnti_types[2] = { NR_RNTI_C, 0 }; From b232c4347760b127ffa0737c6d0cde292cda9de1 Mon Sep 17 00:00:00 2001 From: Mahesh Date: Tue, 16 Mar 2021 12:49:46 +0530 Subject: [PATCH 06/91] Uplink improvement --- executables/nr-gnb.c | 36 +++-- executables/nr-ru.c | 8 +- nfapi/oai_integration/nfapi_pnf.c | 1 + nfapi/open-nFAPI/pnf/src/pnf_p7.c | 53 ++++--- openair1/PHY/NR_TRANSPORT/nr_ulsch_decoding.c | 8 +- openair1/PHY/NR_TRANSPORT/pucch_rx.c | 17 ++- openair1/SCHED_NR/phy_procedures_nr_gNB.c | 7 +- .../LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c | 141 +++++++++--------- openair2/NR_PHY_INTERFACE/NR_IF_Module.c | 23 +-- 9 files changed, 172 insertions(+), 122 deletions(-) diff --git a/executables/nr-gnb.c b/executables/nr-gnb.c index 6632289102..5e63c54ab8 100644 --- a/executables/nr-gnb.c +++ b/executables/nr-gnb.c @@ -253,25 +253,33 @@ static inline int rxtx(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx, int frame_t // RX processing int tx_slot_type; int rx_slot_type; - if(NFAPI_MODE == NFAPI_MODE_VNF) { - if ((slot_tx==8) || (slot_rx==8) || (slot_tx==9) || (slot_rx==9) || (slot_tx==18) || (slot_rx==18) || (slot_tx==19) || (slot_rx==19)) { - tx_slot_type = NR_UPLINK_SLOT; - rx_slot_type = NR_UPLINK_SLOT; - } - else if ((slot_tx==7) || (slot_rx==7) || (slot_tx==17) || (slot_rx==17)) { - tx_slot_type = NR_MIXED_SLOT; - rx_slot_type = NR_MIXED_SLOT; - } - else { - tx_slot_type = NR_DOWNLINK_SLOT; - rx_slot_type = NR_DOWNLINK_SLOT; - } + if(NFAPI_MODE != NFAPI_MONOLITHIC) { //slot selection routines not working properly in nfapi, so temporarily hardcoding + if ((slot_tx==8) || (slot_tx==9) || (slot_tx==18) || (slot_tx==19)) { //tx slot config + tx_slot_type = NR_UPLINK_SLOT; + } + else if ((slot_tx==7) || (slot_tx==17)) { + tx_slot_type = NR_MIXED_SLOT; + } + else { + tx_slot_type = NR_DOWNLINK_SLOT;; + } + + if ((slot_rx==8) || (slot_rx==9) || (slot_rx==18) || (slot_rx==19)) { // rx slot config + rx_slot_type = NR_UPLINK_SLOT; + } + else if ((slot_rx==7) || (slot_rx==17)) { + rx_slot_type = NR_MIXED_SLOT; + } + else { + rx_slot_type = NR_DOWNLINK_SLOT;; + } + + } else { tx_slot_type = nr_slot_select(cfg,frame_tx,slot_tx); rx_slot_type = nr_slot_select(cfg,frame_rx,slot_rx); } - if (rx_slot_type == NR_UPLINK_SLOT || rx_slot_type == NR_MIXED_SLOT) { // UE-specific RX processing for subframe n // TODO: check if this is correct for PARALLEL_RU_L1_TRX_SPLIT diff --git a/executables/nr-ru.c b/executables/nr-ru.c index 1184a9d80c..d0bc1a3e0e 100644 --- a/executables/nr-ru.c +++ b/executables/nr-ru.c @@ -1607,7 +1607,13 @@ void *ru_thread( void *param ) { // do RX front-end processing (frequency-shift, dft) if needed - int slot_type = nr_slot_select(cfg,proc->frame_rx,proc->tti_rx); + //int slot_type = nr_slot_select(cfg,proc->frame_rx,proc->tti_rx); + //if (NFAPI_MODE == NFAPI_MODE_PNF) + int slot_type; + if (slot ==7) + slot_type = NR_MIXED_SLOT; + if (slot == 8) + slot_type = NR_UPLINK_SLOT; if (slot_type == NR_UPLINK_SLOT || slot_type == NR_MIXED_SLOT) { //if (proc->tti_rx==8) { diff --git a/nfapi/oai_integration/nfapi_pnf.c b/nfapi/oai_integration/nfapi_pnf.c index 20db37b123..e744fcbb24 100644 --- a/nfapi/oai_integration/nfapi_pnf.c +++ b/nfapi/oai_integration/nfapi_pnf.c @@ -1475,6 +1475,7 @@ int pnf_phy_ul_tti_req(gNB_L1_rxtx_proc_t *proc, nfapi_pnf_p7_config_t *pnf_p7, switch (ul_tti_pdu_list[i].pdu_type) { case NFAPI_NR_UL_CONFIG_PUSCH_PDU_TYPE: //LOG_D(PHY,"frame %d, slot %d, Got NFAPI_NR_UL_TTI_PUSCH_PDU_TYPE for %d.%d\n", frame, slot, UL_tti_req->SFN, UL_tti_req->Slot); + //curr_sfn = curr_sfn + 3; //Gokul nr_fill_ulsch(gNB,curr_sfn, curr_slot, &ul_tti_pdu_list[i].pusch_pdu); break; case NFAPI_NR_UL_CONFIG_PUCCH_PDU_TYPE: diff --git a/nfapi/open-nFAPI/pnf/src/pnf_p7.c b/nfapi/open-nFAPI/pnf/src/pnf_p7.c index fefd822bb0..14b4846846 100644 --- a/nfapi/open-nFAPI/pnf/src/pnf_p7.c +++ b/nfapi/open-nFAPI/pnf/src/pnf_p7.c @@ -1007,36 +1007,34 @@ int pnf_p7_slot_ind(pnf_p7_t* pnf_p7, uint16_t phy_id, uint16_t sfn, uint16_t sl // if(tx_slot_buffer->slot == slot_tx && tx_slot_buffer->sfn == sfn_tx) // { - if(tx_slot_buffer->tx_data_req != 0) - { + if(tx_slot_buffer->tx_data_req != 0) + { - if(pnf_p7->_public.tx_data_req_fn) - { - (pnf_p7->_public.tx_data_req_fn)(&(pnf_p7->_public), tx_slot_buffer->tx_data_req); - } + if(pnf_p7->_public.tx_data_req_fn) + { + (pnf_p7->_public.tx_data_req_fn)(&(pnf_p7->_public), tx_slot_buffer->tx_data_req); } - else + } + else + { + // send dummy + if(pnf_p7->_public.tx_data_req_fn && pnf_p7->_public.dummy_slot.tx_data_req) { - // send dummy - if(pnf_p7->_public.tx_data_req_fn && pnf_p7->_public.dummy_slot.tx_data_req) - { - pnf_p7->_public.dummy_slot.tx_data_req->SFN = sfn_tx; - pnf_p7->_public.dummy_slot.tx_data_req->Slot = slot_tx; + pnf_p7->_public.dummy_slot.tx_data_req->SFN = sfn_tx; + pnf_p7->_public.dummy_slot.tx_data_req->Slot = slot_tx; - (pnf_p7->_public.tx_data_req_fn)(&(pnf_p7->_public), pnf_p7->_public.dummy_slot.tx_data_req); - } + (pnf_p7->_public.tx_data_req_fn)(&(pnf_p7->_public), pnf_p7->_public.dummy_slot.tx_data_req); } - //} + } + - if( tx_slot_buffer->dl_tti_req != 0) // ADDED & TO BYPASS ERROR + if(tx_slot_buffer->dl_tti_req != 0) { if(pnf_p7->_public.dl_tti_req_fn) { (pnf_p7->_public.dl_tti_req_fn)(NULL, &(pnf_p7->_public), tx_slot_buffer->dl_tti_req); } } - - else { // send dummy @@ -1048,6 +1046,7 @@ int pnf_p7_slot_ind(pnf_p7_t* pnf_p7, uint16_t phy_id, uint16_t sfn, uint16_t sl } } + if(tx_slot_buffer->ul_dci_req!= 0) { if(pnf_p7->_public.ul_dci_req_fn) @@ -1065,6 +1064,23 @@ int pnf_p7_slot_ind(pnf_p7_t* pnf_p7, uint16_t phy_id, uint16_t sfn, uint16_t sl (pnf_p7->_public.ul_dci_req_fn)(NULL, &(pnf_p7->_public), pnf_p7->_public.dummy_slot.ul_dci_req); } } + if(tx_slot_buffer->ul_tti_req != 0) + { + if(pnf_p7->_public.ul_tti_req_fn) + { + (pnf_p7->_public.ul_tti_req_fn)(NULL, &(pnf_p7->_public), tx_slot_buffer->ul_tti_req); + } + } + else + { + // send dummy + if(pnf_p7->_public.ul_tti_req_fn && pnf_p7->_public.dummy_slot.ul_tti_req) + { + pnf_p7->_public.dummy_slot.ul_tti_req->SFN = sfn_tx; + pnf_p7->_public.dummy_slot.ul_tti_req->Slot = slot_tx; + (pnf_p7->_public.ul_tti_req_fn)(NULL, &(pnf_p7->_public), pnf_p7->_public.dummy_slot.ul_tti_req); + } + } if(tx_slot_buffer->dl_tti_req != 0) { deallocate_nfapi_dl_tti_request(tx_slot_buffer->dl_tti_req, pnf_p7); @@ -1101,7 +1117,6 @@ int pnf_p7_slot_ind(pnf_p7_t* pnf_p7, uint16_t phy_id, uint16_t sfn, uint16_t sl { (pnf_p7->_public.ul_tti_req_fn)(NULL, &(pnf_p7->_public), slot_buffer->ul_tti_req); } - //deallocate_nfapi_ul_config_request(subframe_buffer->ul_config_req, pnf_p7); } else { diff --git a/openair1/PHY/NR_TRANSPORT/nr_ulsch_decoding.c b/openair1/PHY/NR_TRANSPORT/nr_ulsch_decoding.c index d990176d79..0b0851dddb 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_ulsch_decoding.c +++ b/openair1/PHY/NR_TRANSPORT/nr_ulsch_decoding.c @@ -430,14 +430,14 @@ void nr_processULSegment(void* arg) { p_procTime); if (check_crc((uint8_t*)llrProcBuf,length_dec,ulsch_harq->F,crc_type)) { -#ifdef PRINT_CRC_CHECK +// #ifdef PRINT_CRC_CHECK LOG_I(PHY, "Segment %d CRC OK\n",r); -#endif +// #endif rdata->decodeIterations = no_iteration_ldpc; } else { -#ifdef PRINT_CRC_CHECK +// #ifdef PRINT_CRC_CHECK LOG_I(PHY, "CRC NOK\n"); -#endif +// #endif rdata->decodeIterations = max_ldpc_iterations + 1; } diff --git a/openair1/PHY/NR_TRANSPORT/pucch_rx.c b/openair1/PHY/NR_TRANSPORT/pucch_rx.c index 2d1fdff4be..3d2f27476a 100644 --- a/openair1/PHY/NR_TRANSPORT/pucch_rx.c +++ b/openair1/PHY/NR_TRANSPORT/pucch_rx.c @@ -47,6 +47,7 @@ #include "PHY/NR_REFSIG/nr_refsig.h" #include "common/utils/LOG/log.h" #include "common/utils/LOG/vcd_signal_dumper.h" +#include "nfapi/oai_integration/vendor_ext.h" #include "T.h" @@ -86,7 +87,8 @@ void nr_fill_pucch(PHY_VARS_gNB *gNB, int frame, int slot, nfapi_nr_pucch_pdu_t *pucch_pdu) { - + if (NFAPI_MODE == NFAPI_MODE_PNF) + gNB->pucch[0]->active = 0; //check if ture in monolithic mode int id = nr_find_pucch(pucch_pdu->rnti,frame,slot,gNB); AssertFatal( (id>=0) && (idrnti,id); @@ -164,10 +166,15 @@ void nr_decode_pucch0(PHY_VARS_gNB *gNB, int slot, nfapi_nr_uci_pucch_pdu_format_0_1_t* uci_pdu, nfapi_nr_pucch_pdu_t* pucch_pdu) { - + printf("Inside nr_decode_pucch0. \n"); int32_t **rxdataF = gNB->common_vars.rxdataF; NR_DL_FRAME_PARMS *frame_parms = &gNB->frame_parms; - + //Gokul + // printf("rxdataf buff: \n"); + // for(int i = 1;i<=5*7*14*512;++i){ + // if(gNB->RU_list[0]->common.rxdataF[0][i] != 0) + // printf("%d ",gNB->RU_list[0]->common.rxdataF[0][i]); + // } int nr_sequences; const uint8_t *mcs; @@ -1085,7 +1092,7 @@ void nr_decode_pucch2(PHY_VARS_gNB *gNB, int slot, nfapi_nr_uci_pucch_pdu_format_2_3_4_t* uci_pdu, nfapi_nr_pucch_pdu_t* pucch_pdu) { - + printf("Inside nr_decode_pucch2. \n"); int32_t **rxdataF = gNB->common_vars.rxdataF; NR_DL_FRAME_PARMS *frame_parms = &gNB->frame_parms; //pucch_GroupHopping_t pucch_GroupHopping = pucch_pdu->group_hop_flag + (pucch_pdu->sequence_hop_flag<<1); @@ -1465,7 +1472,7 @@ void nr_decode_pucch2(PHY_VARS_gNB *gNB, } } // cw loop corr_dB = dB_fixed64((uint64_t)corr); - LOG_D(PHY,"cw_ML %d, metric %d dB\n",cw_ML,corr_dB); + LOG_I(PHY,"cw_ML %d, metric %d dB\n",cw_ML,corr_dB); decodedPayload[0]=(uint64_t)cw_ML; } else { // polar coded case diff --git a/openair1/SCHED_NR/phy_procedures_nr_gNB.c b/openair1/SCHED_NR/phy_procedures_nr_gNB.c index 9f97b7eadf..7e7aff0a09 100644 --- a/openair1/SCHED_NR/phy_procedures_nr_gNB.c +++ b/openair1/SCHED_NR/phy_procedures_nr_gNB.c @@ -560,6 +560,8 @@ void phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx) for (int i=0;ipucch[i]; if (pucch) { + if (NFAPI_MODE == NFAPI_MODE_PNF) + pucch->frame = frame_rx; if ((pucch->active == 1) && (pucch->frame == frame_rx) && (pucch->slot == slot_rx) ) { @@ -620,12 +622,15 @@ void phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx) for (harq_pid=0;harq_pidharq_processes[harq_pid]; AssertFatal(ulsch_harq!=NULL,"harq_pid %d is not allocated\n",harq_pid); + //printf("ulsch_harq->frame = %d, frame_rx = %d \n", ulsch_harq->frame, frame_rx); + if (NFAPI_MODE == NFAPI_MODE_PNF) + ulsch_harq->frame = frame_rx; if ((ulsch_harq->status == NR_ACTIVE) && (ulsch_harq->frame == frame_rx) && (ulsch_harq->slot == slot_rx) && (ulsch_harq->handled == 0)){ - LOG_D(PHY, "PUSCH detection started in frame %d slot %d\n", + LOG_I(PHY, "PUSCH detection started in frame %d slot %d\n", frame_rx,slot_rx); #ifdef DEBUG_RXDATA diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c index 9842d9137f..3ae3707962 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c @@ -318,13 +318,15 @@ void handle_nr_uci_pucch_0_1(module_id_t mod_id, frame_t frame, sub_frame_t slot, const nfapi_nr_uci_pucch_pdu_format_0_1_t *uci_01) -{ +{ NR_UE_info_t *UE_info = &RC.nrmac[mod_id]->UE_info; + UE_info->active[0] = 1; + UE_info->rnti[0] = uci_01->rnti; int UE_id = find_nr_UE_id(mod_id, uci_01->rnti); if (UE_id < 0) { LOG_E(MAC, "%s(): unknown RNTI %04x in PUCCH UCI\n", __func__, uci_01->rnti); return; } - NR_UE_info_t *UE_info = &RC.nrmac[mod_id]->UE_info; + //NR_UE_info_t *UE_info = &RC.nrmac[mod_id]->UE_info; NR_UE_sched_ctrl_t *sched_ctrl = &UE_info->UE_sched_ctrl[UE_id]; // tpc (power control) @@ -332,51 +334,55 @@ void handle_nr_uci_pucch_0_1(module_id_t mod_id, uci_01->ul_cqi, 30); - NR_ServingCellConfigCommon_t *scc = RC.nrmac[mod_id]->common_channels->ServingCellConfigCommon; - const int num_slots = nr_slots_per_frame[*scc->ssbSubcarrierSpacing]; - if (((uci_01->pduBitmap >> 1) & 0x01)) { - // iterate over received harq bits - for (int harq_bit = 0; harq_bit < uci_01->harq->num_harq; harq_bit++) { - const uint8_t harq_value = uci_01->harq->harq_list[harq_bit].harq_value; - const uint8_t harq_confidence = uci_01->harq->harq_confidence_level; - const int feedback_slot = (slot - 1 + num_slots) % num_slots; - /* In case of realtime problems: we can only identify a HARQ process by - * timing. If the HARQ process's feedback_slot is not the one we - * expected, we assume that processing has been aborted and we need to - * skip this HARQ process, which is what happens in the loop below. If - * you don't experience real-time problems, you might simply revert the - * commit that introduced these changes. */ - int8_t pid = sched_ctrl->feedback_dl_harq.head; - DevAssert(pid >= 0); - while (sched_ctrl->harq_processes[pid].feedback_slot != feedback_slot) { - LOG_W(MAC, - "expected feedback slot %d, but found %d instead\n", - sched_ctrl->harq_processes[pid].feedback_slot, - feedback_slot); - remove_front_nr_list(&sched_ctrl->feedback_dl_harq); - handle_dl_harq(mod_id, UE_id, pid, 0); - pid = sched_ctrl->feedback_dl_harq.head; - DevAssert(pid >= 0); - } - remove_front_nr_list(&sched_ctrl->feedback_dl_harq); - NR_UE_harq_t *harq = &sched_ctrl->harq_processes[pid]; - DevAssert(harq->is_waiting); - handle_dl_harq(mod_id, UE_id, pid, harq_value == 1 && harq_confidence == 0); - } - } + // NR_ServingCellConfigCommon_t *scc = RC.nrmac[mod_id]->common_channels->ServingCellConfigCommon; + // const int num_slots = nr_slots_per_frame[*scc->ssbSubcarrierSpacing]; + const int num_slots = 20; + + // if (((uci_01->pduBitmap >> 1) & 0x01)) { + // // iterate over received harq bits + // for (int harq_bit = 0; harq_bit < uci_01->harq->num_harq; harq_bit++) { + // const uint8_t harq_value = uci_01->harq->harq_list[harq_bit].harq_value; + // const uint8_t harq_confidence = uci_01->harq->harq_confidence_level; + // const int feedback_slot = (slot - 1 + num_slots) % num_slots; + // /* In case of realtime problems: we can only identify a HARQ process by + // * timing. If the HARQ process's feedback_slot is not the one we + // * expected, we assume that processing has been aborted and we need to + // * skip this HARQ process, which is what happens in the loop below. If + // * you don't experience real-time problems, you might simply revert the + // * commit that introduced these changes. */ + // int8_t pid = sched_ctrl->feedback_dl_harq.head; + // DevAssert(pid >= 0); + // while (sched_ctrl->harq_processes[pid].feedback_slot != feedback_slot) { + // LOG_W(MAC, + // "expected feedback slot %d, but found %d instead\n", + // sched_ctrl->harq_processes[pid].feedback_slot, + // feedback_slot); + // remove_front_nr_list(&sched_ctrl->feedback_dl_harq); + // handle_dl_harq(mod_id, UE_id, pid, 0); + // pid = sched_ctrl->feedback_dl_harq.head; + // DevAssert(pid >= 0); + // } + // remove_front_nr_list(&sched_ctrl->feedback_dl_harq); + // NR_UE_harq_t *harq = &sched_ctrl->harq_processes[pid]; + // DevAssert(harq->is_waiting); + // handle_dl_harq(mod_id, UE_id, pid, harq_value == 1 && harq_confidence == 0); + // } + // } } void handle_nr_uci_pucch_2_3_4(module_id_t mod_id, frame_t frame, sub_frame_t slot, const nfapi_nr_uci_pucch_pdu_format_2_3_4_t *uci_234) -{ +{ NR_UE_info_t *UE_info = &RC.nrmac[mod_id]->UE_info; + UE_info->active[0] = 1; + UE_info->rnti[0] = uci_234->rnti; int UE_id = find_nr_UE_id(mod_id, uci_234->rnti); if (UE_id < 0) { LOG_E(MAC, "%s(): unknown RNTI %04x in PUCCH UCI\n", __func__, uci_234->rnti); return; } - NR_UE_info_t *UE_info = &RC.nrmac[mod_id]->UE_info; + //NR_UE_info_t *UE_info = &RC.nrmac[mod_id]->UE_info; NR_UE_sched_ctrl_t *sched_ctrl = &UE_info->UE_sched_ctrl[UE_id]; // tpc (power control) @@ -384,37 +390,38 @@ void handle_nr_uci_pucch_2_3_4(module_id_t mod_id, uci_234->ul_cqi, 30); - NR_ServingCellConfigCommon_t *scc = RC.nrmac[mod_id]->common_channels->ServingCellConfigCommon; - const int num_slots = nr_slots_per_frame[*scc->ssbSubcarrierSpacing]; - if ((uci_234->pduBitmap >> 1) & 0x01) { - // iterate over received harq bits - for (int harq_bit = 0; harq_bit < uci_234->harq.harq_bit_len; harq_bit++) { - const int acknack = ((uci_234->harq.harq_payload[harq_bit >> 3]) >> harq_bit) & 0x01; - const int feedback_slot = (slot - 1 + num_slots) % num_slots; - /* In case of realtime problems: we can only identify a HARQ process by - * timing. If the HARQ process's feedback_slot is not the one we - * expected, we assume that processing has been aborted and we need to - * skip this HARQ process, which is what happens in the loop below. If - * you don't experience real-time problems, you might simply revert the - * commit that introduced these changes. */ - int8_t pid = sched_ctrl->feedback_dl_harq.head; - DevAssert(pid >= 0); - while (sched_ctrl->harq_processes[pid].feedback_slot != feedback_slot) { - LOG_W(MAC, - "expected feedback slot %d, but found %d instead\n", - sched_ctrl->harq_processes[pid].feedback_slot, - feedback_slot); - remove_front_nr_list(&sched_ctrl->feedback_dl_harq); - handle_dl_harq(mod_id, UE_id, pid, 0); - pid = sched_ctrl->feedback_dl_harq.head; - DevAssert(pid >= 0); - } - remove_front_nr_list(&sched_ctrl->feedback_dl_harq); - NR_UE_harq_t *harq = &sched_ctrl->harq_processes[pid]; - DevAssert(harq->is_waiting); - handle_dl_harq(mod_id, UE_id, pid, uci_234->harq.harq_crc != 1 && acknack); - } - } + // NR_ServingCellConfigCommon_t *scc = RC.nrmac[mod_id]->common_channels->ServingCellConfigCommon; + // const int num_slots = nr_slots_per_frame[*scc->ssbSubcarrierSpacing]; + const int num_slots = 20; + // if ((uci_234->pduBitmap >> 1) & 0x01) { + // // iterate over received harq bits + // for (int harq_bit = 0; harq_bit < uci_234->harq.harq_bit_len; harq_bit++) { + // const int acknack = ((uci_234->harq.harq_payload[harq_bit >> 3]) >> harq_bit) & 0x01; + // const int feedback_slot = (slot - 1 + num_slots) % num_slots; + // /* In case of realtime problems: we can only identify a HARQ process by + // * timing. If the HARQ process's feedback_slot is not the one we + // * expected, we assume that processing has been aborted and we need to + // * skip this HARQ process, which is what happens in the loop below. If + // * you don't experience real-time problems, you might simply revert the + // * commit that introduced these changes. */ + // int8_t pid = sched_ctrl->feedback_dl_harq.head; + // DevAssert(pid >= 0); + // while (sched_ctrl->harq_processes[pid].feedback_slot != feedback_slot) { + // LOG_W(MAC, + // "expected feedback slot %d, but found %d instead\n", + // sched_ctrl->harq_processes[pid].feedback_slot, + // feedback_slot); + // remove_front_nr_list(&sched_ctrl->feedback_dl_harq); + // handle_dl_harq(mod_id, UE_id, pid, 0); + // pid = sched_ctrl->feedback_dl_harq.head; + // DevAssert(pid >= 0); + // } + // remove_front_nr_list(&sched_ctrl->feedback_dl_harq); + // NR_UE_harq_t *harq = &sched_ctrl->harq_processes[pid]; + // DevAssert(harq->is_waiting); + // handle_dl_harq(mod_id, UE_id, pid, uci_234->harq.harq_crc != 1 && acknack); + // } + // } } diff --git a/openair2/NR_PHY_INTERFACE/NR_IF_Module.c b/openair2/NR_PHY_INTERFACE/NR_IF_Module.c index d5f6bb2308..9c118ec53b 100644 --- a/openair2/NR_PHY_INTERFACE/NR_IF_Module.c +++ b/openair2/NR_PHY_INTERFACE/NR_IF_Module.c @@ -139,17 +139,18 @@ void handle_nr_ulsch(NR_UL_IND_t *UL_info) crc->tb_crc_status); /* if CRC passes, pass PDU, otherwise pass NULL as error indication */ - nr_rx_sdu(UL_info->module_id, - UL_info->CC_id, - UL_info->rx_ind.sfn, - UL_info->rx_ind.slot, - rx->rnti, - crc->tb_crc_status ? NULL : rx->pdu, - rx->pdu_length, - rx->timing_advance, - rx->ul_cqi, - rx->rssi); - handle_nr_ul_harq(UL_info->module_id, UL_info->frame, UL_info->slot, crc); + //Gokul + // nr_rx_sdu(UL_info->module_id, + // UL_info->CC_id, + // UL_info->rx_ind.sfn, + // UL_info->rx_ind.slot, + // rx->rnti, + // crc->tb_crc_status ? NULL : rx->pdu, + // rx->pdu_length, + // rx->timing_advance, + // rx->ul_cqi, + // rx->rssi); + //handle_nr_ul_harq(UL_info->module_id, UL_info->frame, UL_info->slot, crc); break; } // for (j=0;jcrc_ind.number_crcs;j++) } // for (i=0;irx_ind.number_of_pdus;i++) From 4454627ba364d348269131a050f3bef6ce53707f Mon Sep 17 00:00:00 2001 From: Mahesh Date: Wed, 17 Mar 2021 14:43:05 +0530 Subject: [PATCH 07/91] Uplink constellation + CRC OK --- executables/nr-gnb.c | 6 +++++- openair1/PHY/NR_TRANSPORT/nr_ulsch_decoding.c | 3 +++ openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_coding.c | 14 +++++++------- .../LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c | 7 +++++++ 4 files changed, 22 insertions(+), 8 deletions(-) diff --git a/executables/nr-gnb.c b/executables/nr-gnb.c index 5e63c54ab8..2f7944e313 100644 --- a/executables/nr-gnb.c +++ b/executables/nr-gnb.c @@ -428,7 +428,11 @@ static void *gNB_L1_thread( void *param ) { VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_gNB_PROC_RXTX0, 0 ); int frame_rx = L1_proc->frame_rx; - int slot_rx = L1_proc->slot_rx; + int slot_rx; + if (NFAPI_MODE == NFAPI_MODE_PNF) + slot_rx = (L1_proc->slot_rx) + 1; + else + slot_rx = L1_proc->slot_rx; int frame_tx = L1_proc->frame_tx; int slot_tx = L1_proc->slot_tx; uint64_t timestamp_tx = L1_proc->timestamp_tx; diff --git a/openair1/PHY/NR_TRANSPORT/nr_ulsch_decoding.c b/openair1/PHY/NR_TRANSPORT/nr_ulsch_decoding.c index 0b0851dddb..91f72922e2 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_ulsch_decoding.c +++ b/openair1/PHY/NR_TRANSPORT/nr_ulsch_decoding.c @@ -443,7 +443,9 @@ void nr_processULSegment(void* arg) { for (int m=0; m < Kr>>3; m ++) { ulsch_harq->c[r][m]= (uint8_t) llrProcBuf[m]; + //printf("%x ", ulsch_harq->c[r][m]); } + //printf("\n"); //stop_meas(&phy_vars_gNB->ulsch_ldpc_decoding_stats); } @@ -510,6 +512,7 @@ uint32_t nr_ulsch_decoding(PHY_VARS_gNB *phy_vars_gNB, A = (harq_process->TBS)<<3; LOG_D(PHY,"ULSCH Decoding, harq_pid %d TBS %d G %d mcs %d Nl %d nb_rb %d, Qm %d, n_layers %d\n",harq_pid,A,G, mcs, n_layers, nb_rb, Qm, n_layers); + //printf("ULSCH in %d.%d \n", frame, nr_tti_rx); if (R<1024) Coderate = (float) R /(float) 1024; diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_coding.c b/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_coding.c index d9bea8a3ac..f6a346aee9 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_coding.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_coding.c @@ -275,13 +275,13 @@ int nr_ulsch_encoding(NR_UE_ULSCH_t *ulsch, ///////////////////////// a---->| add CRC |---->b ///////////////////////// /////////// - /* - int i; - printf("ulsch (tx): \n"); - for (i=0;i<(A>>3);i++) - printf("%02x.",a[i]); - printf("\n"); - */ + + // int i; + // printf("ulsch (tx): \n"); + // for (i=0;i<(A>>3);i++) + // printf("%x ",harq_process->a[i]); + // printf("\n"); + if (A > 3824) { // Add 24-bit crc (polynomial A) to payload diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c index e7149c5d65..00e53dd21e 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c @@ -62,6 +62,7 @@ #include "common/ran_context.h" extern RAN_CONTEXT_t RC; +uint8_t count = 0; uint8_t harq_pid_ul = -1; int flag = 0; // Note the 2 scs values in the table names represent resp. scs_common and pdcch_scs /// LUT for the number of symbols in the coreset indexed by coreset index (4 MSB rmsi_pdcch_config) @@ -1248,6 +1249,11 @@ void fill_dci_pdu_rel15(const NR_ServingCellConfigCommon_t *scc, case NR_UL_DCI_FORMAT_0_1: switch (rnti_type) { case NR_RNTI_C: + harq_pid_ul = (harq_pid_ul + 1) % 16; + if (harq_pid_ul == 0) + flag = !flag; + dci_pdu_rel15->ndi = flag; + // Indicating a DL DCI format 1bit pos = 1; *dci_pdu |= ((uint64_t)dci_pdu_rel15->format_indicator & 0x1) << (dci_size - pos); @@ -1280,6 +1286,7 @@ void fill_dci_pdu_rel15(const NR_ServingCellConfigCommon_t *scc, *dci_pdu |= ((uint64_t)dci_pdu_rel15->rv & 0x3) << (dci_size - pos); // HARQ process number 4bit pos += 4; + dci_pdu_rel15->harq_pid = harq_pid_ul; *dci_pdu |= ((uint64_t)dci_pdu_rel15->harq_pid & 0xf) << (dci_size - pos); // 1st Downlink assignment index pos += dci_pdu_rel15->dai[0].nbits; From 047b7b17ba942ad4aecc01832b159ea4c7959cf1 Mon Sep 17 00:00:00 2001 From: Mahesh Date: Tue, 13 Apr 2021 02:31:40 +0530 Subject: [PATCH 08/91] Uplink indication --- nfapi/oai_integration/nfapi_pnf.c | 33 + .../nfapi/public_inc/nfapi_nr_interface_scf.h | 7 +- nfapi/open-nFAPI/nfapi/src/nfapi_p7.c | 840 ++++++++++++++---- nfapi/open-nFAPI/pnf/src/pnf_p7_interface.c | 72 +- nfapi/open-nFAPI/vnf/src/vnf_p7.c | 136 ++- openair2/NR_PHY_INTERFACE/NR_IF_Module.c | 60 +- 6 files changed, 937 insertions(+), 211 deletions(-) diff --git a/nfapi/oai_integration/nfapi_pnf.c b/nfapi/oai_integration/nfapi_pnf.c index e744fcbb24..92057186e2 100644 --- a/nfapi/oai_integration/nfapi_pnf.c +++ b/nfapi/oai_integration/nfapi_pnf.c @@ -2406,3 +2406,36 @@ int oai_nfapi_sr_indication(nfapi_sr_indication_t *ind) { //free(ind.rx_indication_body.rx_pdu_list); return retval; } + +//NR UPLINK INDICATION + +int oai_nfapi_nr_rx_data_indication(nfapi_nr_rx_data_indication_t *ind) { + ind->header.phy_id = 1; // DJP HACK TODO FIXME - need to pass this around!!!! + ind->header.message_id = NFAPI_NR_PHY_MSG_TYPE_RX_DATA_INDICATION; + return nfapi_pnf_p7_nr_rx_data_ind(p7_config_g, ind); +} + +int oai_nfapi_nr_crc_indication(nfapi_nr_crc_indication_t *ind) { + ind->header.phy_id = 1; // DJP HACK TODO FIXME - need to pass this around!!!! + ind->header.message_id = NFAPI_NR_PHY_MSG_TYPE_CRC_INDICATION; + return nfapi_pnf_p7_nr_crc_ind(p7_config_g, ind); +} + +int oai_nfapi_nr_srs_indication(nfapi_nr_srs_indication_t *ind) { + ind->header.phy_id = 1; // DJP HACK TODO FIXME - need to pass this around!!!! + ind->header.message_id = NFAPI_NR_PHY_MSG_TYPE_SRS_INDICATION; + return nfapi_pnf_p7_nr_srs_ind(p7_config_g, ind); +} + +int oai_nfapi_nr_uci_indication(nfapi_nr_uci_indication_t *ind) { + ind->header.phy_id = 1; // DJP HACK TODO FIXME - need to pass this around!!!! + ind->header.message_id = NFAPI_NR_PHY_MSG_TYPE_UCI_INDICATION; + return nfapi_pnf_p7_nr_uci_ind(p7_config_g, ind); +} + +int oai_nfapi_nr_rach_indication(nfapi_nr_rach_indication_t *ind) { + ind->header.phy_id = 1; // DJP 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); +} + 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 bc5e7af45f..85f1efa3f4 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 @@ -1516,10 +1516,11 @@ typedef struct typedef struct { + nfapi_p7_message_header_t header; uint16_t sfn; uint16_t slot; uint16_t number_of_pdus; - nfapi_nr_rx_data_pdu_t* pdu_list; + nfapi_nr_rx_data_pdu_t *pdu_list; //changed from pointer to struct - gokul } nfapi_nr_rx_data_indication_t; @@ -1542,6 +1543,7 @@ typedef struct typedef struct { + nfapi_p7_message_header_t header; uint16_t sfn; uint16_t slot; uint16_t number_crcs; @@ -1679,6 +1681,7 @@ typedef struct typedef struct { + nfapi_p7_message_header_t header; uint16_t sfn; uint16_t slot; uint16_t num_ucis; @@ -1715,6 +1718,7 @@ typedef struct typedef struct { + nfapi_p7_message_header_t header; uint16_t sfn; uint16_t slot; uint8_t number_of_pdus; @@ -1747,6 +1751,7 @@ typedef struct{ typedef struct { + nfapi_p7_message_header_t header; uint16_t sfn; uint16_t slot; uint8_t number_of_pdus; diff --git a/nfapi/open-nFAPI/nfapi/src/nfapi_p7.c b/nfapi/open-nFAPI/nfapi/src/nfapi_p7.c index 49ecba5eac..a97e4ccaaf 100755 --- a/nfapi/open-nFAPI/nfapi/src/nfapi_p7.c +++ b/nfapi/open-nFAPI/nfapi/src/nfapi_p7.c @@ -3354,6 +3354,308 @@ static uint8_t pack_nr_timing_info(void *msg, uint8_t **ppWritePackedMsg, uint8_ } +//NR UPLINK indication function packing + +//RX DATA INDICATION + +static uint8_t pack_nr_rx_data_indication_body(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_nr_rx_data_pdu_t* value = (nfapi_nr_rx_data_pdu_t*)tlv; + + if(!(push32(value->handle, ppWritePackedMsg, end) && + push16(value->rnti, ppWritePackedMsg, end) && + push8(value->harq_id, ppWritePackedMsg, end) && + push16(value->pdu_length, ppWritePackedMsg, end) && + push8(value->ul_cqi, ppWritePackedMsg, end) && + push16(value->timing_advance, ppWritePackedMsg, end) && + push16(value->rssi, ppWritePackedMsg, end) + )) + return 0; + + return 1; +} + + +static uint8_t pack_nr_rx_data_indication(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) +{ + nfapi_nr_rx_data_indication_t *pNfapiMsg = (nfapi_nr_rx_data_indication_t*)msg; + + if (!(push16(pNfapiMsg->sfn , ppWritePackedMsg, end) && + push16(pNfapiMsg->slot , ppWritePackedMsg, end) && + push16(pNfapiMsg->number_of_pdus, ppWritePackedMsg, end) + )) + return 0; + + for(int i=0; inumber_of_pdus;i++) + { + if(!pack_nr_rx_data_indication_body(pNfapiMsg->pdu_list,ppWritePackedMsg,end)) + return 0; + } + +return 1; +} + +//NR CRC INDICATION + +static uint8_t pack_nr_crc_indication_body(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_nr_crc_t* value = (nfapi_nr_crc_t*)tlv; + + if(!(push32(value->handle, ppWritePackedMsg, end) && + push16(value->rnti, ppWritePackedMsg, end) && + push8(value->harq_id, ppWritePackedMsg, end) && + push8(value->tb_crc_status, ppWritePackedMsg, end) && + push16(value->num_cb, ppWritePackedMsg, end) && + //pusharray8(value->cb_crc_status, (int)(value->num_cb / 8) + 1, (int)(value->num_cb / 8) + 1, ppWritePackedMsg, end) && //length is ceil(NumCb/8) + push8(value->ul_cqi, ppWritePackedMsg, end) && + push16(value->timing_advance, ppWritePackedMsg, end) && + push16(value->rssi, ppWritePackedMsg, end) + )) + return 0; + + return 1; +} + +static uint8_t pack_nr_crc_indication(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) +{ + nfapi_nr_crc_indication_t *pNfapiMsg = (nfapi_nr_crc_indication_t*)msg; + + if (!(push16(pNfapiMsg->sfn , ppWritePackedMsg, end) && + push16(pNfapiMsg->slot , ppWritePackedMsg, end) && + push16(pNfapiMsg->number_crcs, ppWritePackedMsg, end) + )) + return 0; + + for(int i=0; inumber_crcs;i++) + { + if(!pack_nr_crc_indication_body(pNfapiMsg->crc_list,ppWritePackedMsg,end)) + return 0; + } + +return 1; +} + +//SRS INDICATION + +static uint8_t pack_nr_srs_indication_body(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_nr_srs_indication_pdu_t* value = (nfapi_nr_srs_indication_pdu_t*)tlv; + + if(!(push32(value->handle, ppWritePackedMsg, end) && + push16(value->rnti, ppWritePackedMsg, end) && + push16(value->timing_advance, ppWritePackedMsg, end) && + push8(value->num_symbols, ppWritePackedMsg, end) && + push8(value->wide_band_snr, ppWritePackedMsg, end) && + push8(value->num_reported_symbols, ppWritePackedMsg, end) && + push8(value->reported_symbol_list->num_rbs, ppWritePackedMsg, end) + )) + return 0; + for(int i = 0; i < value->reported_symbol_list->num_rbs; i++) + { + if(!(push8(value->reported_symbol_list->rb_list->rb_snr, ppWritePackedMsg, end) + )) + return 0; + } + return 1; +} + +static uint8_t pack_nr_srs_indication(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) +{ + nfapi_nr_srs_indication_t *pNfapiMsg = (nfapi_nr_srs_indication_t*)msg; + + if (!(push16(pNfapiMsg->sfn , ppWritePackedMsg, end) && + push16(pNfapiMsg->slot , ppWritePackedMsg, end) && + push16(pNfapiMsg->number_of_pdus, ppWritePackedMsg, end) + )) + return 0; + + for(int i=0; inumber_of_pdus;i++) + { + if(!pack_nr_srs_indication_body(&(pNfapiMsg->pdu_list[i]),ppWritePackedMsg,end)) + return 0; + } + +return 1; +} + +//RACH INDICATION + +static uint8_t pack_nr_rach_indication_body(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_nr_prach_indication_pdu_t* value = (nfapi_nr_prach_indication_pdu_t*)tlv; + + if(!(push16(value->phy_cell_id, ppWritePackedMsg, end) && + push8(value->symbol_index, ppWritePackedMsg, end) && + push8(value->slot_index, ppWritePackedMsg, end) && + push8(value->freq_index, ppWritePackedMsg, end) && + push8(value->avg_rssi, ppWritePackedMsg, end) && + push8(value->avg_snr, ppWritePackedMsg, end) && + push8(value->num_preamble, ppWritePackedMsg, end) + )) + return 0; + for(int i = 0; i < value->num_preamble; i++) + { + if(!(push8(value->preamble_list->preamble_index, ppWritePackedMsg, end) && + push16(value->preamble_list->timing_advance, ppWritePackedMsg, end) && + push32(value->preamble_list->preamble_pwr, ppWritePackedMsg, end) + )) + return 0; + } + return 1; +} + +static uint8_t pack_nr_rach_indication(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) +{ + nfapi_nr_rach_indication_t *pNfapiMsg = (nfapi_nr_rach_indication_t*)msg; + + if (!(push16(pNfapiMsg->sfn , ppWritePackedMsg, end) && + push16(pNfapiMsg->slot , ppWritePackedMsg, end) && + push16(pNfapiMsg->number_of_pdus, ppWritePackedMsg, end) + )) + return 0; + + for(int i=0; inumber_of_pdus;i++) + { + if(!pack_nr_rach_indication_body(&(pNfapiMsg->pdu_list[i]),ppWritePackedMsg,end)) + return 0; + } + +return 1; +} + + +//UCI INDICATION + +static uint8_t pack_nr_uci_pucch_0_1(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_nr_uci_pucch_pdu_format_0_1_t* value = (nfapi_nr_uci_pucch_pdu_format_0_1_t*)tlv; + + if(!(push8(value->pduBitmap, ppWritePackedMsg, end) && + push32(value->handle, ppWritePackedMsg, end) && + push16(value->rnti, ppWritePackedMsg, end) && + push8(value->pucch_format, ppWritePackedMsg, end) && + push8(value->ul_cqi, ppWritePackedMsg, end) && + push16(value->timing_advance, ppWritePackedMsg, end) && + push16(value->rssi, ppWritePackedMsg, end) + )) + return 0; + if (value->pduBitmap & 0x01) { //SR + if(!(push8(value->sr->sr_indication, ppWritePackedMsg, end) && + push8(value->sr->sr_confidence_level, ppWritePackedMsg, end) + )) + return 0; + } + + if (((value->pduBitmap >> 1) & 0x01)) { //HARQ + if(!(push8(value->harq->num_harq, ppWritePackedMsg, end) && + push8(value->harq->harq_confidence_level, ppWritePackedMsg, end) + )) + return 0; + + for(int i=0; iharq->num_harq;i++) + { + if(!(push8(value->harq->harq_list[i].harq_value, ppWritePackedMsg, end) + )) + return 0; + } + } + + return 1; +} + +static uint8_t pack_nr_uci_pucch_2_3_4(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_nr_uci_pucch_pdu_format_2_3_4_t* value = (nfapi_nr_uci_pucch_pdu_format_2_3_4_t*) tlv; + + if(!(push8(value->pduBitmap, ppWritePackedMsg, end) && + push32(value->handle, ppWritePackedMsg, end) && + push16(value->rnti, ppWritePackedMsg, end) && + push8(value->pucch_format, ppWritePackedMsg, end) && + push8(value->ul_cqi, ppWritePackedMsg, end) && + push16(value->timing_advance, ppWritePackedMsg, end) && + push16(value->rssi, ppWritePackedMsg, end) + )) + return 0; + + if (value->pduBitmap & 0x01) { //SR + if(!(push8(value->sr.sr_bit_len, ppWritePackedMsg, end) && + pusharray8(value->sr.sr_payload, (int)(value->sr.sr_bit_len / 8) + 1, (int)(value->sr.sr_bit_len / 8) + 1, ppWritePackedMsg, end) + )) + return 0; + } + + if (((value->pduBitmap >> 1) & 0x01)) { //HARQ + if(!(push8(value->harq.harq_crc, ppWritePackedMsg, end) && + push8(value->harq.harq_bit_len, ppWritePackedMsg, end) && + pusharray8(value->harq.harq_payload, (int)(value->harq.harq_bit_len / 8) + 1, (int)(value->harq.harq_bit_len / 8) + 1, ppWritePackedMsg, end) + )) + return 0; + } + + if (((value->pduBitmap >> 2) & 0x01)) { //CSI-1 + if(!(push8(value->csi_part1.csi_part1_crc, ppWritePackedMsg, end) && + push8(value->csi_part1.csi_part1_bit_len, ppWritePackedMsg, end) && + pusharray8(value->csi_part1.csi_part1_payload, (int)(value->csi_part1.csi_part1_bit_len / 8) + 1, (int)(value->csi_part1.csi_part1_bit_len / 8) + 1, ppWritePackedMsg, end) + )) + return 0; + } + + if (((value->pduBitmap >> 3) & 0x01)) { //CSI-2 + if(!(push8(value->csi_part2.csi_part2_crc, ppWritePackedMsg, end) && + push8(value->csi_part2.csi_part2_bit_len, ppWritePackedMsg, end) && + pusharray8(value->csi_part2.csi_part2_payload, (int)(value->csi_part2.csi_part2_bit_len / 8) + 1, (int)(value->csi_part2.csi_part2_bit_len / 8) + 1, ppWritePackedMsg, end) + )) + return 0; + } + + return 1; +} + +static uint8_t pack_nr_uci_indication_body(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_nr_uci_t* value = (nfapi_nr_uci_t*)tlv; + + if(!(push16(value->pdu_type, ppWritePackedMsg, end) && + push16(value->pdu_size, ppWritePackedMsg, end) + )) + return 0; + + switch (value->pdu_type) { + case NFAPI_NR_UCI_PUSCH_PDU_TYPE: + printf("Unhandled NFAPI_NR_UCI_PUSCH_PDU_TYPE \n"); + break; + + case NFAPI_NR_UCI_FORMAT_0_1_PDU_TYPE: { + nfapi_nr_uci_pucch_pdu_format_0_1_t *uci_pdu = &value->pucch_pdu_format_0_1; + pack_nr_uci_pucch_0_1(uci_pdu, ppWritePackedMsg, end); + break; + } + case NFAPI_NR_UCI_FORMAT_2_3_4_PDU_TYPE: { + nfapi_nr_uci_pucch_pdu_format_2_3_4_t *uci_pdu = &value->pucch_pdu_format_2_3_4; + pack_nr_uci_pucch_2_3_4(uci_pdu, ppWritePackedMsg, end); + break; + } + } + + return 1; +} + +static uint8_t pack_nr_uci_indication(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) +{ + nfapi_nr_uci_indication_t *pNfapiMsg = (nfapi_nr_uci_indication_t*)msg; + + if (!(push16(pNfapiMsg->sfn , ppWritePackedMsg, end) && + push16(pNfapiMsg->slot , ppWritePackedMsg, end) && + push16(pNfapiMsg->num_ucis, ppWritePackedMsg, end) + )) + return 0; + + for(int i=0; inum_ucis;i++) + { + if(!pack_nr_uci_indication_body(&(pNfapiMsg->uci_list[i]),ppWritePackedMsg,end)) + return 0; + } + +return 1; +} // Main pack function - public @@ -3419,49 +3721,24 @@ int nfapi_nr_p7_message_pack(void *pMessageBuf, void *pPackedBuf, uint32_t packe result =pack_ue_release_response(pMessageHeader, &pWritePackedMessage, end, config); break; - case NFAPI_HARQ_INDICATION: - result = pack_harq_indication(pMessageHeader, &pWritePackedMessage, end, config); + case NFAPI_NR_PHY_MSG_TYPE_RX_DATA_INDICATION: + result = pack_nr_rx_data_indication(pMessageHeader, &pWritePackedMessage, end, config); break; - case NFAPI_CRC_INDICATION: - result = pack_crc_indication(pMessageHeader, &pWritePackedMessage, end, config); + case NFAPI_NR_PHY_MSG_TYPE_CRC_INDICATION: + result = pack_nr_crc_indication(pMessageHeader, &pWritePackedMessage, end, config); break; - case NFAPI_RX_ULSCH_INDICATION: - //printf("RX ULSCH\n"); - result = pack_rx_ulsch_indication(pMessageHeader, &pWritePackedMessage, end, config); + case NFAPI_NR_PHY_MSG_TYPE_UCI_INDICATION: + result = pack_nr_uci_indication(pMessageHeader, &pWritePackedMessage, end, config); break; - case NFAPI_RACH_INDICATION: - result = pack_rach_indication(pMessageHeader, &pWritePackedMessage, end, config); + case NFAPI_NR_PHY_MSG_TYPE_SRS_INDICATION: + result = pack_nr_rach_indication(pMessageHeader, &pWritePackedMessage, end, config); break; - case NFAPI_SRS_INDICATION: - result = pack_srs_indication(pMessageHeader, &pWritePackedMessage, end, config); - break; - - case NFAPI_RX_SR_INDICATION: - result = pack_sr_indication(pMessageHeader, &pWritePackedMessage, end, config); - break; - - case NFAPI_RX_CQI_INDICATION: - result = pack_cqi_indication(pMessageHeader, &pWritePackedMessage, end, config); - break; - - case NFAPI_LBT_DL_CONFIG_REQUEST: - result = pack_lbt_dl_config_request(pMessageHeader, &pWritePackedMessage, end, config); - break; - - case NFAPI_LBT_DL_INDICATION: - result = pack_lbt_dl_indication(pMessageHeader, &pWritePackedMessage, end, config); - break; - - case NFAPI_NB_HARQ_INDICATION: - result = pack_nb_harq_indication(pMessageHeader, &pWritePackedMessage, end, config); - break; - - case NFAPI_NRACH_INDICATION: - result = pack_nrach_indication(pMessageHeader, &pWritePackedMessage, end, config); + case NFAPI_NR_PHY_MSG_TYPE_RACH_INDICATION: + result = pack_nr_srs_indication(pMessageHeader, &pWritePackedMessage, end, config); break; case NFAPI_NR_PHY_MSG_TYPE_DL_NODE_SYNC: @@ -3577,7 +3854,6 @@ int nfapi_p7_message_pack(void *pMessageBuf, void *pPackedBuf, uint32_t packedBu switch (pMessageHeader->message_id) { case NFAPI_DL_CONFIG_REQUEST: - //NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() NFAPI_DL_CONFIG_REQUEST\n", __FUNCTION__); result = pack_dl_config_request(pMessageHeader, &pWritePackedMessage, end, config); break; @@ -3585,7 +3861,6 @@ int nfapi_p7_message_pack(void *pMessageBuf, void *pPackedBuf, uint32_t packedBu result = pack_ul_config_request(pMessageHeader, &pWritePackedMessage, end, config); break; case NFAPI_TX_REQUEST: - //NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() NFAPI_TX_REQUEST\n", __FUNCTION__); result = pack_tx_request(pMessageHeader, &pWritePackedMessage, end, config); break; case NFAPI_HI_DCI0_REQUEST: @@ -3609,7 +3884,6 @@ int nfapi_p7_message_pack(void *pMessageBuf, void *pPackedBuf, uint32_t packedBu break; case NFAPI_RX_ULSCH_INDICATION: - //printf("RX ULSCH\n"); result = pack_rx_ulsch_indication(pMessageHeader, &pWritePackedMessage, end, config); break; @@ -6074,6 +6348,334 @@ static uint8_t unpack_tx_request(uint8_t **ppReadPackedMsg, uint8_t *end, void * return 1; } + +//UNPACK NR UPLINK INDICATION FUNCTIONS + +//RX DATA INDICATION + +static uint8_t unpack_nr_rx_data_indication_body(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_nr_rx_data_pdu_t* value = (nfapi_nr_rx_data_pdu_t*)tlv; + + if(!(pull32(ppReadPackedMsg, &value->handle, end) && + pull16(ppReadPackedMsg, &value->rnti, end) && + pull8(ppReadPackedMsg, &value->harq_id, end) && + pull16(ppReadPackedMsg, &value->pdu_length, end) && + pull8(ppReadPackedMsg, &value->ul_cqi, end) && + pull16(ppReadPackedMsg, &value->timing_advance, end) && + pull16(ppReadPackedMsg, &value->rssi, end) + )) + return 0; + return 1; +} + + +static uint8_t unpack_nr_rx_data_indication(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config) +{ + // uint8_t *ptr = *ppReadPackedMsg; + // printf("\n Read P7 message rx data indication unpack: "); + // while(ptr < end){ + // printf(" %d ", *ptr); + // ptr++; + // } + // printf("\n"); + nfapi_nr_rx_data_indication_t *pNfapiMsg = (nfapi_nr_rx_data_indication_t*)msg; + + printf("\n"); + if (!(pull16(ppReadPackedMsg, &pNfapiMsg->sfn , end) && + pull16(ppReadPackedMsg, &pNfapiMsg->slot , end) && + pull16(ppReadPackedMsg, &pNfapiMsg->number_of_pdus, end) + )) + return 0; + + for(int i=0; inumber_of_pdus;i++) + { + if(!unpack_nr_rx_data_indication_body(&pNfapiMsg->pdu_list, ppReadPackedMsg, end)) + return 0; + } + +return 1; +} + +//NR CRC INDICATION + +static uint8_t unpack_nr_crc_indication_body(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_nr_crc_t* value = (nfapi_nr_crc_t*)tlv; + + if(!(pull32(ppReadPackedMsg, &value->handle, end) && + pull16(ppReadPackedMsg, &value->rnti, end) && + pull8(ppReadPackedMsg, &value->harq_id, end) && + pull8(ppReadPackedMsg, &value->tb_crc_status, end) && + pull16(ppReadPackedMsg, &value->num_cb, end) && + //pullarray8(ppReadPackedMsg, value->cb_crc_status, (int)(value->num_cb / 8) + 1, (int)(value->num_cb / 8) + 1, end) && //length is ceil(NumCb/8) + pull8(ppReadPackedMsg, &value->ul_cqi, end) && + pull16(ppReadPackedMsg, &value->timing_advance, end) && + pull16(ppReadPackedMsg, &value->rssi, end) + )) + return 0; + + return 1; +} + +static uint8_t unpack_nr_crc_indication(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config) +{ + uint8_t *ptr = *ppReadPackedMsg; + // printf("\n Read P7 message indication unpack: "); + // while(ptr < end){ + // printf(" %d ", *ptr); + // ptr++; + // } + // printf("\n"); + nfapi_nr_crc_indication_t *pNfapiMsg = (nfapi_nr_crc_indication_t*)msg; + + if (!(pull16(ppReadPackedMsg, &pNfapiMsg->sfn , end) && + pull16(ppReadPackedMsg, &pNfapiMsg->slot , end) && + pull16(ppReadPackedMsg, &pNfapiMsg->number_crcs, end) + )) + return 0; + + for(int i=0; inumber_crcs;i++) + { + if(!unpack_nr_crc_indication_body(&pNfapiMsg->crc_list,ppReadPackedMsg,end)) + return 0; + } + +return 1; +} + +//SRS INDICATION + +static uint8_t unpack_nr_srs_indication_body(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_nr_srs_indication_pdu_t* value = (nfapi_nr_srs_indication_pdu_t*)tlv; + + if(!(pull32(ppReadPackedMsg, &value->handle, end) && + pull16(ppReadPackedMsg, &value->rnti, end) && + pull16(ppReadPackedMsg, &value->timing_advance, end) && + pull8(ppReadPackedMsg, &value->num_symbols, end) && + pull8(ppReadPackedMsg, &value->wide_band_snr, end) && + pull8(ppReadPackedMsg, &value->num_reported_symbols, end) && + pull16(ppReadPackedMsg, &value->reported_symbol_list->num_rbs, end) + )) + return 0; + for(int i = 0; i < value->reported_symbol_list->num_rbs; i++) + { + if(!(pull8(ppReadPackedMsg, &value->reported_symbol_list->rb_list->rb_snr, end) + )) + return 0; + } + return 1; +} + +static uint8_t unpack_nr_srs_indication(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config) +{ + nfapi_nr_srs_indication_t *pNfapiMsg = (nfapi_nr_srs_indication_t*)msg; + + if (!(pull16(ppReadPackedMsg,&pNfapiMsg->sfn , end) && + pull16(ppReadPackedMsg,&pNfapiMsg->slot , end) && + pull8(ppReadPackedMsg,&pNfapiMsg->number_of_pdus, end) + )) + return 0; + + for(int i=0; inumber_of_pdus;i++) + { + if(!unpack_nr_srs_indication_body(&pNfapiMsg->pdu_list,ppReadPackedMsg,end)) + return 0; + } + +return 1; +} + +//NR RACH + +static uint8_t unpack_nr_rach_indication_body(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_nr_prach_indication_pdu_t* value = (nfapi_nr_prach_indication_pdu_t*)tlv; + + if(!(pull16(ppReadPackedMsg, &value->phy_cell_id, end) && + pull8(ppReadPackedMsg, &value->symbol_index, end) && + pull8(ppReadPackedMsg, &value->slot_index, end) && + pull8(ppReadPackedMsg, &value->freq_index, end) && + pull8(ppReadPackedMsg, &value->avg_rssi, end) && + pull8(ppReadPackedMsg, &value->avg_snr, end) && + pull8(ppReadPackedMsg, &value->num_preamble, end) + )) + return 0; + for(int i = 0; i < value->num_preamble; i++) + { + if(!(pull8(ppReadPackedMsg, &value->preamble_list->preamble_index, end) && + pull16(ppReadPackedMsg, &value->preamble_list->timing_advance, end) && + pull32(ppReadPackedMsg, &value->preamble_list->preamble_pwr, end) + )) + return 0; + } + return 1; +} + +static uint8_t unpack_nr_rach_indication(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config) { + + nfapi_nr_rach_indication_t *pNfapiMsg = (nfapi_nr_rach_indication_t*)msg; + if (!(pull16(ppReadPackedMsg, &pNfapiMsg->sfn , end) && + pull16(ppReadPackedMsg, &pNfapiMsg->slot , end) && + pull8(ppReadPackedMsg, &pNfapiMsg->number_of_pdus, end) + )) + return 0; + + for(int i=0; i< pNfapiMsg->number_of_pdus;i++) + { + if(!unpack_nr_rach_indication_body(&pNfapiMsg->pdu_list,ppReadPackedMsg,end)) + return 0; + } + +return 1; +} + +//NR UCI + +static uint8_t unpack_nr_uci_pucch_0_1(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_nr_uci_pucch_pdu_format_0_1_t* value = (nfapi_nr_uci_pucch_pdu_format_0_1_t*)tlv; + + uint8_t *ptr = *ppReadPackedMsg; + printf("\n Read P7 message uci_0_1 indication unpack: "); + while(ptr < end){ + printf(" %d ", *ptr); + ptr++; + } + printf("\n"); + + if(!(pull8(ppReadPackedMsg, &value->pduBitmap, end) && + pull32(ppReadPackedMsg, &value->handle, end) && + pull16(ppReadPackedMsg, &value->rnti, end) && + pull8(ppReadPackedMsg, &value->pucch_format, end) && + pull8(ppReadPackedMsg, &value->ul_cqi, end) && + pull16(ppReadPackedMsg, &value->timing_advance, end) && + pull16(ppReadPackedMsg, &value->rssi, end) + )) + return 0; + if (value->pduBitmap & 0x01) { //SR + if(!(pull8(ppReadPackedMsg, &value->sr->sr_indication, end) && + pull8(ppReadPackedMsg, &value->sr->sr_confidence_level, end) + )) + return 0; + } + + // if (((value->pduBitmap >> 1) & 0x01)) { //HARQ + // uint8_t* temp; //&value->harq->num_harq &value->harq->harq_confidence_level &value->harq->harq_list[0].harq_value + // temp = (uint8_t*) malloc(sizeof(uint8_t)); + // //printf("value->harq->num_harq = %d \n", value->harq->num_harq); + // // if(!(pull8(ppReadPackedMsg, temp, end) && + // // pull8(ppReadPackedMsg, temp, end) + // // )) + // // return 0; + + // // for(int i=0; i<1;i++) + // // { + // // if(!(pull8(ppReadPackedMsg, temp, end) //review - gokul + // // )) + // // return 0; + // // } + // } + + return 1; +} + + +static uint8_t unpack_nr_uci_pucch_2_3_4(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_nr_uci_pucch_pdu_format_2_3_4_t* value = (nfapi_nr_uci_pucch_pdu_format_2_3_4_t*) tlv; + + if(!(pull8(ppReadPackedMsg, &value->pduBitmap, end) && + pull32(ppReadPackedMsg, &value->handle, end) && + pull16(ppReadPackedMsg, &value->rnti, end) && + pull8(ppReadPackedMsg, &value->pucch_format, end) && + pull8(ppReadPackedMsg, &value->ul_cqi, end) && + pull16(ppReadPackedMsg, &value->timing_advance, end) && + pull16(ppReadPackedMsg, &value->rssi, end) + )) + return 0; + if (value->pduBitmap & 0x01) { //SR + if(!(pull16(ppReadPackedMsg, &value->sr.sr_bit_len, end) && + pullarray8(ppReadPackedMsg, value->sr.sr_payload, (int)(value->sr.sr_bit_len / 8) + 1, (int)(value->sr.sr_bit_len / 8) + 1, end) + )) + return 0; + } + + if (((value->pduBitmap >> 1) & 0x01)) { //HARQ + if(!(pull8(ppReadPackedMsg, &value->harq.harq_crc, end) && + pull16(ppReadPackedMsg, &value->harq.harq_bit_len, end) && + pullarray8(ppReadPackedMsg, value->harq.harq_payload, (int)(value->harq.harq_bit_len / 8) + 1, (int)(value->harq.harq_bit_len / 8) + 1, end) + )) + return 0; + } + + if (((value->pduBitmap >> 2) & 0x01)) { //CSI-1 + if(!(pull8(ppReadPackedMsg, &value->csi_part1.csi_part1_crc, end) && + pull16(ppReadPackedMsg, &value->csi_part1.csi_part1_bit_len, end) && + pullarray8(ppReadPackedMsg, value->csi_part1.csi_part1_payload, (int)(value->csi_part1.csi_part1_bit_len / 8) + 1, (int)(value->csi_part1.csi_part1_bit_len / 8) + 1, end) + )) + return 0; + } + + if (((value->pduBitmap >> 3) & 0x01)) { //CSI-2 + if(!(pull8(ppReadPackedMsg, &value->csi_part2.csi_part2_crc, end) && + pull16(ppReadPackedMsg, &value->csi_part2.csi_part2_bit_len, end) && + pullarray8(ppReadPackedMsg, value->csi_part2.csi_part2_payload, (int)(value->csi_part2.csi_part2_bit_len / 8) + 1, (int)(value->csi_part2.csi_part2_bit_len / 8) + 1, end) + )) + return 0; + } + + return 1; +} + +static uint8_t unpack_nr_uci_indication_body(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_nr_uci_t* value = (nfapi_nr_uci_t*)tlv; + + if(!(pull16(ppReadPackedMsg, &value->pdu_type, end) && + pull16(ppReadPackedMsg, &value->pdu_size, end) + )) + return 0; + + switch (value->pdu_type) { + case NFAPI_NR_UCI_PUSCH_PDU_TYPE: + printf("Unhandled NFAPI_NR_UCI_PUSCH_PDU_TYPE \n"); + break; + + case NFAPI_NR_UCI_FORMAT_0_1_PDU_TYPE: { + nfapi_nr_uci_pucch_pdu_format_0_1_t* uci_pdu = &value->pucch_pdu_format_0_1; + unpack_nr_uci_pucch_0_1(&uci_pdu, ppReadPackedMsg, end); + break; + } + case NFAPI_NR_UCI_FORMAT_2_3_4_PDU_TYPE: { + nfapi_nr_uci_pucch_pdu_format_2_3_4_t *uci_pdu = &value->pucch_pdu_format_2_3_4; + unpack_nr_uci_pucch_2_3_4(&uci_pdu, ppReadPackedMsg, end); + break; + } + } + + return 1; +} + +static uint8_t unpack_nr_uci_indication(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config) +{ + nfapi_nr_uci_indication_t *pNfapiMsg = (nfapi_nr_uci_indication_t*)msg; + + if (!(pull16(ppReadPackedMsg, &pNfapiMsg->sfn , end) && + pull16(ppReadPackedMsg, &pNfapiMsg->slot , end) && + pull16(ppReadPackedMsg, &pNfapiMsg->num_ucis, end) + )) + return 0; + + for(int i=0; inum_ucis;i++) + { + if(!unpack_nr_uci_indication_body(&pNfapiMsg->uci_list,ppReadPackedMsg,end)) + return 0; + } + +return 1; +} + + static uint8_t unpack_ue_release_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config) { uint8_t proceed = 1; @@ -7699,62 +8301,32 @@ static int check_nr_unpack_length(nfapi_message_id_e msgId, uint32_t unpackedBuf if (unpackedBufLen >= sizeof(nfapi_nr_tx_data_request_t)) retLen = sizeof(nfapi_nr_tx_data_request_t); break; - - case NFAPI_HARQ_INDICATION: - if (unpackedBufLen >= sizeof(nfapi_harq_indication_t)) - retLen = sizeof(nfapi_harq_indication_t); + + case NFAPI_NR_PHY_MSG_TYPE_RX_DATA_INDICATION: + if (unpackedBufLen >= sizeof(nfapi_nr_rx_data_indication_t)) + retLen = sizeof(nfapi_nr_rx_data_indication_t); + break; + + case NFAPI_NR_PHY_MSG_TYPE_CRC_INDICATION: + if (unpackedBufLen >= sizeof(nfapi_nr_crc_indication_t)) + retLen = sizeof(nfapi_nr_crc_indication_t); break; - case NFAPI_CRC_INDICATION: - if (unpackedBufLen >= sizeof(nfapi_crc_indication_t)) - retLen = sizeof(nfapi_crc_indication_t); + case NFAPI_NR_PHY_MSG_TYPE_RACH_INDICATION: + if (unpackedBufLen >= sizeof(nfapi_nr_rach_indication_t)) + retLen = sizeof(nfapi_nr_rach_indication_t); break; - - case NFAPI_RX_ULSCH_INDICATION: - if (unpackedBufLen >= sizeof(nfapi_rx_indication_t)) - retLen = sizeof(nfapi_rx_indication_t); + + case NFAPI_NR_PHY_MSG_TYPE_UCI_INDICATION: + if (unpackedBufLen >= sizeof(nfapi_nr_uci_indication_t)) + retLen = sizeof(nfapi_nr_uci_indication_t); break; - - case NFAPI_RACH_INDICATION: - if (unpackedBufLen >= sizeof(nfapi_rach_indication_t)) - retLen = sizeof(nfapi_rach_indication_t); + + case NFAPI_NR_PHY_MSG_TYPE_SRS_INDICATION: + if (unpackedBufLen >= sizeof(nfapi_nr_srs_indication_t)) + retLen = sizeof(nfapi_nr_srs_indication_t); break; - - case NFAPI_SRS_INDICATION: - if (unpackedBufLen >= sizeof(nfapi_srs_indication_t)) - retLen = sizeof(nfapi_srs_indication_t); - break; - - case NFAPI_RX_SR_INDICATION: - if (unpackedBufLen >= sizeof(nfapi_sr_indication_t)) - retLen = sizeof(nfapi_sr_indication_t); - break; - - case NFAPI_RX_CQI_INDICATION: - if (unpackedBufLen >= sizeof(nfapi_cqi_indication_t)) - retLen = sizeof(nfapi_cqi_indication_t); - break; - - case NFAPI_LBT_DL_CONFIG_REQUEST: - if (unpackedBufLen >= sizeof(nfapi_lbt_dl_config_request_t)) - retLen = sizeof(nfapi_lbt_dl_config_request_t); - break; - - case NFAPI_LBT_DL_INDICATION: - if (unpackedBufLen >= sizeof(nfapi_lbt_dl_indication_t)) - retLen = sizeof(nfapi_lbt_dl_indication_t); - break; - - case NFAPI_NB_HARQ_INDICATION: - if (unpackedBufLen >= sizeof(nfapi_nb_harq_indication_t)) - retLen = sizeof(nfapi_nb_harq_indication_t); - break; - - case NFAPI_NRACH_INDICATION: - if (unpackedBufLen >= sizeof(nfapi_nrach_indication_t)) - retLen = sizeof(nfapi_nrach_indication_t); - break; - + case NFAPI_NR_PHY_MSG_TYPE_DL_NODE_SYNC: if (unpackedBufLen >= sizeof(nfapi_nr_dl_node_sync_t)) retLen = sizeof(nfapi_nr_dl_node_sync_t); @@ -8064,15 +8636,15 @@ int nfapi_nr_p7_message_unpack(void *pMessageBuf, uint32_t messageBufLen, void * NFAPI_TRACE(NFAPI_TRACE_ERROR, "P7 unpack supplied message buffer is too small %d, %d\n", messageBufLen, unpackedBufLen); return -1; } - /* - uint8_t *ptr = pMessageBuf; - printf("\n Read P7 message unpack: "); - while(ptr < end){ - printf(" %d ", *ptr); - ptr++; - } - printf("\n"); -*/ + + // uint8_t *ptr = pMessageBuf; + // printf("\n Read P7 message unpack: "); + // while(ptr < end){ + // printf(" %d ", *ptr); + // ptr++; + // } + // printf("\n"); + // clean the supplied buffer for - tag value blanking (void)memset(pUnpackedBuf, 0, unpackedBufLen); @@ -8138,83 +8710,41 @@ int nfapi_nr_p7_message_unpack(void *pMessageBuf, uint32_t messageBufLen, void * return -1; break; - case NFAPI_HARQ_INDICATION: - if (check_nr_unpack_length(NFAPI_HARQ_INDICATION, unpackedBufLen)) - result = unpack_harq_indication(&pReadPackedMessage, end, pMessageHeader, config); + case NFAPI_NR_PHY_MSG_TYPE_RX_DATA_INDICATION: + if (check_nr_unpack_length(NFAPI_NR_PHY_MSG_TYPE_RX_DATA_INDICATION, unpackedBufLen)) + result = unpack_nr_rx_data_indication(&pReadPackedMessage, end, pMessageHeader, config); else return -1; break; - case NFAPI_CRC_INDICATION: - if (check_nr_unpack_length(NFAPI_CRC_INDICATION, unpackedBufLen)) - result = unpack_crc_indication(&pReadPackedMessage,end , pMessageHeader, config); + case NFAPI_NR_PHY_MSG_TYPE_CRC_INDICATION: + if (check_nr_unpack_length(NFAPI_NR_PHY_MSG_TYPE_CRC_INDICATION, unpackedBufLen)) + result = unpack_nr_crc_indication(&pReadPackedMessage,end , pMessageHeader, config); else return -1; break; - case NFAPI_RX_ULSCH_INDICATION: - if (check_nr_unpack_length(NFAPI_RX_ULSCH_INDICATION, unpackedBufLen)) - result = unpack_rx_indication(&pReadPackedMessage, end, pMessageHeader, config); + case NFAPI_NR_PHY_MSG_TYPE_UCI_INDICATION: + if (check_nr_unpack_length(NFAPI_NR_PHY_MSG_TYPE_UCI_INDICATION, unpackedBufLen)) + result = unpack_nr_uci_indication(&pReadPackedMessage, end, pMessageHeader, config); else return -1; break; - case NFAPI_RACH_INDICATION: - if (check_nr_unpack_length(NFAPI_RACH_INDICATION, unpackedBufLen)) - result = unpack_rach_indication(&pReadPackedMessage, end, pMessageHeader, config); + case NFAPI_NR_PHY_MSG_TYPE_SRS_INDICATION: + if (check_nr_unpack_length(NFAPI_NR_PHY_MSG_TYPE_SRS_INDICATION, unpackedBufLen)) + result = unpack_nr_srs_indication(&pReadPackedMessage, end, pMessageHeader, config); else return -1; break; - case NFAPI_SRS_INDICATION: - if (check_nr_unpack_length(NFAPI_SRS_INDICATION, unpackedBufLen)) - result = unpack_srs_indication(&pReadPackedMessage, end, pMessageHeader, config); + case NFAPI_NR_PHY_MSG_TYPE_RACH_INDICATION: + if (check_nr_unpack_length(NFAPI_NR_PHY_MSG_TYPE_RACH_INDICATION, unpackedBufLen)) + result = unpack_nr_rach_indication(&pReadPackedMessage, end, pMessageHeader, config); else return -1; break; - case NFAPI_RX_SR_INDICATION: - if (check_nr_unpack_length(NFAPI_RX_SR_INDICATION, unpackedBufLen)) - result = unpack_sr_indication(&pReadPackedMessage, end, pMessageHeader, config); - else - return -1; - break; - - case NFAPI_RX_CQI_INDICATION: - if (check_nr_unpack_length(NFAPI_RX_CQI_INDICATION, unpackedBufLen)) - result = unpack_cqi_indication(&pReadPackedMessage, end, pMessageHeader, config); - else - return -1; - break; - - case NFAPI_LBT_DL_CONFIG_REQUEST: - if (check_nr_unpack_length(NFAPI_LBT_DL_CONFIG_REQUEST, unpackedBufLen)) - result = unpack_lbt_dl_config_request(&pReadPackedMessage, end, pMessageHeader, config); - else - return -1; - break; - - case NFAPI_LBT_DL_INDICATION: - if (check_nr_unpack_length(NFAPI_LBT_DL_INDICATION, unpackedBufLen)) - result = unpack_lbt_dl_indication(&pReadPackedMessage, end, pMessageHeader, config); - else - return -1; - break; - - case NFAPI_NB_HARQ_INDICATION: - if (check_nr_unpack_length(NFAPI_NB_HARQ_INDICATION, unpackedBufLen)) - result = unpack_nb_harq_indication(&pReadPackedMessage, end, pMessageHeader, config); - else - return -1; - break; - - case NFAPI_NRACH_INDICATION: - if (check_nr_unpack_length(NFAPI_NRACH_INDICATION, unpackedBufLen)) - result = unpack_nrach_indication(&pReadPackedMessage, end, pMessageHeader, config); - else - return -1; - break; - case NFAPI_NR_PHY_MSG_TYPE_DL_NODE_SYNC: if (check_nr_unpack_length(NFAPI_NR_PHY_MSG_TYPE_DL_NODE_SYNC, unpackedBufLen)) result = unpack_nr_dl_node_sync(&pReadPackedMessage, end, pMessageHeader, config); diff --git a/nfapi/open-nFAPI/pnf/src/pnf_p7_interface.c b/nfapi/open-nFAPI/pnf/src/pnf_p7_interface.c index efcb60ce96..88aa1391cb 100644 --- a/nfapi/open-nFAPI/pnf/src/pnf_p7_interface.c +++ b/nfapi/open-nFAPI/pnf/src/pnf_p7_interface.c @@ -175,17 +175,7 @@ int nfapi_pnf_p7_rach_ind(nfapi_pnf_p7_config_t* config, nfapi_rach_indication_t pnf_p7_t* _this = (pnf_p7_t*)(config); return pnf_p7_pack_and_send_p7_message(_this, (nfapi_p7_message_header_t*)ind, sizeof(nfapi_rach_indication_t)); } -int nfapi_pnf_p7_srs_ind(nfapi_pnf_p7_config_t* config, nfapi_srs_indication_t* ind) -{ - 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); - return pnf_p7_pack_and_send_p7_message(_this, (nfapi_p7_message_header_t*)ind, sizeof(nfapi_srs_indication_t)); -} int nfapi_pnf_p7_sr_ind(nfapi_pnf_p7_config_t* config, nfapi_sr_indication_t* ind) { if(config == NULL || ind == NULL) @@ -265,3 +255,65 @@ int nfapi_pnf_ue_release_resp(nfapi_pnf_p7_config_t* config, nfapi_ue_release_re return pnf_p7_pack_and_send_p7_message(_this, &(resp->header), sizeof(nfapi_ue_release_response_t)); } + +//NR UPLINK INDICATION + +int nfapi_pnf_p7_nr_rx_data_ind(nfapi_pnf_p7_config_t* config, nfapi_nr_rx_data_indication_t* ind) +{ + 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); + return pnf_nr_p7_pack_and_send_p7_message(_this, (nfapi_p7_message_header_t*)ind, sizeof(nfapi_nr_rx_data_indication_t)); +} + +int nfapi_pnf_p7_nr_crc_ind(nfapi_pnf_p7_config_t* config, nfapi_nr_crc_indication_t* ind) +{ + 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); + return pnf_nr_p7_pack_and_send_p7_message(_this, (nfapi_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) +{ + 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); + return pnf_nr_p7_pack_and_send_p7_message(_this, (nfapi_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) +{ + 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); + return pnf_nr_p7_pack_and_send_p7_message(_this, (nfapi_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) +{ + 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); + return pnf_nr_p7_pack_and_send_p7_message(_this, (nfapi_p7_message_header_t*)ind, sizeof(nfapi_nr_rach_indication_t)); +} diff --git a/nfapi/open-nFAPI/vnf/src/vnf_p7.c b/nfapi/open-nFAPI/vnf/src/vnf_p7.c index 8edb168e38..453f0f3769 100644 --- a/nfapi/open-nFAPI/vnf/src/vnf_p7.c +++ b/nfapi/open-nFAPI/vnf/src/vnf_p7.c @@ -1455,6 +1455,102 @@ void vnf_handle_ul_node_sync(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vnf_p7) } } +//NR HANDLES FOR UPLINK MESSAGES + +void vnf_handle_nr_rx_data_indication(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vnf_p7) +{ + // ensure it's valid + if (pRecvMsg == NULL || vnf_p7 == NULL) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__); + } + 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) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: Failed to unpack message\n", __FUNCTION__); + } + + } +} + +void vnf_handle_nr_crc_indication(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vnf_p7) +{ + // ensure it's valid + if (pRecvMsg == NULL || vnf_p7 == NULL) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__); + } + else + { + nfapi_nr_crc_indication_t ind; + + if(nfapi_nr_p7_message_unpack(pRecvMsg, recvMsgLen, &ind, sizeof(ind), &vnf_p7->_public.codec_config) < 0) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: Failed to unpack message\n", __FUNCTION__); + } + + } +} + +void vnf_handle_nr_srs_indication(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vnf_p7) +{ + // ensure it's valid + if (pRecvMsg == NULL || vnf_p7 == NULL) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__); + } + else + { + nfapi_nr_srs_indication_t ind; + + if(nfapi_nr_p7_message_unpack(pRecvMsg, recvMsgLen, &ind, sizeof(ind), &vnf_p7->_public.codec_config) < 0) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: Failed to unpack message\n", __FUNCTION__); + } + + } +} + +void vnf_handle_nr_uci_indication(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vnf_p7) +{ + // ensure it's valid + if (pRecvMsg == NULL || vnf_p7 == NULL) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__); + } + else + { + nfapi_nr_uci_indication_t ind; + + if(nfapi_nr_p7_message_unpack(pRecvMsg, recvMsgLen, &ind, sizeof(ind), &vnf_p7->_public.codec_config) < 0) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: Failed to unpack message\n", __FUNCTION__); + } + } +} + +void vnf_handle_nr_rach_indication(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vnf_p7) +{ + // ensure it's valid + if (pRecvMsg == NULL || vnf_p7 == NULL) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__); + } + else + { + nfapi_nr_rach_indication_t ind; + + if(nfapi_nr_p7_message_unpack(pRecvMsg, recvMsgLen, &ind, sizeof(ind), &vnf_p7->_public.codec_config) < 0) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: Failed to unpack message\n", __FUNCTION__); + } + + } +} + void vnf_nr_handle_ul_node_sync(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vnf_p7) { //printf("received UL Node sync"); @@ -2035,46 +2131,26 @@ void vnf_nr_dispatch_p7_message(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vnf_p7 vnf_nr_handle_timing_info(pRecvMsg, recvMsgLen, vnf_p7); break; - case NFAPI_HARQ_INDICATION: - vnf_handle_harq_indication(pRecvMsg, recvMsgLen, vnf_p7); + case NFAPI_NR_PHY_MSG_TYPE_RX_DATA_INDICATION: + vnf_handle_nr_rx_data_indication(pRecvMsg, recvMsgLen, vnf_p7); break; - case NFAPI_CRC_INDICATION: - vnf_handle_crc_indication(pRecvMsg, recvMsgLen, vnf_p7); + case NFAPI_NR_PHY_MSG_TYPE_CRC_INDICATION: + vnf_handle_nr_crc_indication(pRecvMsg, recvMsgLen, vnf_p7); break; - case NFAPI_RX_ULSCH_INDICATION: - vnf_handle_rx_ulsch_indication(pRecvMsg, recvMsgLen, vnf_p7); + case NFAPI_NR_PHY_MSG_TYPE_UCI_INDICATION: + vnf_handle_nr_uci_indication(pRecvMsg, recvMsgLen, vnf_p7); break; - case NFAPI_RACH_INDICATION: - vnf_handle_rach_indication(pRecvMsg, recvMsgLen, vnf_p7); + case NFAPI_NR_PHY_MSG_TYPE_SRS_INDICATION: + vnf_handle_nr_rach_indication(pRecvMsg, recvMsgLen, vnf_p7); break; - case NFAPI_SRS_INDICATION: - vnf_handle_srs_indication(pRecvMsg, recvMsgLen, vnf_p7); + case NFAPI_NR_PHY_MSG_TYPE_RACH_INDICATION: + vnf_handle_nr_srs_indication(pRecvMsg, recvMsgLen, vnf_p7); break; - case NFAPI_RX_SR_INDICATION: - vnf_handle_rx_sr_indication(pRecvMsg, recvMsgLen, vnf_p7); - break; - - case NFAPI_RX_CQI_INDICATION: - vnf_handle_rx_cqi_indication(pRecvMsg, recvMsgLen, vnf_p7); - break; - - case NFAPI_LBT_DL_INDICATION: - vnf_handle_lbt_dl_indication(pRecvMsg, recvMsgLen, vnf_p7); - break; - - case NFAPI_NB_HARQ_INDICATION: - vnf_handle_nb_harq_indication(pRecvMsg, recvMsgLen, vnf_p7); - break; - - case NFAPI_NRACH_INDICATION: - vnf_handle_nrach_indication(pRecvMsg, recvMsgLen, vnf_p7); - break; - case NFAPI_UE_RELEASE_RESPONSE: vnf_handle_ue_release_resp(pRecvMsg, recvMsgLen, vnf_p7); break; diff --git a/openair2/NR_PHY_INTERFACE/NR_IF_Module.c b/openair2/NR_PHY_INTERFACE/NR_IF_Module.c index 9c118ec53b..2e0abda556 100644 --- a/openair2/NR_PHY_INTERFACE/NR_IF_Module.c +++ b/openair2/NR_PHY_INTERFACE/NR_IF_Module.c @@ -54,7 +54,14 @@ extern uint16_t sf_ahead; extern uint16_t sl_ahead; 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) { + //LOG_D(PHY,"UL_info->crc_ind.crc_indication_body.number_of_crcs:%d CRC_IND:SFN/SF:%d\n", UL_info->crc_ind.crc_indication_body.number_of_crcs, NFAPI_SFNSF2DEC(UL_info->crc_ind.sfn_sf)); + oai_nfapi_nr_rach_indication(&UL_info->rach_ind); + UL_info->rach_ind.number_of_pdus = 0; + } + } + else { if (UL_info->rach_ind.number_of_pdus>0) { LOG_I(MAC,"UL_info[Frame %d, Slot %d] Calling initiate_ra_proc RACH:SFN/SLOT:%d/%d\n",UL_info->frame,UL_info->slot, UL_info->rach_ind.sfn,UL_info->rach_ind.slot); int npdus = UL_info->rach_ind.number_of_pdus; @@ -75,10 +82,19 @@ void handle_nr_rach(NR_UL_IND_t *UL_info) { } } } +} void handle_nr_uci(NR_UL_IND_t *UL_info) -{ +{ + if(NFAPI_MODE == NFAPI_MODE_PNF) { + if (UL_info->uci_ind.num_ucis>0) { + //LOG_D(PHY,"UL_info->crc_ind.crc_indication_body.number_of_crcs:%d CRC_IND:SFN/SF:%d\n", UL_info->crc_ind.crc_indication_body.number_of_crcs, NFAPI_SFNSF2DEC(UL_info->crc_ind.sfn_sf)); + //oai_nfapi_nr_uci_indication(&UL_info->uci_ind); + UL_info->uci_ind.num_ucis = 0; + } + } + else { const module_id_t mod_id = UL_info->module_id; const frame_t frame = UL_info->frame; const sub_frame_t slot = UL_info->slot; @@ -110,10 +126,24 @@ void handle_nr_uci(NR_UL_IND_t *UL_info) // NOTE: we just assume it is BWP ID 1, to be revised for multiple BWPs RC.nrmac[mod_id]->pucch_index_used[1][slot] = 0; } - +} void handle_nr_ulsch(NR_UL_IND_t *UL_info) -{ +{ + if(NFAPI_MODE == NFAPI_MODE_PNF) { + if (UL_info->crc_ind.number_crcs>0) { + //LOG_D(PHY,"UL_info->crc_ind.crc_indication_body.number_of_crcs:%d CRC_IND:SFN/SF:%d\n", UL_info->crc_ind.crc_indication_body.number_of_crcs, NFAPI_SFNSF2DEC(UL_info->crc_ind.sfn_sf)); + oai_nfapi_nr_crc_indication(&UL_info->crc_ind); + UL_info->crc_ind.number_crcs = 0; + } + + if (UL_info->rx_ind.number_of_pdus>0) { + //LOG_D(PHY,"UL_info->rx_ind.number_of_pdus:%d RX_IND:SFN/SF:%d\n", UL_info->rx_ind.rx_indication_body.number_of_pdus, NFAPI_SFNSF2DEC(UL_info->rx_ind.sfn_sf)); + oai_nfapi_nr_rx_data_indication(&UL_info->rx_ind); + UL_info->rx_ind.number_of_pdus = 0; + } + } + else { if (UL_info->rx_ind.number_of_pdus > 0 && UL_info->crc_ind.number_crcs > 0) { for (int i = 0; i < UL_info->rx_ind.number_of_pdus; i++) { for (int j = 0; j < UL_info->crc_ind.number_crcs; j++) { @@ -139,17 +169,16 @@ void handle_nr_ulsch(NR_UL_IND_t *UL_info) crc->tb_crc_status); /* if CRC passes, pass PDU, otherwise pass NULL as error indication */ - //Gokul - // nr_rx_sdu(UL_info->module_id, - // UL_info->CC_id, - // UL_info->rx_ind.sfn, - // UL_info->rx_ind.slot, - // rx->rnti, - // crc->tb_crc_status ? NULL : rx->pdu, - // rx->pdu_length, - // rx->timing_advance, - // rx->ul_cqi, - // rx->rssi); + nr_rx_sdu(UL_info->module_id, + UL_info->CC_id, + UL_info->rx_ind.sfn, + UL_info->rx_ind.slot, + rx->rnti, + crc->tb_crc_status ? NULL : rx->pdu, + rx->pdu_length, + rx->timing_advance, + rx->ul_cqi, + rx->rssi); //handle_nr_ul_harq(UL_info->module_id, UL_info->frame, UL_info->slot, crc); break; } // for (j=0;jcrc_ind.number_crcs;j++) @@ -169,6 +198,7 @@ void handle_nr_ulsch(NR_UL_IND_t *UL_info) UL_info->crc_ind.number_crcs, UL_info->rx_ind.sfn, UL_info->rx_ind.slot); + } } } From 7577df940178fad649b0f8b3a7ef39011cd37039 Mon Sep 17 00:00:00 2001 From: francescomani Date: Thu, 6 May 2021 10:53:13 +0200 Subject: [PATCH 09/91] adding rsrp to ssb indication --- nfapi/open-nFAPI/nfapi/public_inc/fapi_nr_ue_interface.h | 1 + openair1/SCHED_NR_UE/phy_procedures_nr_ue.c | 1 + openair2/LAYER2/NR_MAC_UE/mac_defs.h | 3 +++ openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c | 2 +- 4 files changed, 6 insertions(+), 1 deletion(-) 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 c0abf6acb0..dd7cf21895 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 @@ -112,6 +112,7 @@ typedef struct { uint8_t ssb_length; uint16_t cell_id; uint16_t ssb_start_subcarrier; + short rsrp_dBm; } fapi_nr_ssb_pdu_t; typedef struct { diff --git a/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c b/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c index 179a25bad9..19f90d3686 100644 --- a/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c +++ b/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c @@ -146,6 +146,7 @@ void nr_fill_rx_indication(fapi_nr_rx_indication_t *rx_ind, rx_ind->rx_indication_body[n_pdus - 1].ssb_pdu.ssb_length = frame_parms->Lmax; rx_ind->rx_indication_body[n_pdus - 1].ssb_pdu.cell_id = frame_parms->Nid_cell; rx_ind->rx_indication_body[n_pdus - 1].ssb_pdu.ssb_start_subcarrier = frame_parms->ssb_start_subcarrier; + rx_ind->rx_indication_body[n_pdus - 1].ssb_pdu.rsrp_dBm = ue->measurements.rsrp_dBm[gNB_id]; break; default: break; diff --git a/openair2/LAYER2/NR_MAC_UE/mac_defs.h b/openair2/LAYER2/NR_MAC_UE/mac_defs.h index 5f7ab73605..2e97e2fa9a 100755 --- a/openair2/LAYER2/NR_MAC_UE/mac_defs.h +++ b/openair2/LAYER2/NR_MAC_UE/mac_defs.h @@ -362,6 +362,9 @@ typedef struct { RA_config_t ra; /// SSB index from MIB decoding uint8_t mib_ssb; + /// measured SSB RSRP in dBm + short ssb_rsrp_dBm; + /// Last NDI of UL HARQ processes uint8_t UL_ndi[NR_MAX_HARQ_PROCESSES]; /// first ULTX of UL HARQ processes diff --git a/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c b/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c index 5b020b5988..876bdafd05 100644 --- a/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c +++ b/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c @@ -164,7 +164,7 @@ int nr_ue_dl_indication(nr_downlink_indication_t *dl_info, NR_UL_TIME_ALIGNMENT_ switch(dl_info->rx_ind->rx_indication_body[i].pdu_type){ case FAPI_NR_RX_PDU_TYPE_SSB: - + mac->ssb_rsrp_dBm = (dl_info->rx_ind->rx_indication_body+i)->ssb_pdu.rsrp_dBm; ret_mask |= (handle_bcch_bch(dl_info->module_id, dl_info->cc_id, dl_info->gNB_index, (dl_info->rx_ind->rx_indication_body+i)->ssb_pdu.pdu, (dl_info->rx_ind->rx_indication_body+i)->ssb_pdu.additional_bits, From f691d8805afb7d2c71d87b82242143754270a79e Mon Sep 17 00:00:00 2001 From: francescomani Date: Thu, 6 May 2021 17:40:59 +0200 Subject: [PATCH 10/91] formatting in nr_ue_dlsch_procedures --- openair1/SCHED_NR_UE/phy_procedures_nr_ue.c | 453 ++++++++++---------- 1 file changed, 224 insertions(+), 229 deletions(-) diff --git a/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c b/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c index 19f90d3686..b2073c5b30 100644 --- a/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c +++ b/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c @@ -858,13 +858,13 @@ int nr_ue_pdsch_procedures(PHY_VARS_NR_UE *ue, UE_nr_rxtx_proc_t *proc, int eNB_ } void nr_ue_dlsch_procedures(PHY_VARS_NR_UE *ue, - UE_nr_rxtx_proc_t *proc, - int eNB_id, - PDSCH_t pdsch, - NR_UE_DLSCH_t *dlsch0, - NR_UE_DLSCH_t *dlsch1, - int *dlsch_errors, - uint8_t dlsch_parallel) { + UE_nr_rxtx_proc_t *proc, + int gNB_id, + PDSCH_t pdsch, + NR_UE_DLSCH_t *dlsch0, + NR_UE_DLSCH_t *dlsch1, + int *dlsch_errors, + uint8_t dlsch_parallel) { if (dlsch0==NULL) AssertFatal(0,"dlsch0 should be defined at this level \n"); @@ -879,7 +879,7 @@ void nr_ue_dlsch_procedures(PHY_VARS_NR_UE *ue, fapi_nr_rx_indication_t rx_ind; uint16_t number_pdus = 1; // params for UL time alignment procedure - NR_UL_TIME_ALIGNMENT_t *ul_time_alignment = &ue->ul_time_alignment[eNB_id]; + NR_UL_TIME_ALIGNMENT_t *ul_time_alignment = &ue->ul_time_alignment[gNB_id]; uint8_t is_cw0_active = dlsch0->harq_processes[harq_pid]->status; uint16_t nb_symb_sch = dlsch0->harq_processes[harq_pid]->nb_symbols; @@ -916,7 +916,7 @@ void nr_ue_dlsch_procedures(PHY_VARS_NR_UE *ue, case RA_PDSCH: case P_PDSCH: case PDSCH: - pdsch_vars = ue->pdsch_vars[proc->thread_id][eNB_id]; + pdsch_vars = ue->pdsch_vars[proc->thread_id][gNB_id]; break; case PMCH: case PDSCH1: @@ -934,8 +934,8 @@ void nr_ue_dlsch_procedures(PHY_VARS_NR_UE *ue, *dlsch_errors=0; if (pdsch == RA_PDSCH) { - if (ue->prach_resources[eNB_id]!=NULL) - dlsch0->rnti = ue->prach_resources[eNB_id]->ra_RNTI; + if (ue->prach_resources[gNB_id]!=NULL) + dlsch0->rnti = ue->prach_resources[gNB_id]->ra_RNTI; else { LOG_E(PHY,"[UE %d] Frame %d, nr_slot_rx %d: FATAL, prach_resources is NULL\n", ue->Mod_id, frame_rx, nr_slot_rx); //mac_xface->macphy_exit("prach_resources is NULL"); @@ -955,17 +955,17 @@ void nr_ue_dlsch_procedures(PHY_VARS_NR_UE *ue, dlsch0->harq_processes[harq_pid]->Qm, dlsch0->harq_processes[harq_pid]->Nl); #if UE_TIMING_TRACE - start_meas(&ue->dlsch_unscrambling_stats); + start_meas(&ue->dlsch_unscrambling_stats); #endif - nr_dlsch_unscrambling(pdsch_vars->llr[0], - dlsch0->harq_processes[harq_pid]->G, - 0, - ue->frame_parms.Nid_cell, - dlsch0->rnti); + nr_dlsch_unscrambling(pdsch_vars->llr[0], + dlsch0->harq_processes[harq_pid]->G, + 0, + ue->frame_parms.Nid_cell, + dlsch0->rnti); #if UE_TIMING_TRACE - stop_meas(&ue->dlsch_unscrambling_stats); + stop_meas(&ue->dlsch_unscrambling_stats); #endif #if 0 @@ -976,83 +976,81 @@ void nr_ue_dlsch_procedures(PHY_VARS_NR_UE *ue, LOG_I(PHY,"start ldpc decode for CW 0 for AbsSubframe %d.%d / %d --> Nl %d \n", frame_rx, nr_slot_rx, harq_pid, dlsch0->harq_processes[harq_pid]->Nl); LOG_I(PHY,"start ldpc decode for CW 0 for AbsSubframe %d.%d / %d --> G %d \n", frame_rx, nr_slot_rx, harq_pid, dlsch0->harq_processes[harq_pid]->G); LOG_I(PHY,"start ldpc decode for CW 0 for AbsSubframe %d.%d / %d --> Kmimo %d \n", frame_rx, nr_slot_rx, harq_pid, dlsch0->Kmimo); - LOG_I(PHY,"start ldpc decode for CW 0 for AbsSubframe %d.%d / %d --> Pdcch Sym %d \n", frame_rx, nr_slot_rx, harq_pid, ue->pdcch_vars[proc->thread_id][eNB_id]->num_pdcch_symbols); + LOG_I(PHY,"start ldpc decode for CW 0 for AbsSubframe %d.%d / %d --> Pdcch Sym %d \n", frame_rx, nr_slot_rx, harq_pid, ue->pdcch_vars[proc->thread_id][gNB_id]->num_pdcch_symbols); #endif #if UE_TIMING_TRACE - start_meas(&ue->dlsch_decoding_stats[proc->thread_id]); + start_meas(&ue->dlsch_decoding_stats[proc->thread_id]); #endif - if( dlsch_parallel) - { - ret = nr_dlsch_decoding_mthread(ue, - proc, - eNB_id, - pdsch_vars->llr[0], - &ue->frame_parms, - dlsch0, - dlsch0->harq_processes[harq_pid], - frame_rx, - nb_symb_sch, - nr_slot_rx, - harq_pid, - pdsch==PDSCH?1:0, - dlsch0->harq_processes[harq_pid]->TBS>256?1:0); - LOG_T(PHY,"dlsch decoding is parallelized, ret = %d\n", ret); + if( dlsch_parallel) { + ret = nr_dlsch_decoding_mthread(ue, + proc, + gNB_id, + pdsch_vars->llr[0], + &ue->frame_parms, + dlsch0, + dlsch0->harq_processes[harq_pid], + frame_rx, + nb_symb_sch, + nr_slot_rx, + harq_pid, + pdsch==PDSCH?1:0, + dlsch0->harq_processes[harq_pid]->TBS>256?1:0); + + LOG_T(PHY,"dlsch decoding is parallelized, ret = %d\n", ret); } - else - { - ret = nr_dlsch_decoding(ue, - proc, - eNB_id, - pdsch_vars->llr[0], - &ue->frame_parms, - dlsch0, - dlsch0->harq_processes[harq_pid], - frame_rx, - nb_symb_sch, - nr_slot_rx, - harq_pid, - pdsch==PDSCH?1:0, - dlsch0->harq_processes[harq_pid]->TBS>256?1:0); + else { + ret = nr_dlsch_decoding(ue, + proc, + gNB_id, + pdsch_vars->llr[0], + &ue->frame_parms, + dlsch0, + dlsch0->harq_processes[harq_pid], + frame_rx, + nb_symb_sch, + nr_slot_rx, + harq_pid, + pdsch==PDSCH?1:0, + dlsch0->harq_processes[harq_pid]->TBS>256?1:0); LOG_T(PHY,"Sequential dlsch decoding , ret = %d\n", ret); - } + } #if UE_TIMING_TRACE - stop_meas(&ue->dlsch_decoding_stats[proc->thread_id]); + stop_meas(&ue->dlsch_decoding_stats[proc->thread_id]); #if DISABLE_LOG_X - printf(" --> Unscrambling for CW0 %5.3f\n", - (ue->dlsch_unscrambling_stats.p_time)/(cpuf*1000.0)); - printf("AbsSubframe %d.%d --> LDPC Decoding for CW0 %5.3f\n", - frame_rx%1024, nr_slot_rx,(ue->dlsch_decoding_stats[proc->thread_id].p_time)/(cpuf*1000.0)); + printf(" --> Unscrambling for CW0 %5.3f\n", + (ue->dlsch_unscrambling_stats.p_time)/(cpuf*1000.0)); + printf("AbsSubframe %d.%d --> LDPC Decoding for CW0 %5.3f\n", + frame_rx%1024, nr_slot_rx,(ue->dlsch_decoding_stats[proc->thread_id].p_time)/(cpuf*1000.0)); #else - LOG_I(PHY, " --> Unscrambling for CW0 %5.3f\n", - (ue->dlsch_unscrambling_stats.p_time)/(cpuf*1000.0)); - LOG_I(PHY, "AbsSubframe %d.%d --> LDPC Decoding for CW0 %5.3f\n", - frame_rx%1024, nr_slot_rx,(ue->dlsch_decoding_stats[proc->thread_id].p_time)/(cpuf*1000.0)); + LOG_I(PHY, " --> Unscrambling for CW0 %5.3f\n", + (ue->dlsch_unscrambling_stats.p_time)/(cpuf*1000.0)); + LOG_I(PHY, "AbsSubframe %d.%d --> LDPC Decoding for CW0 %5.3f\n", + frame_rx%1024, nr_slot_rx,(ue->dlsch_decoding_stats[proc->thread_id].p_time)/(cpuf*1000.0)); #endif #endif - if(is_cw1_active) - { - // start ldpc decode for CW 1 - dlsch1->harq_processes[harq_pid]->G = nr_get_G(dlsch1->harq_processes[harq_pid]->nb_rb, - nb_symb_sch, - nb_re_dmrs, - dmrs_len, - dlsch1->harq_processes[harq_pid]->Qm, - dlsch1->harq_processes[harq_pid]->Nl); + if(is_cw1_active) { + // start ldpc decode for CW 1 + dlsch1->harq_processes[harq_pid]->G = nr_get_G(dlsch1->harq_processes[harq_pid]->nb_rb, + nb_symb_sch, + nb_re_dmrs, + dmrs_len, + dlsch1->harq_processes[harq_pid]->Qm, + dlsch1->harq_processes[harq_pid]->Nl); #if UE_TIMING_TRACE - start_meas(&ue->dlsch_unscrambling_stats); + start_meas(&ue->dlsch_unscrambling_stats); #endif - nr_dlsch_unscrambling(pdsch_vars->llr[1], - dlsch1->harq_processes[harq_pid]->G, - 0, - ue->frame_parms.Nid_cell, - dlsch1->rnti); + nr_dlsch_unscrambling(pdsch_vars->llr[1], + dlsch1->harq_processes[harq_pid]->G, + 0, + ue->frame_parms.Nid_cell, + dlsch1->rnti); #if UE_TIMING_TRACE - stop_meas(&ue->dlsch_unscrambling_stats); + stop_meas(&ue->dlsch_unscrambling_stats); #endif #if 0 @@ -1062,185 +1060,182 @@ void nr_ue_dlsch_procedures(PHY_VARS_NR_UE *ue, LOG_I(PHY,"start ldpc decode for CW 1 for AbsSubframe %d.%d / %d --> Nl %d \n", frame_rx, nr_slot_rx, harq_pid, dlsch1->harq_processes[harq_pid]->Nl); LOG_I(PHY,"start ldpc decode for CW 1 for AbsSubframe %d.%d / %d --> G %d \n", frame_rx, nr_slot_rx, harq_pid, dlsch1->harq_processes[harq_pid]->G); LOG_I(PHY,"start ldpc decode for CW 1 for AbsSubframe %d.%d / %d --> Kmimo %d \n", frame_rx, nr_slot_rx, harq_pid, dlsch1->Kmimo); - LOG_I(PHY,"start ldpc decode for CW 1 for AbsSubframe %d.%d / %d --> Pdcch Sym %d \n", frame_rx, nr_slot_rx, harq_pid, ue->pdcch_vars[proc->thread_id][eNB_id]->num_pdcch_symbols); + LOG_I(PHY,"start ldpc decode for CW 1 for AbsSubframe %d.%d / %d --> Pdcch Sym %d \n", frame_rx, nr_slot_rx, harq_pid, ue->pdcch_vars[proc->thread_id][gNB_id]->num_pdcch_symbols); #endif #if UE_TIMING_TRACE - start_meas(&ue->dlsch_decoding_stats[proc->thread_id]); + start_meas(&ue->dlsch_decoding_stats[proc->thread_id]); #endif - if(dlsch_parallel) - { - ret1 = nr_dlsch_decoding_mthread(ue, - proc, - eNB_id, - pdsch_vars->llr[1], - &ue->frame_parms, - dlsch1, - dlsch1->harq_processes[harq_pid], - frame_rx, - nb_symb_sch, - nr_slot_rx, - harq_pid, - pdsch==PDSCH?1:0, - dlsch1->harq_processes[harq_pid]->TBS>256?1:0); - LOG_T(PHY,"CW dlsch decoding is parallelized, ret1 = %d\n", ret1); - } - else - { - ret1 = nr_dlsch_decoding(ue, - proc, - eNB_id, - pdsch_vars->llr[1], - &ue->frame_parms, - dlsch1, - dlsch1->harq_processes[harq_pid], - frame_rx, - nb_symb_sch, - nr_slot_rx, - harq_pid, - pdsch==PDSCH?1:0,//proc->decoder_switch, - dlsch1->harq_processes[harq_pid]->TBS>256?1:0); - LOG_T(PHY,"CWW sequential dlsch decoding, ret1 = %d\n", ret1); - } + if(dlsch_parallel) { + ret1 = nr_dlsch_decoding_mthread(ue, + proc, + gNB_id, + pdsch_vars->llr[1], + &ue->frame_parms, + dlsch1, + dlsch1->harq_processes[harq_pid], + frame_rx, + nb_symb_sch, + nr_slot_rx, + harq_pid, + pdsch==PDSCH?1:0, + dlsch1->harq_processes[harq_pid]->TBS>256?1:0); + LOG_T(PHY,"CW dlsch decoding is parallelized, ret1 = %d\n", ret1); + } + else { + ret1 = nr_dlsch_decoding(ue, + proc, + gNB_id, + pdsch_vars->llr[1], + &ue->frame_parms, + dlsch1, + dlsch1->harq_processes[harq_pid], + frame_rx, + nb_symb_sch, + nr_slot_rx, + harq_pid, + pdsch==PDSCH?1:0,//proc->decoder_switch, + dlsch1->harq_processes[harq_pid]->TBS>256?1:0); + LOG_T(PHY,"CWW sequential dlsch decoding, ret1 = %d\n", ret1); + } #if UE_TIMING_TRACE - stop_meas(&ue->dlsch_decoding_stats[proc->thread_id]); + stop_meas(&ue->dlsch_decoding_stats[proc->thread_id]); #if DISABLE_LOG_X - printf(" --> Unscrambling for CW1 %5.3f\n", - (ue->dlsch_unscrambling_stats.p_time)/(cpuf*1000.0)); - printf("AbsSubframe %d.%d --> ldpc Decoding for CW1 %5.3f\n", - frame_rx%1024, nr_slot_rx,(ue->dlsch_decoding_stats[proc->thread_id].p_time)/(cpuf*1000.0)); + printf(" --> Unscrambling for CW1 %5.3f\n", + (ue->dlsch_unscrambling_stats.p_time)/(cpuf*1000.0)); + printf("AbsSubframe %d.%d --> ldpc Decoding for CW1 %5.3f\n", + frame_rx%1024, nr_slot_rx,(ue->dlsch_decoding_stats[proc->thread_id].p_time)/(cpuf*1000.0)); #else - LOG_D(PHY, " --> Unscrambling for CW1 %5.3f\n", - (ue->dlsch_unscrambling_stats.p_time)/(cpuf*1000.0)); - LOG_D(PHY, "AbsSubframe %d.%d --> ldpc Decoding for CW1 %5.3f\n", - frame_rx%1024, nr_slot_rx,(ue->dlsch_decoding_stats[proc->thread_id].p_time)/(cpuf*1000.0)); + LOG_D(PHY, " --> Unscrambling for CW1 %5.3f\n", + (ue->dlsch_unscrambling_stats.p_time)/(cpuf*1000.0)); + LOG_D(PHY, "AbsSubframe %d.%d --> ldpc Decoding for CW1 %5.3f\n", + frame_rx%1024, nr_slot_rx,(ue->dlsch_decoding_stats[proc->thread_id].p_time)/(cpuf*1000.0)); #endif #endif - LOG_I(PHY,"AbsSubframe %d.%d --> ldpc Decoding for CW1 %5.3f\n", - frame_rx%1024, nr_slot_rx,(ue->dlsch_decoding_stats[proc->thread_id].p_time)/(cpuf*1000.0)); + LOG_I(PHY,"AbsSubframe %d.%d --> ldpc Decoding for CW1 %5.3f\n", + frame_rx%1024, nr_slot_rx,(ue->dlsch_decoding_stats[proc->thread_id].p_time)/(cpuf*1000.0)); - LOG_D(PHY, "harq_pid: %d, TBS expected dlsch1: %d \n", harq_pid, dlsch1->harq_processes[harq_pid]->TBS); + LOG_D(PHY, "harq_pid: %d, TBS expected dlsch1: %d \n", harq_pid, dlsch1->harq_processes[harq_pid]->TBS); + } + + LOG_D(PHY," ------ end ldpc decoder for AbsSubframe %d.%d ------ decoded in %d \n", frame_rx, nr_slot_rx, ret); + LOG_D(PHY, "harq_pid: %d, TBS expected dlsch0: %d \n",harq_pid, dlsch0->harq_processes[harq_pid]->TBS); + + if(retmax_ldpc_iterations+1){ + + switch (pdsch) { + case RA_PDSCH: + nr_fill_dl_indication(&dl_indication, NULL, &rx_ind, proc, ue, gNB_id); + nr_fill_rx_indication(&rx_ind, FAPI_NR_RX_PDU_TYPE_RAR, gNB_id, ue, dlsch0, number_pdus); + ue->UE_mode[gNB_id] = RA_RESPONSE; + break; + case PDSCH: + nr_fill_dl_indication(&dl_indication, NULL, &rx_ind, proc, ue, gNB_id); + nr_fill_rx_indication(&rx_ind, FAPI_NR_RX_PDU_TYPE_DLSCH, gNB_id, ue, dlsch0, number_pdus); + break; + case SI_PDSCH: + nr_fill_dl_indication(&dl_indication, NULL, &rx_ind, proc, ue, gNB_id); + nr_fill_rx_indication(&rx_ind, FAPI_NR_RX_PDU_TYPE_SIB, gNB_id, ue, dlsch0, number_pdus); + break; + default: + break; } - LOG_D(PHY," ------ end ldpc decoder for AbsSubframe %d.%d ------ decoded in %d \n", frame_rx, nr_slot_rx, ret); - LOG_D(PHY, "harq_pid: %d, TBS expected dlsch0: %d \n",harq_pid, dlsch0->harq_processes[harq_pid]->TBS); + LOG_D(PHY, "In %s DL PDU length in bits: %d, in bytes: %d \n", __FUNCTION__, dlsch0->harq_processes[harq_pid]->TBS, dlsch0->harq_processes[harq_pid]->TBS / 8); - if(retmax_ldpc_iterations+1){ - - switch (pdsch) { - case RA_PDSCH: - nr_fill_dl_indication(&dl_indication, NULL, &rx_ind, proc, ue, eNB_id); - nr_fill_rx_indication(&rx_ind, FAPI_NR_RX_PDU_TYPE_RAR, eNB_id, ue, dlsch0, number_pdus); - - ue->UE_mode[eNB_id] = RA_RESPONSE; - break; - case PDSCH: - nr_fill_dl_indication(&dl_indication, NULL, &rx_ind, proc, ue, eNB_id); - nr_fill_rx_indication(&rx_ind, FAPI_NR_RX_PDU_TYPE_DLSCH, eNB_id, ue, dlsch0, number_pdus); - break; - case SI_PDSCH: - nr_fill_dl_indication(&dl_indication, NULL, &rx_ind, proc, ue, eNB_id); - nr_fill_rx_indication(&rx_ind, FAPI_NR_RX_PDU_TYPE_SIB, eNB_id, ue, dlsch0, number_pdus); - break; - default: - break; - } - - LOG_D(PHY, "In %s DL PDU length in bits: %d, in bytes: %d \n", __FUNCTION__, dlsch0->harq_processes[harq_pid]->TBS, dlsch0->harq_processes[harq_pid]->TBS / 8); - - // send to mac - if (ue->if_inst && ue->if_inst->dl_indication) { - ue->if_inst->dl_indication(&dl_indication, ul_time_alignment); - } + // send to mac + if (ue->if_inst && ue->if_inst->dl_indication) { + ue->if_inst->dl_indication(&dl_indication, ul_time_alignment); } + } - if (ue->mac_enabled == 1) { + if (ue->mac_enabled == 1) { - /* Time Alignment procedure - // - UE processing capability 1 - // - Setting the TA update to be applied after the reception of the TA command - // - Timing adjustment computed according to TS 38.213 section 4.2 - // - Durations of N1 and N2 symbols corresponding to PDSCH and PUSCH are - // computed according to sections 5.3 and 6.4 of TS 38.214 */ - const int numerology = ue->frame_parms.numerology_index; - const int ofdm_symbol_size = ue->frame_parms.ofdm_symbol_size; - const int nb_prefix_samples = ue->frame_parms.nb_prefix_samples; - const int samples_per_subframe = ue->frame_parms.samples_per_subframe; - const int slots_per_frame = ue->frame_parms.slots_per_frame; - const int slots_per_subframe = ue->frame_parms.slots_per_subframe; + /* Time Alignment procedure + // - UE processing capability 1 + // - Setting the TA update to be applied after the reception of the TA command + // - Timing adjustment computed according to TS 38.213 section 4.2 + // - Durations of N1 and N2 symbols corresponding to PDSCH and PUSCH are + // computed according to sections 5.3 and 6.4 of TS 38.214 */ + const int numerology = ue->frame_parms.numerology_index; + const int ofdm_symbol_size = ue->frame_parms.ofdm_symbol_size; + const int nb_prefix_samples = ue->frame_parms.nb_prefix_samples; + const int samples_per_subframe = ue->frame_parms.samples_per_subframe; + const int slots_per_frame = ue->frame_parms.slots_per_frame; + const int slots_per_subframe = ue->frame_parms.slots_per_subframe; - const double tc_factor = 1.0 / samples_per_subframe; - const uint16_t bw_scaling = get_bw_scaling(ofdm_symbol_size); + const double tc_factor = 1.0 / samples_per_subframe; + const uint16_t bw_scaling = get_bw_scaling(ofdm_symbol_size); - const int Ta_max = 3846; // Max value of 12 bits TA Command - const double N_TA_max = Ta_max * bw_scaling * tc_factor; + const int Ta_max = 3846; // Max value of 12 bits TA Command + const double N_TA_max = Ta_max * bw_scaling * tc_factor; - /* PDSCH decoding time N_1 for processing capability 1 */ - int N_1; - if (ue->dmrs_DownlinkConfig.pdsch_dmrs_AdditionalPosition == pdsch_dmrs_pos0) - N_1 = pdsch_N_1_capability_1[numerology][1]; - else if (ue->dmrs_DownlinkConfig.pdsch_dmrs_AdditionalPosition == pdsch_dmrs_pos1 || ue->dmrs_DownlinkConfig.pdsch_dmrs_AdditionalPosition == 2) // TODO set to pdsch_dmrs_pos2 when available - N_1 = pdsch_N_1_capability_1[numerology][2]; - else - N_1 = pdsch_N_1_capability_1[numerology][3]; + /* PDSCH decoding time N_1 for processing capability 1 */ + int N_1; + if (ue->dmrs_DownlinkConfig.pdsch_dmrs_AdditionalPosition == pdsch_dmrs_pos0) + N_1 = pdsch_N_1_capability_1[numerology][1]; + else if (ue->dmrs_DownlinkConfig.pdsch_dmrs_AdditionalPosition == pdsch_dmrs_pos1 || ue->dmrs_DownlinkConfig.pdsch_dmrs_AdditionalPosition == 2) // TODO set to pdsch_dmrs_pos2 when available + N_1 = pdsch_N_1_capability_1[numerology][2]; + else + N_1 = pdsch_N_1_capability_1[numerology][3]; + /* PUSCH preapration time N_2 for processing capability 1 */ + const int N_2 = pusch_N_2_timing_capability_1[numerology][1]; - /* PUSCH preapration time N_2 for processing capability 1 */ - const int N_2 = pusch_N_2_timing_capability_1[numerology][1]; - - /* d_1_1 depending on the number of PDSCH symbols allocated */ - const int d = 0; // TODO number of overlapping symbols of the scheduling PDCCH and the scheduled PDSCH - int d_1_1 = 0; - mappingType_t mapping_type_dl = ue->PDSCH_Config.pdsch_TimeDomainResourceAllocation[0]->mappingType; - if (mapping_type_dl == typeA) - if (nb_symb_sch + start_symbol < 7) + /* d_1_1 depending on the number of PDSCH symbols allocated */ + const int d = 0; // TODO number of overlapping symbols of the scheduling PDCCH and the scheduled PDSCH + int d_1_1 = 0; + mappingType_t mapping_type_dl = ue->PDSCH_Config.pdsch_TimeDomainResourceAllocation[0]->mappingType; + if (mapping_type_dl == typeA) + if (nb_symb_sch + start_symbol < 7) d_1_1 = 7 - (nb_symb_sch + start_symbol); - else - d_1_1 = 0; - else // mapping type B - switch (nb_symb_sch){ - case 7: d_1_1 = 0; break; - case 4: d_1_1 = 3; break; - case 2: d_1_1 = 3 + d; break; - default: break; - } - - /* d_2_1 */ - int d_2_1; - mappingType_t mapping_type_ul = ue->pusch_config.pusch_TimeDomainResourceAllocation[0]->mappingType; - if (mapping_type_ul == typeB && start_symbol != 0) - d_2_1 = 0; else - d_2_1 = 1; - - /* d_2_2 */ - const double d_2_2 = 0.0; // set to 0 because there is only 1 BWP: TODO this should corresponds to the switching time as defined in TS 38.133 - - /* N_t_1 time duration in msec of N_1 symbols corresponding to a PDSCH reception time - // N_t_2 time duration in msec of N_2 symbols corresponding to a PUSCH preparation time */ - double N_t_1 = (N_1 + d_1_1) * (ofdm_symbol_size + nb_prefix_samples) * tc_factor; - double N_t_2 = (N_2 + d_2_1) * (ofdm_symbol_size + nb_prefix_samples) * tc_factor; - if (N_t_2 < d_2_2) N_t_2 = d_2_2; - - /* Time alignment procedure */ - // N_t_1 + N_t_2 + N_TA_max must be in msec - const double t_subframe = 1.0; // subframe duration of 1 msec - const int ul_tx_timing_adjustment = 1 + (int)ceil(slots_per_subframe*(N_t_1 + N_t_2 + N_TA_max + 0.5)/t_subframe); - - if (ul_time_alignment->apply_ta == 1){ - ul_time_alignment->ta_slot = (nr_slot_rx + ul_tx_timing_adjustment) % slots_per_frame; - if (nr_slot_rx + ul_tx_timing_adjustment > slots_per_frame){ - ul_time_alignment->ta_frame = (frame_rx + 1) % 1024; - } else { - ul_time_alignment->ta_frame = frame_rx; - } - // reset TA flag - ul_time_alignment->apply_ta = 0; - LOG_D(PHY,"Frame %d slot %d -- Starting UL time alignment procedures. TA update will be applied at frame %d slot %d\n", frame_rx, nr_slot_rx, ul_time_alignment->ta_frame, ul_time_alignment->ta_slot); + d_1_1 = 0; + else // mapping type B + switch (nb_symb_sch){ + case 7: d_1_1 = 0; break; + case 4: d_1_1 = 3; break; + case 2: d_1_1 = 3 + d; break; + default: break; } + + /* d_2_1 */ + int d_2_1; + mappingType_t mapping_type_ul = ue->pusch_config.pusch_TimeDomainResourceAllocation[0]->mappingType; + if (mapping_type_ul == typeB && start_symbol != 0) + d_2_1 = 0; + else + d_2_1 = 1; + + /* d_2_2 */ + const double d_2_2 = 0.0; // set to 0 because there is only 1 BWP: TODO this should corresponds to the switching time as defined in TS 38.133 + + /* N_t_1 time duration in msec of N_1 symbols corresponding to a PDSCH reception time + // N_t_2 time duration in msec of N_2 symbols corresponding to a PUSCH preparation time */ + double N_t_1 = (N_1 + d_1_1) * (ofdm_symbol_size + nb_prefix_samples) * tc_factor; + double N_t_2 = (N_2 + d_2_1) * (ofdm_symbol_size + nb_prefix_samples) * tc_factor; + if (N_t_2 < d_2_2) N_t_2 = d_2_2; + + /* Time alignment procedure */ + // N_t_1 + N_t_2 + N_TA_max must be in msec + const double t_subframe = 1.0; // subframe duration of 1 msec + const int ul_tx_timing_adjustment = 1 + (int)ceil(slots_per_subframe*(N_t_1 + N_t_2 + N_TA_max + 0.5)/t_subframe); + + if (ul_time_alignment->apply_ta == 1){ + ul_time_alignment->ta_slot = (nr_slot_rx + ul_tx_timing_adjustment) % slots_per_frame; + if (nr_slot_rx + ul_tx_timing_adjustment > slots_per_frame){ + ul_time_alignment->ta_frame = (frame_rx + 1) % 1024; + } else { + ul_time_alignment->ta_frame = frame_rx; + } + // reset TA flag + ul_time_alignment->apply_ta = 0; + LOG_D(PHY,"Frame %d slot %d -- Starting UL time alignment procedures. TA update will be applied at frame %d slot %d\n", + frame_rx, nr_slot_rx, ul_time_alignment->ta_frame, ul_time_alignment->ta_slot); } + } } } From 7d59106c5f1b6183840e3bbcf84441da8979f631 Mon Sep 17 00:00:00 2001 From: Mahesh Date: Tue, 11 May 2021 02:26:59 +0530 Subject: [PATCH 11/91] nfapi working with latest threading architecture --- ci-scripts/Jenkinsfile-GitLab-Container | 261 +++++ ci-scripts/Jenkinsfile-gitlab | 33 +- ci-scripts/Jenkinsfile-tmp-multi-enb-benetel | 293 ++++++ ci-scripts/Jenkinsfile-tmp-multi-enb-nsa | 297 ++++++ ci-scripts/Jenkinsfile-tmp-ran | 44 +- ci-scripts/Jenkinsfile-trig-nsa | 73 ++ ci-scripts/buildOnVM.sh | 19 +- ci-scripts/cls_containerize.py | 125 +-- ci-scripts/conf_files/benetel-4g.conf | 285 ++++++ ci-scripts/conf_files/benetel-5g.conf | 317 ++++++ .../gnb.band66.tm1.106PRB.usrpn300.conf | 292 ++++++ .../gnb.band78.tm1.106PRB.usrpn300.conf | 20 +- ci-scripts/createVM.sh | 6 + ci-scripts/docker_log_split.py | 92 ++ ci-scripts/oai-ci-vm-tool | 9 +- ci-scripts/ran.py | 3 +- ci-scripts/reportBuildLocally.sh | 100 +- ci-scripts/reportTestLocally.sh | 2 +- ci-scripts/runTestOnVM.sh | 90 +- ci-scripts/waitBuildOnVM.sh | 12 + ..._test.xml => benetel_multi_node_build.xml} | 59 +- ci-scripts/xml_files/benetel_nsa_base.xml | 162 +++ ...ge_build.xml => container_image_build.xml} | 4 +- ci-scripts/xml_files/fr1_multi_node_build.xml | 2 + ...{fr1_ran_ue_iperf.xml => fr1_nsa_base.xml} | 39 +- ...1_ran_ue_base.xml => fr1_nsa_base_ref.xml} | 47 +- cmake_targets/CMakeLists.txt | 8 +- cmake_targets/autotests/test_case_list.xml | 8 +- cmake_targets/build_oai | 40 +- cmake_targets/tools/build_helper | 28 +- common/utils/LOG/log.c | 11 +- common/utils/LOG/log.h | 10 +- common/utils/T/.gitignore | 1 + common/utils/T/T_messages.txt | 8 +- common/utils/T/tracer/Makefile | 10 +- common/utils/T/tracer/gnb.c | 172 ++++ common/utils/T/tracer/logger/iqlog.c | 78 ++ common/utils/T/tracer/logger/logger.h | 2 + common/utils/nr/nr_common.c | 75 ++ common/utils/nr/nr_common.h | 14 + doc/NFAPI_archi.md | 132 +++ doc/RUNMODEM.md | 17 +- docker/Dockerfile.eNB.rhel8.2 | 5 +- docker/Dockerfile.eNB.ubuntu18 | 5 +- docker/Dockerfile.gNB.rhel8.2 | 5 +- docker/Dockerfile.gNB.ubuntu18 | 5 +- docker/Dockerfile.lteUE.rhel8.2 | 6 +- docker/Dockerfile.lteUE.ubuntu18 | 5 +- docker/Dockerfile.nrUE.rhel8.2 | 5 +- docker/Dockerfile.nrUE.ubuntu18 | 5 +- executables/nr-gnb.c | 730 ++----------- executables/nr-ru.c | 964 +++++------------- executables/nr-softmodem.c | 90 -- executables/nr-ue.c | 62 +- executables/nr-uesoftmodem.c | 97 +- executables/softmodem-common.h | 7 + nfapi/oai_integration/nfapi_pnf.c | 33 - .../nfapi/public_inc/nfapi_nr_interface_scf.h | 7 +- nfapi/open-nFAPI/nfapi/src/nfapi_p7.c | 842 +++------------ nfapi/open-nFAPI/pnf/src/pnf_p7.c | 2 +- nfapi/open-nFAPI/pnf/src/pnf_p7_interface.c | 72 +- nfapi/open-nFAPI/vnf/inc/vnf_p7.h | 2 - nfapi/open-nFAPI/vnf/src/vnf_p7.c | 136 +-- nfapi/open-nFAPI/vnf/src/vnf_p7_interface.c | 48 +- openair1/PHY/INIT/nr_init.c | 59 +- openair1/PHY/INIT/nr_init_ue.c | 34 +- openair1/PHY/INIT/nr_parms.c | 119 +-- openair1/PHY/MODULATION/modulation_UE.h | 7 +- openair1/PHY/MODULATION/nr_modulation.c | 74 +- openair1/PHY/MODULATION/nr_modulation.h | 6 +- openair1/PHY/MODULATION/ofdm_mod.c | 22 +- openair1/PHY/MODULATION/slot_fep_nr.c | 619 +++++------ .../PHY/NR_ESTIMATION/nr_measurements_gNB.c | 12 +- .../NR_ESTIMATION/nr_ul_channel_estimation.c | 90 +- openair1/PHY/NR_REFSIG/nr_dmrs_rx.c | 4 +- openair1/PHY/NR_TRANSPORT/nr_dlsch.c | 9 +- openair1/PHY/NR_TRANSPORT/nr_prach.c | 477 +++++---- .../PHY/NR_TRANSPORT/nr_ulsch_demodulation.c | 1 + openair1/PHY/NR_TRANSPORT/pucch_rx.c | 9 +- openair1/PHY/NR_UE_TRANSPORT/dci_nr.c | 9 +- .../nr_dlsch_llr_computation.c | 52 +- .../PHY/NR_UE_TRANSPORT/nr_initial_sync.c | 3 +- openair1/PHY/NR_UE_TRANSPORT/nr_prach.c | 375 +++++-- .../PHY/NR_UE_TRANSPORT/nr_transport_ue.h | 2 + .../PHY/NR_UE_TRANSPORT/nr_ue_rf_helpers.c | 16 +- .../PHY/NR_UE_TRANSPORT/nr_ulsch_coding.c | 7 +- openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c | 20 +- openair1/PHY/TOOLS/nr_phy_scope.c | 24 - openair1/PHY/defs_RU.h | 6 + openair1/PHY/defs_gNB.h | 12 + openair1/PHY/defs_nr_common.h | 19 +- openair1/SCHED_NR/fapi_nr_l1.c | 3 +- openair1/SCHED_NR/nr_ru_procedures.c | 6 +- openair1/SCHED_NR/phy_procedures_nr_gNB.c | 27 +- openair1/SCHED_NR_UE/phy_procedures_nr_ue.c | 185 ++-- openair1/SIMULATION/NR_PHY/dlsim.c | 57 +- openair1/SIMULATION/NR_PHY/nr_unitary_defs.h | 14 +- openair1/SIMULATION/NR_PHY/pbchsim.c | 16 +- openair1/SIMULATION/NR_PHY/prachsim.c | 24 +- openair1/SIMULATION/NR_PHY/ulsim.c | 127 ++- openair2/COMMON/rrc_messages_types.h | 2 + openair2/COMMON/s1ap_messages_types.h | 5 + openair2/ENB_APP/enb_config.c | 59 ++ openair2/ENB_APP/enb_paramdef.h | 15 + openair2/GNB_APP/RRC_nr_paramsvalues.h | 38 + openair2/GNB_APP/gnb_config.c | 190 ++++ openair2/LAYER2/MAC/mac.h | 2 +- openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c | 284 +++--- openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h | 14 +- openair2/LAYER2/NR_MAC_UE/config_ue.c | 7 +- openair2/LAYER2/NR_MAC_UE/mac_defs.h | 2 + openair2/LAYER2/NR_MAC_UE/mac_proto.h | 4 +- openair2/LAYER2/NR_MAC_UE/mac_vars.c | 2 +- openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c | 66 +- openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c | 28 +- openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c | 117 ++- openair2/LAYER2/NR_MAC_gNB/config.c | 5 +- openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c | 12 +- openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c | 17 +- .../LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c | 15 +- .../LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c | 2 +- .../NR_MAC_gNB/gNB_scheduler_primitives.c | 5 +- .../LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c | 777 ++++++++++++-- .../LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c | 40 +- openair2/LAYER2/NR_MAC_gNB/mac_proto.h | 3 +- openair2/LAYER2/NR_MAC_gNB/main.c | 2 +- openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h | 113 +- openair2/LAYER2/nr_pdcp/nr_pdcp_entity.c | 262 ++++- openair2/LAYER2/nr_pdcp/nr_pdcp_entity.h | 57 +- .../LAYER2/nr_pdcp/nr_pdcp_entity_drb_am.c | 90 -- openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.c | 31 +- openair2/LAYER2/nr_pdcp/nr_pdcp_sdu.c | 78 ++ ...{nr_pdcp_entity_drb_am.h => nr_pdcp_sdu.h} | 30 +- .../LAYER2/nr_pdcp/nr_pdcp_timer_thread.c | 87 ++ .../LAYER2/nr_pdcp/nr_pdcp_timer_thread.h | 32 + openair2/LAYER2/nr_pdcp/nr_pdcp_ue_manager.c | 14 + openair2/LAYER2/nr_pdcp/nr_pdcp_ue_manager.h | 3 + openair2/NR_PHY_INTERFACE/NR_IF_Module.c | 68 +- openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c | 4 +- openair2/RRC/LTE/rrc_eNB_S1AP.c | 32 +- openair2/RRC/NR/nr_rrc_proto.h | 20 +- openair2/RRC/NR/nr_rrc_types.h | 6 +- openair2/RRC/NR/rrc_gNB.c | 4 +- openair2/RRC/NR/rrc_gNB_nsa.c | 14 +- openair2/RRC/NR/rrc_gNB_reconfig.c | 203 ++-- openair2/RRC/NR_UE/L2_interface_ue.c | 32 +- openair2/RRC/NR_UE/rrc_UE.c | 410 +++----- openair2/RRC/NR_UE/rrc_defs.h | 31 +- openair2/RRC/NR_UE/rrc_proto.h | 21 +- openair2/SIMULATION/NR_RRC/itti_sim.c | 2 +- openair2/X2AP/x2ap_eNB_generate_messages.c | 3 + openair2/X2AP/x2ap_eNB_handler.c | 35 +- openair3/GTPV1-U/gtpv1u_eNB.c | 2 +- openair3/NAS/COMMON/EMM/MSG/AttachAccept.c | 1 - openair3/NAS/COMMON/IES/SupportedCodecList.c | 4 + openair3/NAS/UE/EMM/SAP/emm_as.c | 4 +- openair3/NAS/UE/EMM/SecurityModeControl.c | 14 +- openair3/S1AP/s1ap_common.h | 7 +- openair3/S1AP/s1ap_eNB.c | 417 ++++++-- openair3/S1AP/s1ap_eNB.h | 17 + openair3/S1AP/s1ap_eNB_decoder.c | 2 - openair3/S1AP/s1ap_eNB_defs.h | 14 + openair3/S1AP/s1ap_eNB_handlers.c | 369 +++++-- .../S1AP/s1ap_eNB_management_procedures.c | 34 +- openair3/S1AP/s1ap_eNB_nas_procedures.c | 22 +- openair3/S1AP/s1ap_eNB_nnsf.c | 86 +- openair3/S1AP/s1ap_eNB_overload.c | 16 +- openair3/S1AP/s1ap_eNB_trace.c | 4 + openair3/SCTP/sctp_default_values.h | 4 +- openair3/SCTP/sctp_eNB_task.c | 12 +- targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp | 4 +- targets/ARCH/rfsimulator/stored_node.c | 5 +- .../CONF/gnb.band66.tm1.106PRB.usrpn300.conf | 18 +- .../CONF/gnb.band66.tm1.106PRB.usrpx300.conf | 18 +- .../gnb.band78.tm1.106PRB.PTRS.usrpx300.conf | 331 ++++++ .../CONF/gnb.band78.tm1.106PRB.usrpn300.conf | 8 +- .../CONF/gnb.band78.tm1.106PRB.usrpx300.conf | 27 +- .../CONF/gnb.band78.tm1.24PRB.usrpb210.conf | 292 ++++++ .../CONF/gnb.band78.tm1.24PRB.usrpn300.conf | 290 ++++++ .../CONF/gnb.band78.tm1.24PRB.usrpx300.conf | 290 ++++++ .../CONF/testing_gnb_24PRB.conf | 306 ++++++ .../gnb.sa.band78.fr1.106PRB.usrpb210.conf | 11 +- 182 files changed, 9786 insertions(+), 5217 deletions(-) create mode 100644 ci-scripts/Jenkinsfile-GitLab-Container create mode 100644 ci-scripts/Jenkinsfile-tmp-multi-enb-benetel create mode 100644 ci-scripts/Jenkinsfile-tmp-multi-enb-nsa create mode 100644 ci-scripts/Jenkinsfile-trig-nsa create mode 100644 ci-scripts/conf_files/benetel-4g.conf create mode 100644 ci-scripts/conf_files/benetel-5g.conf create mode 100644 ci-scripts/conf_files/gnb.band66.tm1.106PRB.usrpn300.conf create mode 100644 ci-scripts/docker_log_split.py rename ci-scripts/xml_files/{fr1_multi_node_test.xml => benetel_multi_node_build.xml} (50%) create mode 100644 ci-scripts/xml_files/benetel_nsa_base.xml rename ci-scripts/xml_files/{fr1_image_build.xml => container_image_build.xml} (93%) rename ci-scripts/xml_files/{fr1_ran_ue_iperf.xml => fr1_nsa_base.xml} (80%) rename ci-scripts/xml_files/{fr1_ran_ue_base.xml => fr1_nsa_base_ref.xml} (80%) create mode 100644 common/utils/T/tracer/gnb.c create mode 100644 doc/NFAPI_archi.md delete mode 100644 openair2/LAYER2/nr_pdcp/nr_pdcp_entity_drb_am.c create mode 100644 openair2/LAYER2/nr_pdcp/nr_pdcp_sdu.c rename openair2/LAYER2/nr_pdcp/{nr_pdcp_entity_drb_am.h => nr_pdcp_sdu.h} (58%) create mode 100644 openair2/LAYER2/nr_pdcp/nr_pdcp_timer_thread.c create mode 100644 openair2/LAYER2/nr_pdcp/nr_pdcp_timer_thread.h create mode 100644 targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.106PRB.PTRS.usrpx300.conf create mode 100644 targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.24PRB.usrpb210.conf create mode 100644 targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.24PRB.usrpn300.conf create mode 100644 targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.24PRB.usrpx300.conf create mode 100644 targets/PROJECTS/GENERIC-LTE-EPC/CONF/testing_gnb_24PRB.conf diff --git a/ci-scripts/Jenkinsfile-GitLab-Container b/ci-scripts/Jenkinsfile-GitLab-Container new file mode 100644 index 0000000000..fbf9ba8f4b --- /dev/null +++ b/ci-scripts/Jenkinsfile-GitLab-Container @@ -0,0 +1,261 @@ +#!/bin/groovy +/* + * 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 + */ + +// Location of the executor node +def nodeExecutor = params.nodeExecutor + +// Tags to shorten pipeline duration +def doMandatoryTests = false +def doFullTestsuite = false + +pipeline { + agent { + label nodeExecutor + } + options { + disableConcurrentBuilds() + timestamps() + gitLabConnection('OAI GitLab') + ansiColor('xterm') + } + + stages { + stage ("Verify Parameters") { + steps { + script { + JOB_TIMESTAMP = sh returnStdout: true, script: 'date --utc --rfc-3339=seconds | sed -e "s#+00:00##"' + JOB_TIMESTAMP = JOB_TIMESTAMP.trim() + + echo '\u2705 \u001B[32mVerify Parameters\u001B[0m' + def allParametersPresent = true + + echo '\u2705 \u001B[32mVerify Labels\u001B[0m' + if ("MERGE".equals(env.gitlabActionType)) { + LABEL_CHECK = sh returnStdout: true, script: 'ci-scripts/checkGitLabMergeRequestLabels.sh --mr-id ' + env.gitlabMergeRequestIid + LABEL_CHECK = LABEL_CHECK.trim() + if (LABEL_CHECK == 'NONE') { + def message = "OAI " + JOB_NAME + " build (" + BUILD_ID + "): Your merge request has none of the mandatory labels:\n\n" + message += " - BUILD-ONLY\n" + message += " - 4G-LTE\n" + message += " - 5G-NR\n" + message += " - CI\n\n" + message += "Not performing CI due to lack of labels" + addGitLabMRComment comment: message + error('Not performing CI due to lack of labels') + } else if (LABEL_CHECK == 'FULL') { + doMandatoryTests = true + doFullTestsuite = true + } else if (LABEL_CHECK == 'SHORTEN-5G') { + doMandatoryTests = true + } else { + def message = "OAI " + JOB_NAME + " build (" + BUILD_ID + "): We will perform only build stages on your Merge Request" + addGitLabMRComment comment: message + } + } else { + doMandatoryTests = true + doFullTestsuite = true + } + } + } + } + stage ("Verify Guidelines") { + steps { + echo "Git URL is ${GIT_URL}" + echo "GitLab Act is ${env.gitlabActionType}" + script { + if ("MERGE".equals(env.gitlabActionType)) { + // since a bit, in push events, gitlabUserEmail is not populated + gitCommitAuthorEmailAddr = env.gitlabUserEmail + echo "GitLab Usermail is ${gitCommitAuthorEmailAddr}" + // GitLab-Jenkins plugin integration is lacking to perform the merge by itself + // Doing it manually --> it may have merge conflicts + sh "./ci-scripts/doGitLabMerge.sh --src-branch ${env.gitlabSourceBranch} --src-commit ${env.gitlabMergeRequestLastCommit} --target-branch ${env.gitlabTargetBranch} --target-commit ${GIT_COMMIT}" + } else { + echo "Git Branch is ${GIT_BRANCH}" + echo "Git Commit is ${GIT_COMMIT}" + // since a bit, in push events, gitlabUserEmail is not populated + gitCommitAuthorEmailAddr = sh returnStdout: true, script: 'git log -n1 --pretty=format:%ae ${GIT_COMMIT}' + gitCommitAuthorEmailAddr = gitCommitAuthorEmailAddr.trim() + echo "GitLab Usermail is ${gitCommitAuthorEmailAddr}" + sh "git log -n1 --pretty=format:\"%s\" > .git/CI_COMMIT_MSG" + } + } + } + post { + failure { + script { + def message = "OAI " + JOB_NAME + " build (" + BUILD_ID + "): Merge Conflicts -- Cannot perform CI" + addGitLabMRComment comment: message + currentBuild.result = 'FAILURE' + } + } + } + } + // Build Stages are Mandatory + // Later we will add a Ubuntu20 build + stage ("Image Building Processes") { + parallel { + stage ("Ubuntu18 Build") { + steps { + script { + triggerSlaveJob ('RAN-Ubuntu18-Image-Builder', 'Ubuntu18-Images-Build') + } + } + post { + always { + script { + finalizeSlaveJob('RAN-Ubuntu18-Image-Builder') + } + } + failure { + script { + currentBuild.result = 'FAILURE' + } + } + } + } + stage ("RHEL8 Build") { + steps { + script { + triggerSlaveJob ('RAN-RHEL8-Image-Builder', 'RHEL8-Images-Build') + } + } + post { + always { + script { + finalizeSlaveJob('RAN-RHEL8-Image-Builder') + } + } + failure { + script { + currentBuild.result = 'FAILURE' + } + } + } + } + } + } + } + post { + always { + script { + emailext attachmentsPattern: '*results*.html', + body: '''Hi, + +Here are attached HTML report files for $PROJECT_NAME - Build # $BUILD_NUMBER - $BUILD_STATUS! + +Regards, +OAI CI Team''', + replyTo: 'no-reply@openairinterface.org', + subject: '$PROJECT_NAME - Build # $BUILD_NUMBER - $BUILD_STATUS!', + to: gitCommitAuthorEmailAddr + + if (fileExists('.git/CI_COMMIT_MSG')) { + sh "rm -f .git/CI_COMMIT_MSG" + } + } + } + success { + script { + def message = "OAI " + JOB_NAME + " build (" + BUILD_ID + "): passed (" + BUILD_URL + ")" + if ("MERGE".equals(env.gitlabActionType)) { + echo "This is a MERGE event" + addGitLabMRComment comment: message + } + } + } + failure { + script { + def message = "OAI " + JOB_NAME + " build (" + BUILD_ID + "): failed (" + BUILD_URL + ")" + if ("MERGE".equals(env.gitlabActionType)) { + echo "This is a MERGE event" + addGitLabMRComment comment: message + } + } + } + } +} + +// ---- Slave Job functions + +def triggerSlaveJob (jobName, gitlabStatusName) { + // Workaround for the "cancelled" GitLab pipeline notification + // The slave job is triggered with the propagate false so the following commands are executed + // Its status is now PASS/SUCCESS from a stage pipeline point of view + // localStatus variable MUST be analyzed to properly assess the status + localStatus = build job: jobName, + parameters: [ + string(name: 'eNB_Repository', value: String.valueOf(GIT_URL)), + string(name: 'eNB_Branch', value: String.valueOf(env.gitlabSourceBranch)), + string(name: 'eNB_CommitID', value: String.valueOf(env.gitlabMergeRequestLastCommit)), + booleanParam(name: 'eNB_mergeRequest', value: "MERGE".equals(env.gitlabActionType)), + string(name: 'eNB_TargetBranch', value: String.valueOf(env.gitlabTargetBranch)) + ], propagate: false + localResult = localStatus.getResult() + echo "${jobName} Slave Job status is ${localResult}" + gitlabCommitStatus(name: gitlabStatusName) { + if (localStatus.resultIsBetterOrEqualTo('SUCCESS')) { + echo "${jobName} Slave Job is OK" + } else { + echo "${jobName} Slave Job is KO" + sh "ci-scripts/fail.sh" + } + } +} + +def triggerSlaveJobNoGitLab (jobName) { + // Workaround for the "cancelled" GitLab pipeline notification + // The slave job is triggered with the propagate false so the following commands are executed + // Its status is now PASS/SUCCESS from a stage pipeline point of view + // localStatus variable MUST be analyzed to properly assess the status + localStatus = build job: jobName, + parameters: [ + string(name: 'eNB_Repository', value: String.valueOf(GIT_URL)), + string(name: 'eNB_Branch', value: String.valueOf(env.gitlabSourceBranch)), + string(name: 'eNB_CommitID', value: String.valueOf(env.gitlabMergeRequestLastCommit)), + booleanParam(name: 'eNB_mergeRequest', value: "MERGE".equals(env.gitlabActionType)), + string(name: 'eNB_TargetBranch', value: String.valueOf(env.gitlabTargetBranch)) + ], propagate: false + localResult = localStatus.getResult() + echo "${jobName} Slave Job status is ${localResult}" + if (localStatus.resultIsBetterOrEqualTo('SUCCESS')) { + echo "${jobName} Slave Job is OK" + } else { + echo "${jobName} Slave Job is KO" + sh "ci-scripts/fail.sh" + } +} + +def finalizeSlaveJob(jobName) { + // In case of any non-success, we are retrieving the HTML report of the last completed + // slave job. The only drop-back is that we may retrieve the HTML report of a previous build + fileName = "test_results-${jobName}.html" + if (!fileExists(fileName)) { + copyArtifacts(projectName: jobName, + filter: 'test_results*.html', + selector: lastCompleted()) + if (fileExists(fileName)) { + sh "sed -i -e 's#TEMPLATE_BUILD_TIME#${JOB_TIMESTAMP}#' ${fileName}" + archiveArtifacts artifacts: fileName + } + } +} diff --git a/ci-scripts/Jenkinsfile-gitlab b/ci-scripts/Jenkinsfile-gitlab index ff661543c0..de49275b7e 100644 --- a/ci-scripts/Jenkinsfile-gitlab +++ b/ci-scripts/Jenkinsfile-gitlab @@ -196,16 +196,6 @@ pipeline { } } - stage ("Start VM -- enb-usrp") { - steps { - lock (vmResource) { - timeout (time: 5, unit: 'MINUTES') { - sh "./ci-scripts/oai-ci-vm-tool build --workspace $WORKSPACE --variant enb-usrp --job-name ${JOB_NAME} --build-id ${BUILD_ID} --daemon" - } - } - } - } - stage ("Start VM -- phy-sim") { steps { lock (vmResource) { @@ -251,7 +241,7 @@ pipeline { stage ("Analysis with cppcheck") { steps { gitlabCommitStatus(name: "Analysis with cppcheck") { - timeout (time: 20, unit: 'MINUTES') { + timeout (time: 30, unit: 'MINUTES') { sh "./ci-scripts/oai-ci-vm-tool wait --workspace $WORKSPACE --variant cppcheck --job-name ${JOB_NAME} --build-id ${BUILD_ID}" } } @@ -260,7 +250,7 @@ pipeline { stage ("Build basic simulator") { steps { gitlabCommitStatus(name: "Build basic-sim") { - timeout (time: 20, unit: 'MINUTES') { + timeout (time: 30, unit: 'MINUTES') { sh "./ci-scripts/oai-ci-vm-tool wait --workspace $WORKSPACE --variant basic-sim --job-name ${JOB_NAME} --build-id ${BUILD_ID} --keep-vm-alive" } } @@ -269,7 +259,7 @@ pipeline { stage ("Build 5G gNB-USRP") { steps { gitlabCommitStatus(name: "Build gNB-USRP") { - timeout (time: 20, unit: 'MINUTES') { + timeout (time: 30, unit: 'MINUTES') { sh "./ci-scripts/oai-ci-vm-tool wait --workspace $WORKSPACE --variant gnb-usrp --job-name ${JOB_NAME} --build-id ${BUILD_ID} --keep-vm-alive" } } @@ -278,25 +268,16 @@ pipeline { stage ("Build 5G NR-UE-USRP") { steps { gitlabCommitStatus(name: "Build nr-UE-USRP") { - timeout (time: 20, unit: 'MINUTES') { + timeout (time: 30, unit: 'MINUTES') { sh "./ci-scripts/oai-ci-vm-tool wait --workspace $WORKSPACE --variant nr-ue-usrp --job-name ${JOB_NAME} --build-id ${BUILD_ID} --keep-vm-alive" } } } } - stage ("Build eNB-USRP") { - steps { - gitlabCommitStatus(name: "Build eNB-USRP") { - timeout (time: 20, unit: 'MINUTES') { - sh "./ci-scripts/oai-ci-vm-tool wait --workspace $WORKSPACE --variant enb-usrp --job-name ${JOB_NAME} --build-id ${BUILD_ID}" - } - } - } - } stage ("Build physical simulators") { steps { gitlabCommitStatus(name: "Build phy-sim") { - timeout (time: 20, unit: 'MINUTES') { + timeout (time: 30, unit: 'MINUTES') { sh "./ci-scripts/oai-ci-vm-tool wait --workspace $WORKSPACE --variant phy-sim --job-name ${JOB_NAME} --build-id ${BUILD_ID} --keep-vm-alive" } } @@ -305,7 +286,7 @@ pipeline { stage ("Build eNB-ethernet") { steps { gitlabCommitStatus(name: "Build eNB-ethernet") { - timeout (time: 20, unit: 'MINUTES') { + timeout (time: 30, unit: 'MINUTES') { sh "./ci-scripts/oai-ci-vm-tool wait --workspace $WORKSPACE --variant enb-ethernet --job-name ${JOB_NAME} --build-id ${BUILD_ID} --keep-vm-alive" } } @@ -316,7 +297,7 @@ pipeline { // This is typically the last one to finish. lock (vmResource) { gitlabCommitStatus(name: "Build UE-ethernet") { - timeout (time: 20, unit: 'MINUTES') { + timeout (time: 30, unit: 'MINUTES') { sh "./ci-scripts/oai-ci-vm-tool wait --workspace $WORKSPACE --variant ue-ethernet --job-name ${JOB_NAME} --build-id ${BUILD_ID} --keep-vm-alive" } } diff --git a/ci-scripts/Jenkinsfile-tmp-multi-enb-benetel b/ci-scripts/Jenkinsfile-tmp-multi-enb-benetel new file mode 100644 index 0000000000..8ac2e6adff --- /dev/null +++ b/ci-scripts/Jenkinsfile-tmp-multi-enb-benetel @@ -0,0 +1,293 @@ +#!/bin/groovy +/* + * 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 + */ + +// Template Jenkins Declarative Pipeline script to run Test w/ RF HW + +// Location of the python executor node shall be in the same subnet as the others servers +def pythonExecutor = params.pythonExecutor + +// Location of the test XML file to be run +def testXMLFile = params.pythonTestXmlFile +def mainPythonAllXmlFiles = "" +def buildStageStatus = true + +// Name of the test stage +def testStageName = params.pipelineTestStageName + +// Name of the phone resource +def ciSmartPhonesResource1 = params.SmartPhonesResource1 +def ciSmartPhonesResource2 = params.SmartPhonesResource2 + +// Global Parameters. Normally they should be populated when the master job +// triggers the slave job with parameters +def eNB_Repository +def eNB_Branch +def eNB_CommitID +def eNB_AllowMergeRequestProcess +def eNB_TargetBranch + +pipeline { + agent { + label pythonExecutor + } + options { + disableConcurrentBuilds() + ansiColor('xterm') + lock(extra: [[resource: ciSmartPhonesResource2]], resource: ciSmartPhonesResource1) + } + stages { + stage("Build Init") { + steps { + // update the build name and description + buildName "${params.eNB_MR}" + buildDescription "Branch : ${params.eNB_Branch}" + } + } + stage ("Verify Parameters") { + steps { + script { + echo '\u2705 \u001B[32mVerify Parameters\u001B[0m' + def allParametersPresent = true + + // It is already to late to check it + if (params.pythonExecutor != null) { + echo "eNB CI executor node : ${pythonExecutor}" + } + // If not present picking a default Stage Name + if (params.pipelineTestStageName == null) { + // picking default + testStageName = 'Template Test Stage' + } + + if (params.SmartPhonesResource1 == null) { + allParametersPresent = false + } + if (params.SmartPhonesResource2 == null) { + 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) { + eNB_Repository = env.GIT_URL + } else { + eNB_Repository = params.eNB_Repository + } + echo "eNB_Repository : ${eNB_Repository}" + if (params.eNB_Branch == null) { + eNB_Branch = env.GIT_BRANCH + } else { + eNB_Branch = params.eNB_Branch + } + echo "eNB_Branch : ${eNB_Branch}" + if (params.eNB_CommitID == null) { + eNB_CommitID = env.GIT_COMMIT + } else { + eNB_CommitID = params.eNB_CommitID + } + echo "eNB_CommitID : ${eNB_CommitID}" + if (params.eNB_AllowMergeRequestProcess!= null) { + eNB_AllowMergeRequestProcess = params.eNB_AllowMergeRequestProcess + if (eNB_AllowMergeRequestProcess) { + if (params.eNB_TargetBranch != null) { + eNB_TargetBranch = params.eNB_TargetBranch + } else { + eNB_TargetBranch = 'develop' + } + echo "eNB_TargetBranch : ${eNB_TargetBranch}" + } + } + + if (params.EPC_IPAddress == null) { + allParametersPresent = false + } + if (params.EPC_Type == null) { + allParametersPresent = false + } + if (params.EPC_SourceCodePath == null) { + allParametersPresent = false + } + if (params.EPC_Credentials == null) { + allParametersPresent = false + } + + if (params.ADB_IPAddress == null) { + allParametersPresent = false + } + if (params.ADB_Credentials == null) { + allParametersPresent = false + } + + if (allParametersPresent) { + echo "All parameters are present" + if (eNB_AllowMergeRequestProcess) { + sh "git fetch" + sh "./ci-scripts/doGitLabMerge.sh --src-branch ${eNB_Branch} --src-commit ${eNB_CommitID} --target-branch ${eNB_TargetBranch} --target-commit latest" + } else { + sh "git fetch" + sh "git checkout -f ${eNB_CommitID}" + } + } else { + echo "Some parameters are missing" + sh "./ci-scripts/fail.sh" + } + } + } + } + stage ("Build and Test") { + steps { + script { + dir ('ci-scripts') { + echo "\u2705 \u001B[32m${testStageName}\u001B[0m" + // If not present picking a default XML file + if (params.pythonTestXmlFile == null) { + // picking default + testXMLFile = 'xml_files/enb_usrpB210_band7_50PRB.xml' + echo "Test XML file(default): ${testXMLFile}" + mainPythonAllXmlFiles += "--XMLTestFile=" + testXMLFile + " " + } else { + String[] myXmlTestSuite = testXMLFile.split("\\r?\\n") + for (xmlFile in myXmlTestSuite) { + if (fileExists(xmlFile)) { + mainPythonAllXmlFiles += "--XMLTestFile=" + xmlFile + " " + echo "Test XML file : ${xmlFile}" + } + } + } + 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'], + [$class: 'UsernamePasswordMultiBinding', credentialsId: "${params.EPC_Credentials}", usernameVariable: 'EPC_Username', passwordVariable: 'EPC_Password'], + [$class: 'UsernamePasswordMultiBinding', credentialsId: "${params.ADB_Credentials}", usernameVariable: 'ADB_Username', passwordVariable: 'ADB_Password'] + ]) { + sh "python3 main.py --mode=InitiateHtml --ranRepository=${eNB_Repository} --ranBranch=${eNB_Branch} --ranCommitID=${eNB_CommitID} --ranAllowMerge=${eNB_AllowMergeRequestProcess} --ranTargetBranch=${eNB_TargetBranch} --ADBIPAddress=${params.ADB_IPAddress} --ADBUserName=${ADB_Username} --ADBPassword=${ADB_Password} ${mainPythonAllXmlFiles}" + String[] myXmlTestSuite = testXMLFile.split("\\r?\\n") + for (xmlFile in myXmlTestSuite) { + if (fileExists(xmlFile)) { + try { + 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} --EPCIPAddress=${params.EPC_IPAddress} --EPCType=${params.EPC_Type} --EPCUserName=${EPC_Username} --EPCPassword=${EPC_Password} --EPCSourceCodePath=${params.EPC_SourceCodePath} --ADBIPAddress=${params.ADB_IPAddress} --ADBUserName=${ADB_Username} --ADBPassword=${ADB_Password} --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}" + } + } + } + } + } + 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([ + [$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}" + + 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" + } + if(fileExists("ci-scripts/test_results.html")) { + sh "mv ci-scripts/test_results.html test_results-${JOB_NAME}.html" + sh "sed -i -e 's#TEMPLATE_JOB_NAME#${JOB_NAME}#' -e 's@build #TEMPLATE_BUILD_ID@build #${BUILD_ID}@' -e 's#Build-ID: TEMPLATE_BUILD_ID#Build-ID: ${BUILD_ID}#' -e 's#TEMPLATE_STAGE_NAME#${testStageName}#' test_results-${JOB_NAME}.html" + archiveArtifacts "test_results-${JOB_NAME}.html" + } + } + } + } + } + } + } + + post { + always { + script { + if (params.pipelineZipsConsoleLog != null) { + if (params.pipelineZipsConsoleLog) { + echo "Archiving Jenkins console log" + sh "wget --no-check-certificate --no-proxy ${env.JENKINS_URL}/job/${env.JOB_NAME}/${env.BUILD_ID}/consoleText -O consoleText.log || true" + sh "zip -m consoleText.log.${env.BUILD_ID}.zip consoleText.log || true" + if(fileExists("consoleText.log.${env.BUILD_ID}.zip")) { + archiveArtifacts "consoleText.log.${env.BUILD_ID}.zip" + } + } + } + } + } + } +} diff --git a/ci-scripts/Jenkinsfile-tmp-multi-enb-nsa b/ci-scripts/Jenkinsfile-tmp-multi-enb-nsa new file mode 100644 index 0000000000..66d12eed33 --- /dev/null +++ b/ci-scripts/Jenkinsfile-tmp-multi-enb-nsa @@ -0,0 +1,297 @@ +#!/bin/groovy +/* + * 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 + */ + +// Template Jenkins Declarative Pipeline script to run Test w/ RF HW + +// Location of the python executor node shall be in the same subnet as the others servers +def pythonExecutor = params.pythonExecutor + +// Location of the test XML file to be run +def testXMLFile = params.pythonTestXmlFile +def mainPythonAllXmlFiles = "" +def buildStageStatus = true + +// Name of the test stage +def testStageName = params.pipelineTestStageName + +// Name of the phone resource +def ciSmartPhonesResource1 = params.SmartPhonesResource1 +def ciSmartPhonesResource2 = params.SmartPhonesResource2 +def ciSmartPhonesResource3 = params.SmartPhonesResource3 + +// Global Parameters. Normally they should be populated when the master job +// triggers the slave job with parameters +def eNB_Repository +def eNB_Branch +def eNB_CommitID +def eNB_AllowMergeRequestProcess +def eNB_TargetBranch + +pipeline { + agent { + label pythonExecutor + } + options { + disableConcurrentBuilds() + ansiColor('xterm') + lock(extra: [[resource: ciSmartPhonesResource2],[resource: ciSmartPhonesResource3]], resource: ciSmartPhonesResource1) + } + stages { + stage("Build Init") { + steps { + // update the build name and description + buildName "${params.eNB_MR}" + buildDescription "Branch : ${params.eNB_Branch}" + } + } + stage ("Verify Parameters") { + steps { + script { + echo '\u2705 \u001B[32mVerify Parameters\u001B[0m' + def allParametersPresent = true + + // It is already to late to check it + if (params.pythonExecutor != null) { + echo "eNB CI executor node : ${pythonExecutor}" + } + // If not present picking a default Stage Name + if (params.pipelineTestStageName == null) { + // picking default + testStageName = 'Template Test Stage' + } + + if (params.SmartPhonesResource1 == null) { + allParametersPresent = false + } + if (params.SmartPhonesResource2 == null) { + allParametersPresent = false + } + if (params.SmartPhonesResource3== null) { + 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) { + eNB_Repository = env.GIT_URL + } else { + eNB_Repository = params.eNB_Repository + } + echo "eNB_Repository : ${eNB_Repository}" + if (params.eNB_Branch == null) { + eNB_Branch = env.GIT_BRANCH + } else { + eNB_Branch = params.eNB_Branch + } + echo "eNB_Branch : ${eNB_Branch}" + if (params.eNB_CommitID == null) { + eNB_CommitID = env.GIT_COMMIT + } else { + eNB_CommitID = params.eNB_CommitID + } + echo "eNB_CommitID : ${eNB_CommitID}" + if (params.eNB_AllowMergeRequestProcess!= null) { + eNB_AllowMergeRequestProcess = params.eNB_AllowMergeRequestProcess + if (eNB_AllowMergeRequestProcess) { + if (params.eNB_TargetBranch != null) { + eNB_TargetBranch = params.eNB_TargetBranch + } else { + eNB_TargetBranch = 'develop' + } + echo "eNB_TargetBranch : ${eNB_TargetBranch}" + } + } + + if (params.EPC_IPAddress == null) { + allParametersPresent = false + } + if (params.EPC_Type == null) { + allParametersPresent = false + } + if (params.EPC_SourceCodePath == null) { + allParametersPresent = false + } + if (params.EPC_Credentials == null) { + allParametersPresent = false + } + + if (params.ADB_IPAddress == null) { + allParametersPresent = false + } + if (params.ADB_Credentials == null) { + allParametersPresent = false + } + + if (allParametersPresent) { + echo "All parameters are present" + if (eNB_AllowMergeRequestProcess) { + sh "git fetch" + sh "./ci-scripts/doGitLabMerge.sh --src-branch ${eNB_Branch} --src-commit ${eNB_CommitID} --target-branch ${eNB_TargetBranch} --target-commit latest" + } else { + sh "git fetch" + sh "git checkout -f ${eNB_CommitID}" + } + } else { + echo "Some parameters are missing" + sh "./ci-scripts/fail.sh" + } + } + } + } + stage ("Build and Test") { + steps { + script { + dir ('ci-scripts') { + echo "\u2705 \u001B[32m${testStageName}\u001B[0m" + // If not present picking a default XML file + if (params.pythonTestXmlFile == null) { + // picking default + testXMLFile = 'xml_files/enb_usrpB210_band7_50PRB.xml' + echo "Test XML file(default): ${testXMLFile}" + mainPythonAllXmlFiles += "--XMLTestFile=" + testXMLFile + " " + } else { + String[] myXmlTestSuite = testXMLFile.split("\\r?\\n") + for (xmlFile in myXmlTestSuite) { + if (fileExists(xmlFile)) { + mainPythonAllXmlFiles += "--XMLTestFile=" + xmlFile + " " + echo "Test XML file : ${xmlFile}" + } + } + } + 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'], + [$class: 'UsernamePasswordMultiBinding', credentialsId: "${params.EPC_Credentials}", usernameVariable: 'EPC_Username', passwordVariable: 'EPC_Password'], + [$class: 'UsernamePasswordMultiBinding', credentialsId: "${params.ADB_Credentials}", usernameVariable: 'ADB_Username', passwordVariable: 'ADB_Password'] + ]) { + sh "python3 main.py --mode=InitiateHtml --ranRepository=${eNB_Repository} --ranBranch=${eNB_Branch} --ranCommitID=${eNB_CommitID} --ranAllowMerge=${eNB_AllowMergeRequestProcess} --ranTargetBranch=${eNB_TargetBranch} --ADBIPAddress=${params.ADB_IPAddress} --ADBUserName=${ADB_Username} --ADBPassword=${ADB_Password} ${mainPythonAllXmlFiles}" + String[] myXmlTestSuite = testXMLFile.split("\\r?\\n") + for (xmlFile in myXmlTestSuite) { + if (fileExists(xmlFile)) { + try { + 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} --EPCIPAddress=${params.EPC_IPAddress} --EPCType=${params.EPC_Type} --EPCUserName=${EPC_Username} --EPCPassword=${EPC_Password} --EPCSourceCodePath=${params.EPC_SourceCodePath} --ADBIPAddress=${params.ADB_IPAddress} --ADBUserName=${ADB_Username} --ADBPassword=${ADB_Password} --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}" + } + } + } + } + } + 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([ + [$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}" + + 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" + } + if(fileExists("ci-scripts/test_results.html")) { + sh "mv ci-scripts/test_results.html test_results-${JOB_NAME}.html" + sh "sed -i -e 's#TEMPLATE_JOB_NAME#${JOB_NAME}#' -e 's@build #TEMPLATE_BUILD_ID@build #${BUILD_ID}@' -e 's#Build-ID: TEMPLATE_BUILD_ID#Build-ID: ${BUILD_ID}#' -e 's#TEMPLATE_STAGE_NAME#${testStageName}#' test_results-${JOB_NAME}.html" + archiveArtifacts "test_results-${JOB_NAME}.html" + } + } + } + } + } + } + } + + post { + always { + script { + if (params.pipelineZipsConsoleLog != null) { + if (params.pipelineZipsConsoleLog) { + echo "Archiving Jenkins console log" + sh "wget --no-check-certificate --no-proxy ${env.JENKINS_URL}/job/${env.JOB_NAME}/${env.BUILD_ID}/consoleText -O consoleText.log || true" + sh "zip -m consoleText.log.${env.BUILD_ID}.zip consoleText.log || true" + if(fileExists("consoleText.log.${env.BUILD_ID}.zip")) { + archiveArtifacts "consoleText.log.${env.BUILD_ID}.zip" + } + } + } + } + } + } +} diff --git a/ci-scripts/Jenkinsfile-tmp-ran b/ci-scripts/Jenkinsfile-tmp-ran index ab1573de7f..7d5307620f 100644 --- a/ci-scripts/Jenkinsfile-tmp-ran +++ b/ci-scripts/Jenkinsfile-tmp-ran @@ -241,6 +241,10 @@ pipeline { stage ("Terminate") { parallel { stage('Terminate UE') { + // Bypassing this stage if there are no abd server defined + when { + expression { params.ADB_IPAddress != "none" } + } steps { echo '\u2705 \u001B[32mTerminate UE\u001B[0m' withCredentials([ @@ -275,6 +279,10 @@ pipeline { } } stage('Terminate SPGW') { + // Bypassing this stage if EPC server is not defined + when { + expression { params.EPC_IPAddress != "none" } + } steps { echo '\u2705 \u001B[32mTerminate SPGW\u001B[0m' withCredentials([ @@ -292,6 +300,10 @@ pipeline { } } stage('Terminate MME') { + // Bypassing this stage if EPC server is not defined + when { + expression { params.EPC_IPAddress != "none" } + } steps { echo '\u2705 \u001B[32mTerminate MME\u001B[0m' withCredentials([ @@ -309,6 +321,10 @@ pipeline { } } stage('Terminate HSS') { + // Bypassing this stage if EPC server is not defined + when { + expression { params.EPC_IPAddress != "none" } + } steps { echo '\u2705 \u001B[32mTerminate HSS\u001B[0m' withCredentials([ @@ -371,6 +387,10 @@ pipeline { } } stage('Log Collection (SPGW)') { + // Bypassing this stage if EPC server is not defined + when { + expression { params.EPC_IPAddress != "none" } + } steps { withCredentials([ [$class: 'UsernamePasswordMultiBinding', credentialsId: "${params.EPC_Credentials}", usernameVariable: 'EPC_Username', passwordVariable: 'EPC_Password'] @@ -389,6 +409,10 @@ pipeline { } } stage('Log Collection (MME)') { + // Bypassing this stage if EPC server is not defined + when { + expression { params.EPC_IPAddress != "none" } + } steps { withCredentials([ [$class: 'UsernamePasswordMultiBinding', credentialsId: "${params.EPC_Credentials}", usernameVariable: 'EPC_Username', passwordVariable: 'EPC_Password'] @@ -407,6 +431,10 @@ pipeline { } } stage('Log Collection (HSS)') { + // Bypassing this stage if EPC server is not defined + when { + expression { params.EPC_IPAddress != "none" } + } steps { withCredentials([ [$class: 'UsernamePasswordMultiBinding', credentialsId: "${params.EPC_Credentials}", usernameVariable: 'EPC_Username', passwordVariable: 'EPC_Password'] @@ -425,6 +453,10 @@ pipeline { } } stage('Log Collection (Ping)') { + // Bypassing this stage if EPC server is not defined + when { + expression { params.EPC_IPAddress != "none" } + } steps { withCredentials([ [$class: 'UsernamePasswordMultiBinding', credentialsId: "${params.EPC_Credentials}", usernameVariable: 'EPC_Username', passwordVariable: 'EPC_Password'] @@ -443,6 +475,10 @@ pipeline { } } stage('Log Collection (Iperf)') { + // Bypassing this stage if EPC server is not defined + when { + expression { params.EPC_IPAddress != "none" } + } steps { withCredentials([ [$class: 'UsernamePasswordMultiBinding', credentialsId: "${params.EPC_Credentials}", usernameVariable: 'EPC_Username', passwordVariable: 'EPC_Password'] @@ -482,7 +518,7 @@ pipeline { // Making sure that we really shutdown every thing before leaving failure { script { - if (!termStatusArray[termUE]) { + if ((!termStatusArray[termUE]) && (params.ADB_IPAddress != "none")) { withCredentials([ [$class: 'UsernamePasswordMultiBinding', credentialsId: "${params.ADB_Credentials}", usernameVariable: 'ADB_Username', passwordVariable: 'ADB_Password'] ]) { @@ -496,21 +532,21 @@ pipeline { sh "python3 ci-scripts/main.py --mode=TerminateeNB --eNBIPAddress=${params.eNB_IPAddress} --eNBUserName=${eNB_Username} --eNBPassword=${eNB_Password}" } } - if (!termStatusArray[termSPGW]) { + if ((!termStatusArray[termSPGW]) && (params.EPC_IPAddress != "none")) { withCredentials([ [$class: 'UsernamePasswordMultiBinding', credentialsId: "${params.EPC_Credentials}", usernameVariable: 'EPC_Username', passwordVariable: 'EPC_Password'] ]) { sh "python3 ci-scripts/main.py --mode=TerminateSPGW --EPCIPAddress=${params.EPC_IPAddress} --EPCUserName=${EPC_Username} --EPCPassword=${EPC_Password} --EPCType=${params.EPC_Type} --EPCSourceCodePath=${params.EPC_SourceCodePath}" } } - if (!termStatusArray[termMME]) { + if ((!termStatusArray[termMME]) && (params.EPC_IPAddress != "none")) { withCredentials([ [$class: 'UsernamePasswordMultiBinding', credentialsId: "${params.EPC_Credentials}", usernameVariable: 'EPC_Username', passwordVariable: 'EPC_Password'] ]) { sh "python3 ci-scripts/main.py --mode=TerminateMME --EPCIPAddress=${params.EPC_IPAddress} --EPCUserName=${EPC_Username} --EPCPassword=${EPC_Password} --EPCType=${params.EPC_Type} --EPCSourceCodePath=${params.EPC_SourceCodePath}" } } - if (!termStatusArray[termHSS]) { + if ((!termStatusArray[termHSS]) && (params.EPC_IPAddress != "none")) { withCredentials([ [$class: 'UsernamePasswordMultiBinding', credentialsId: "${params.EPC_Credentials}", usernameVariable: 'EPC_Username', passwordVariable: 'EPC_Password'] ]) { diff --git a/ci-scripts/Jenkinsfile-trig-nsa b/ci-scripts/Jenkinsfile-trig-nsa new file mode 100644 index 0000000000..3dd5ce3b50 --- /dev/null +++ b/ci-scripts/Jenkinsfile-trig-nsa @@ -0,0 +1,73 @@ +#!/bin/groovy +/* + * 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 + */ + +// Template Jenkins Declarative Pipeline script to run Test w/ RF HW + +// Location of the python executor node shall be in the same subnet as the others servers +def pythonExecutor = params.pythonExecutor + +def TARGET_BRANCH = "develop" +def ALLOW_MERGE = true + +pipeline { + agent { + label pythonExecutor + } + stages { + stage ("Launcher") { + steps { + script { + //retrieve MR that are opened nd with tag READY_TO_BE_MERGED + MR_LIST= sh returnStdout: true, script: 'curl --silent "https://gitlab.eurecom.fr/api/v4/projects/oai%2Fopenairinterface5g/merge_requests?state=opened&per_page=100&labels=READY_TO_BE_MERGED" | jq ".[].iid" || true ' + echo "List of selected MR:\n${MR_LIST}" + def MR_ARRAY = MR_LIST.split('\n') + //for every selected MR, retrieve the branch name and the latest commit + for (MR in MR_ARRAY) { + SRC_BRANCH=sh returnStdout: true, script: """curl --silent "https://gitlab.eurecom.fr/api/v4/projects/oai%2Fopenairinterface5g/merge_requests/${MR}" | jq ".source_branch" || true """ + SRC_BRANCH=SRC_BRANCH.trim() + COMMIT_ID=sh returnStdout: true, script: """curl --silent "https://gitlab.eurecom.fr/api/v4/projects/oai%2Fopenairinterface5g/merge_requests/${MR}" | jq ".sha" || true """ + COMMIT_ID=COMMIT_ID.trim() + echo "Testing NSA on : ${MR} ${SRC_BRANCH} ${COMMIT_ID}" + //calling NSA sub job + build job: "RAN-CI-NSA-B210", wait : false, propagate : false, parameters: [ + string(name: 'eNB_MR', value: String.valueOf(MR)), + string(name: 'eNB_Branch', value: String.valueOf(SRC_BRANCH)), + string(name: 'eNB_CommitID', value: String.valueOf(COMMIT_ID)), + string(name: 'eNB_TargetBranch', value: String.valueOf(TARGET_BRANCH)), + booleanParam(name: 'eNB_AllowMergeRequestProcess', value: Boolean.valueOf(ALLOW_MERGE)) + ] + //calling Benetel sub job + build job: "RAN-CI-BENETEL", wait : false, propagate : false, parameters: [ + string(name: 'eNB_MR', value: String.valueOf(MR)), + string(name: 'eNB_Branch', value: String.valueOf(SRC_BRANCH)), + string(name: 'eNB_CommitID', value: String.valueOf(COMMIT_ID)), + string(name: 'eNB_TargetBranch', value: String.valueOf(TARGET_BRANCH)), + booleanParam(name: 'eNB_AllowMergeRequestProcess', value: Boolean.valueOf(ALLOW_MERGE)) + ] + } + } + } + } + } +} + + diff --git a/ci-scripts/buildOnVM.sh b/ci-scripts/buildOnVM.sh index 861cab0782..2b1a5e0c71 100755 --- a/ci-scripts/buildOnVM.sh +++ b/ci-scripts/buildOnVM.sh @@ -62,6 +62,12 @@ function build_on_vm { echo "ARCHIVES_LOC = $ARCHIVES_LOC" echo "BUILD_OPTIONS = $BUILD_OPTIONS" + if [[ "$VM_NAME" == *"-enb-usrp"* ]] + then + echo "This VM type is no longer supported in the pipeline framework" + return + fi + IS_VM_ALIVE=`uvt-kvm list | grep -c $VM_NAME` if [ $IS_VM_ALIVE -eq 0 ] @@ -158,6 +164,9 @@ function build_on_vm { echo "cd tmp" >> $VM_CMDS echo "echo \"unzip -qq -DD ../localZip.zip\"" >> $VM_CMDS echo "unzip -qq -DD ../localZip.zip" >> $VM_CMDS + # Trying to make some room on filesystem before building + echo "rm ../localZip.zip" >> $VM_CMDS + echo "export CI_ENV=True" >> $VM_CMDS if [[ "$VM_NAME" == *"-cppcheck"* ]] then echo "mkdir cmake_targets/log" >> $VM_CMDS @@ -208,7 +217,15 @@ function build_on_vm { echo "echo \"./build_oai -I $BUILD_OPTIONS \"" >> $VM_CMDS echo "./build_oai -I $BUILD_OPTIONS > log/install-build.txt 2>&1" >> $VM_CMDS else - echo "echo \"./build_oai -I $BUILD_OPTIONS\" > ./my-vm-build.sh" >> $VM_CMDS + if [[ "$VM_NAME" == *"-enb-ethernet"* ]] + then + echo "echo \"sleep 170 && ./build_oai -I $BUILD_OPTIONS\" > ./my-vm-build.sh" >> $VM_CMDS + elif [[ "$VM_NAME" == *"-ue-ethernet"* ]] + then + echo "echo \"sleep 60 && ./build_oai -I $BUILD_OPTIONS\" > ./my-vm-build.sh" >> $VM_CMDS + else + echo "echo \"./build_oai -I $BUILD_OPTIONS\" > ./my-vm-build.sh" >> $VM_CMDS + fi echo "chmod 775 ./my-vm-build.sh " >> $VM_CMDS echo "echo \"sudo -E daemon --inherit --unsafe --name=build_daemon --chdir=/home/ubuntu/tmp/cmake_targets -o /home/ubuntu/tmp/cmake_targets/log/install-build.txt ./my-vm-build.sh\"" >> $VM_CMDS echo "sudo -E daemon --inherit --unsafe --name=build_daemon --chdir=/home/ubuntu/tmp/cmake_targets -o /home/ubuntu/tmp/cmake_targets/log/install-build.txt ./my-vm-build.sh" >> $VM_CMDS diff --git a/ci-scripts/cls_containerize.py b/ci-scripts/cls_containerize.py index 0c07dfe91f..0debe42468 100644 --- a/ci-scripts/cls_containerize.py +++ b/ci-scripts/cls_containerize.py @@ -35,6 +35,7 @@ import sys # arg import re # reg import logging import os +import shutil import time from multiprocessing import Process, Lock, SimpleQueue from zipfile import ZipFile @@ -124,7 +125,7 @@ class Containerize(): self.cli = 'docker' self.dockerfileprefix = '.ubuntu18' elif self.host == 'Red Hat': - self.cli = 'podman' + self.cli = 'sudo podman' self.dockerfileprefix = '.rhel8.2' imageNames = [] @@ -173,6 +174,7 @@ class Containerize(): # if the branch is not develop, then it is a merge request and we need to do # the potential merge. Note that merge conflicts should already been checked earlier imageTag = 'develop' + sharedTag = 'develop' if (self.ranAllowMerge): imageTag = 'ci-temp' if self.ranTargetBranch == '': @@ -188,38 +190,23 @@ class Containerize(): mySSH.command('mkdir -p tmp/entitlement/', '\$', 5) mySSH.command('sudo cp /etc/rhsm/ca/redhat-uep.pem tmp/ca/', '\$', 5) mySSH.command('sudo cp /etc/pki/entitlement/*.pem tmp/entitlement/', '\$', 5) - - #mySSH.close() - #return 0 + sharedimage = 'ran-build' # Let's remove any previous run artifacts if still there - mySSH.command(self.cli + ' image prune --force', '\$', 5) - mySSH.command(self.cli + ' image rm ' + sharedimage + ':' + imageTag, '\$', 5) + mySSH.command(self.cli + ' image prune --force', '\$', 30) + if (not self.ranAllowMerge): + mySSH.command(self.cli + ' image rm ' + sharedimage + ':' + sharedTag, '\$', 30) for image,pattern in imageNames: - mySSH.command(self.cli + ' image rm ' + image + ':' + imageTag, '\$', 5) - # Build the shared image - mySSH.command(self.cli + ' build --target ' + sharedimage + ' --tag ' + sharedimage + ':' + imageTag + ' --file docker/Dockerfile.ran' + self.dockerfileprefix + ' --build-arg NEEDED_GIT_PROXY="http://proxy.eurecom.fr:8080" . > cmake_targets/log/ran-build.log 2>&1', '\$', 1600) - # Build the target image(s) - previousImage = sharedimage + ':' + imageTag - danglingShaOnes=[] - for image,pattern in imageNames: - # the archived Dockerfiles have "ran-build:latest" as base image - # we need to update them with proper tag - mySSH.command('sed -i -e "s#' + sharedimage + ':latest#' + sharedimage + ':' + imageTag + '#" docker/Dockerfile.' + pattern + self.dockerfileprefix, '\$', 5) - mySSH.command(self.cli + ' build --target ' + image + ' --tag ' + image + ':' + imageTag + ' --file docker/Dockerfile.' + pattern + self.dockerfileprefix + ' . > cmake_targets/log/' + image + '.log 2>&1', '\$', 1200) - # Retrieving the dangling image(s) for the log collection - mySSH.command(self.cli + ' images --filter "dangling=true" --filter "since=' + previousImage + '" -q | sed -e "s#^#sha=#"', '\$', 5) - result = re.search('sha=(?P[a-zA-Z0-9\-\_]+)', mySSH.getBefore()) - if result is not None: - danglingShaOnes.append((image, result.group('imageShaOne'))) - previousImage = image + ':' + imageTag + mySSH.command(self.cli + ' image rm ' + image + ':' + imageTag, '\$', 30) - imageTag = 'ci-temp' - # First verify if images were properly created. + # Build the shared image only on Push Events (not on Merge Requests) + if (not self.ranAllowMerge): + mySSH.command(self.cli + ' build --target ' + sharedimage + ' --tag ' + sharedimage + ':' + sharedTag + ' --file docker/Dockerfile.ran' + self.dockerfileprefix + ' --build-arg NEEDED_GIT_PROXY="http://proxy.eurecom.fr:8080" . > cmake_targets/log/ran-build.log 2>&1', '\$', 1600) + # First verify if the shared image was properly created. status = True - mySSH.command(self.cli + ' image inspect --format=\'Size = {{.Size}} bytes\' ' + sharedimage + ':' + imageTag, '\$', 5) - if mySSH.getBefore().count('No such object') != 0: - logging.error('Could not build properly ran-build') + mySSH.command(self.cli + ' image inspect --format=\'Size = {{.Size}} bytes\' ' + sharedimage + ':' + sharedTag, '\$', 5) + if mySSH.getBefore().count('o such image') != 0: + logging.error('\u001B[1m Could not build properly ran-build\u001B[0m') status = False else: result = re.search('Size *= *(?P[0-9\-]+) *bytes', mySSH.getBefore()) @@ -240,11 +227,40 @@ class Containerize(): self.allImagesSize['ran-build'] = str(round(imageSize,1)) + ' Gbytes' else: logging.debug('ran-build size is unknown') + # If the shared image failed, no need to continue + if not status: + # Recover the name of the failed container? + mySSH.command(self.cli + ' ps --quiet --filter "status=exited" -n1 | xargs ' + self.cli + ' rm -f', '\$', 5) + mySSH.command(self.cli + ' image prune --force', '\$', 30) + mySSH.close() + logging.error('\u001B[1m Building OAI Images Failed\u001B[0m') + HTML.CreateHtmlTestRow(self.imageKind, 'KO', CONST.ALL_PROCESSES_OK) + HTML.CreateHtmlTabFooter(False) + sys.exit(1) + else: + # Recover build logs, for the moment only possible when build is successful + mySSH.command(self.cli + ' create --name test ' + sharedimage + ':' + sharedTag, '\$', 5) + mySSH.command('mkdir -p cmake_targets/log/ran-build', '\$', 5) + mySSH.command(self.cli + ' cp test:/oai-ran/cmake_targets/log/. cmake_targets/log/ran-build', '\$', 5) + mySSH.command(self.cli + ' rm -f test', '\$', 5) + + # Build the target image(s) for image,pattern in imageNames: + # the archived Dockerfiles have "ran-build:latest" as base image + # we need to update them with proper tag + mySSH.command('sed -i -e "s#' + sharedimage + ':latest#' + sharedimage + ':' + sharedTag + '#" docker/Dockerfile.' + pattern + self.dockerfileprefix, '\$', 5) + mySSH.command(self.cli + ' build --target ' + image + ' --tag ' + image + ':' + imageTag + ' --file docker/Dockerfile.' + pattern + self.dockerfileprefix + ' . > cmake_targets/log/' + image + '.log 2>&1', '\$', 1200) + # split the log + mySSH.command('mkdir -p cmake_targets/log/' + image, '\$', 5) + mySSH.command('python3 ci-scripts/docker_log_split.py --logfilename=cmake_targets/log/' + image + '.log', '\$', 5) + # checking the status of the build mySSH.command(self.cli + ' image inspect --format=\'Size = {{.Size}} bytes\' ' + image + ':' + imageTag, '\$', 5) - if mySSH.getBefore().count('No such object') != 0: - logging.error('Could not build properly ' + image) + if mySSH.getBefore().count('o such image') != 0: + logging.error('\u001B[1m Could not build properly ' + image + '\u001B[0m') status = False + # Here we should check if the last container corresponds to a failed command and destroy it + mySSH.command(self.cli + ' ps --quiet --filter "status=exited" -n1 | xargs ' + self.cli + ' rm -f', '\$', 5) + self.allImagesSize[image] = 'N/A -- Build Failed' else: result = re.search('Size *= *(?P[0-9\-]+) *bytes', mySSH.getBefore()) if result is not None: @@ -264,39 +280,27 @@ class Containerize(): self.allImagesSize[image] = str(round(imageSize,1)) + ' Gbytes' else: logging.debug('ran-build size is unknown') - if not status: - mySSH.close() - logging.error('\u001B[1m Building OAI Images Failed\u001B[0m') - HTML.CreateHtmlTestRow(self.imageKind, 'KO', CONST.ALL_PROCESSES_OK) - #HTML.CreateHtmlNextTabHeaderTestRow(self.collectInfo, self.allImagesSize) - HTML.CreateHtmlTabFooter(False) - sys.exit(1) + self.allImagesSize[image] = 'unknown' + # Now pruning dangling images in between target builds + mySSH.command(self.cli + ' image prune --force', '\$', 30) - # Recover build logs, for the moment only possible when build is successful - mySSH.command(self.cli + ' create --name test ' + sharedimage + ':' + imageTag, '\$', 5) - mySSH.command('mkdir -p cmake_targets/log/ran-build', '\$', 5) - mySSH.command(self.cli + ' cp test:/oai-ran/cmake_targets/log/. cmake_targets/log/ran-build', '\$', 5) - mySSH.command(self.cli + ' rm -f test', '\$', 5) - for image,shaone in danglingShaOnes: - mySSH.command('mkdir -p cmake_targets/log/' + image, '\$', 5) - mySSH.command(self.cli + ' create --name test ' + shaone, '\$', 5) - mySSH.command(self.cli + ' cp test:/oai-ran/cmake_targets/log/. cmake_targets/log/' + image, '\$', 5) - mySSH.command(self.cli + ' rm -f test', '\$', 5) - mySSH.command(self.cli + ' image prune --force', '\$', 5) - mySSH.command('cd cmake_targets', '\$', 5) + # Analyzing the logs + mySSH.command('cd ' + lSourcePath + '/cmake_targets', '\$', 5) mySSH.command('mkdir -p build_log_' + self.testCase_id, '\$', 5) mySSH.command('mv log/* ' + 'build_log_' + self.testCase_id, '\$', 5) - #mySSH.close() - - mySSH.command('cd /tmp/CI-eNB/cmake_targets', '\$', 5) + + mySSH.command('cd ' + lSourcePath + '/cmake_targets', '\$', 5) + mySSH.command('rm -f build_log_' + self.testCase_id + '.zip || true', '\$', 5) if (os.path.isfile('./build_log_' + self.testCase_id + '.zip')): os.remove('./build_log_' + self.testCase_id + '.zip') + if (os.path.isdir('./build_log_' + self.testCase_id)): + shutil.rmtree('./build_log_' + self.testCase_id) mySSH.command('zip -r -qq build_log_' + self.testCase_id + '.zip build_log_' + self.testCase_id, '\$', 5) mySSH.copyin(lIpAddr, lUserName, lPassWord, lSourcePath + '/cmake_targets/build_log_' + self.testCase_id + '.zip', '.') - #mySSH.command('rm -f build_log_' + self.testCase_id + '.zip','\$', 5) + mySSH.command('rm -f build_log_' + self.testCase_id + '.zip','\$', 5) mySSH.close() ZipFile('build_log_' + self.testCase_id + '.zip').extractall('.') - + #Trying to identify the errors and warnings for each built images imageNames1 = imageNames shared = ('ran-build','ran') @@ -328,9 +332,16 @@ class Containerize(): files[fil] = errorandwarnings self.collectInfo[image] = files - logging.info('\u001B[1m Building OAI Image(s) Pass\u001B[0m') - HTML.CreateHtmlTestRow(self.imageKind, 'OK', CONST.ALL_PROCESSES_OK) - HTML.CreateHtmlNextTabHeaderTestRow(self.collectInfo, self.allImagesSize) + if status: + logging.info('\u001B[1m Building OAI Image(s) Pass\u001B[0m') + HTML.CreateHtmlTestRow(self.imageKind, 'OK', CONST.ALL_PROCESSES_OK) + HTML.CreateHtmlNextTabHeaderTestRow(self.collectInfo, self.allImagesSize) + else: + logging.error('\u001B[1m Building OAI Images Failed\u001B[0m') + HTML.CreateHtmlTestRow(self.imageKind, 'KO', CONST.ALL_PROCESSES_OK) + HTML.CreateHtmlNextTabHeaderTestRow(self.collectInfo, self.allImagesSize) + HTML.CreateHtmlTabFooter(False) + sys.exit(1) def DeployObject(self, HTML, EPC): if self.eNB_serverId[self.eNB_instance] == '0': diff --git a/ci-scripts/conf_files/benetel-4g.conf b/ci-scripts/conf_files/benetel-4g.conf new file mode 100644 index 0000000000..9423ebe56e --- /dev/null +++ b/ci-scripts/conf_files/benetel-4g.conf @@ -0,0 +1,285 @@ +Active_eNBs = ( "eNB-Eurecom-LTEBox"); +# Asn1_verbosity, choice in: none, info, annoying +Asn1_verbosity = "none"; + +eNBs = +( + { + # real_time choice in {hard, rt-preempt, no} + real_time = "no"; + + ////////// Identification parameters: + eNB_ID = 0xe00; + + cell_type = "CELL_MACRO_ENB"; + + eNB_name = "eNB-Eurecom-LTEBox"; + + // Tracking area code, 0x0000 and 0xfffe are reserved values + tracking_area_code = 1; + plmn_list = ( { mcc = 222; mnc = 01; mnc_length = 2; } ); + + tr_s_preference = "local_mac" + + ////////// Physical parameters: + + component_carriers = ( + { + node_function = "NGFI_RCC_IF4p5"; + 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 = 2655000000L; + uplink_frequency_offset = -120000000; + Nid_cell = 0; + N_RB_DL = 100; + Nid_cell_mbsfn = 0; + nb_antenna_ports = 1; + nb_antennas_tx = 1; + nb_antennas_rx = 1; + tx_gain = 90; + rx_gain = 125; + pbch_repetition = "FALSE"; + prach_root = 0; + prach_config_index = 0; + prach_high_speed = "DISABLE"; + prach_zero_correlation = 1; + prach_freq_offset = 90; + pucch_delta_shift = 1; + pucch_nRB_CQI = 0; + pucch_nCS_AN = 0; + pucch_n1_AN = 0; + pdsch_referenceSignalPower = -10; + pdsch_p_b = 0; + pusch_n_SB = 1; + pusch_enable64QAM = "DISABLE"; + pusch_hoppingMode = "interSubFrame"; + pusch_hoppingOffset = 0; + pusch_groupHoppingEnabled = "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; + + //SSB central frequency of NR secondary cell group (for ENDC NSA) + nr_scg_ssb_freq = 640000; + } + ); + + + 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 = "CI_MME_IP_ADDR"; + ipv6 = "192:168:30::17"; + active = "yes"; + preference = "ipv4"; + } + ); + + enable_measurement_reports = "yes"; + + ///X2 + enable_x2 = "yes"; + t_reloc_prep = 1000; /* unit: millisecond */ + tx2_reloc_overall = 2000; /* unit: millisecond */ + t_dc_prep = 1000; /* unit: millisecond */ + t_dc_overall = 2000; /* unit: millisecond */ + + NETWORK_INTERFACES : + { + ENB_INTERFACE_NAME_FOR_S1_MME = "eth0"; + ENB_IPV4_ADDRESS_FOR_S1_MME = "CI_ENB_IP_ADDR"; + ENB_INTERFACE_NAME_FOR_S1U = "eth0"; + ENB_IPV4_ADDRESS_FOR_S1U = "CI_ENB_IP_ADDR"; + ENB_PORT_FOR_S1U = 2152; # Spec 2152 + ENB_IPV4_ADDRESS_FOR_X2C = "127.0.0.1"; + ENB_PORT_FOR_X2C = 36422; # Spec 36422 + }; + } +); + +MACRLCs = ( + { + num_cc = 1; + tr_s_preference = "local_L1"; + tr_n_preference = "local_RRC"; + phy_test_mode = 0; + puSch10xSnr = 160; + puCch10xSnr = 160; + } +); + +L1s = ( + { + num_cc = 1; + tr_n_preference = "local_mac"; + prach_dtx_threshold = 150; + } +); + +RUs = ( + { + //local_if_name = "enp129s0f0"; + local_if_name = "dpdk"; + sdr_addrs = "softmodem -m 2048 -l 35 -n 2 -b 0000:81:00.3 --proc-type auto --file-prefix ggg -- -p 0x1"; + #sdr_addrs = "softmodem -l 8 -n 2 -- -p 0x2"; + #remote_address = "127.0.0.2"; + #local_address = "127.0.0.1"; + #local_portc = 50000; + #remote_portc = 50000; + #local_portd = 50001; + #remote_portd = 50001; + local_rf = "no" + tr_preference = "raw_if4p5" + nb_tx = 1 + nb_rx = 1 + att_tx = 0 + att_rx = 0; + eNB_instances = [0]; + } +); + +THREAD_STRUCT = ( + { + #three config for level of parallelism "PARALLEL_SINGLE_THREAD", "PARALLEL_RU_L1_SPLIT", or "PARALLEL_RU_L1_TRX_SPLIT" + #parallel_config = "PARALLEL_RU_L1_TRX_SPLIT"; + parallel_config = "PARALLEL_SINGLE_THREAD"; + #two option for worker "WORKER_DISABLE" or "WORKER_ENABLE" + worker_config = "WORKER_ENABLE"; + } +); + +NETWORK_CONTROLLER : +{ + FLEXRAN_ENABLED = "no"; + FLEXRAN_INTERFACE_NAME = "lo"; + FLEXRAN_IPV4_ADDRESS = "127.0.0.1"; + FLEXRAN_PORT = 2210; + FLEXRAN_CACHE = "/mnt/oai_agent_cache"; + FLEXRAN_AWAIT_RECONF = "no"; +}; + + log_config : + { + global_log_level ="info"; + global_log_verbosity ="medium"; + hw_log_level ="info"; + hw_log_verbosity ="medium"; + phy_log_level ="info"; + phy_log_verbosity ="medium"; + mac_log_level ="info"; + mac_log_verbosity ="high"; + rlc_log_level ="info"; + rlc_log_verbosity ="medium"; + pdcp_log_level ="info"; + pdcp_log_verbosity ="medium"; + rrc_log_level ="info"; + rrc_log_verbosity ="medium"; + }; diff --git a/ci-scripts/conf_files/benetel-5g.conf b/ci-scripts/conf_files/benetel-5g.conf new file mode 100644 index 0000000000..0dfe7854ee --- /dev/null +++ b/ci-scripts/conf_files/benetel-5g.conf @@ -0,0 +1,317 @@ +Active_gNBs = ( "gNB-Eurecom-5GNRBox"); +# Asn1_verbosity, choice in: none, info, annoying +Asn1_verbosity = "none"; + +gNBs = +( + { + ////////// Identification parameters: + gNB_ID = 0xe00; + + cell_type = "CELL_MACRO_GNB"; + + gNB_name = "gNB-Eurecom-5GNRBox"; + + // Tracking area code, 0x0000 and 0xfffe are reserved values + tracking_area_code = 1; + + plmn_list = ({mcc = 222; mnc = 01; mnc_length = 2;}); + + tr_s_preference = "local_mac" + + ////////// Physical parameters: + + ssb_SubcarrierOffset = 31; //0; + pdsch_AntennaPorts = 1; + #pusch_TargetSNRx10 = 200; + #pucch_TargetSNRx10 = 200; + pusch_TargetSNRx10 = 200; + pucch_TargetSNRx10 = 200; + + servingCellConfigCommon = ( + { + #spCellConfigCommon + + physCellId = 0; + +# downlinkConfigCommon + #frequencyInfoDL + # this is is the central frequency of SSB + absoluteFrequencySSB = 640000; //641272 + dl_frequencyBand = 78; + # the carrier frequency is assumed to be in the middle of the carrier, i.e. dl_absoluteFrequencyPointA_kHz + dl_carrierBandwidth*12*SCS_kHz/2 + dl_absoluteFrequencyPointA = 638728; //640000; + #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=84,L=13 (275*(L-1))+RBstart + initialDLBWPlocationAndBandwidth = 6366; //28875; //6366; #6407; #3384; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + initialDLBWPsubcarrierSpacing = 1; + #pdcch-ConfigCommon + initialDLBWPcontrolResourceSetZero = 0; + initialDLBWPsearchSpaceZero = 0; + #pdsch-ConfigCommon + #pdschTimeDomainAllocationList (up to 16 entries) + initialDLBWPk0_0 = 0; + #initialULBWPmappingType + #0=typeA,1=typeB + initialDLBWPmappingType_0 = 0; + #this is SS=1,L=13 + initialDLBWPstartSymbolAndLength_0 = 40; + + initialDLBWPk0_1 = 0; + initialDLBWPmappingType_1 = 0; + #this is SS=2,L=12 + initialDLBWPstartSymbolAndLength_1 = 53; + + initialDLBWPk0_2 = 0; + initialDLBWPmappingType_2 = 0; + #this is SS=1,L=12 + initialDLBWPstartSymbolAndLength_2 = 54; + + initialDLBWPk0_3 = 0; + initialDLBWPmappingType_3 = 0; + #this is SS=1,L=4 //5 (4 is for 43, 5 is for 57) + initialDLBWPstartSymbolAndLength_3 = 57; //43; //57; + #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 = 6366; //28875; //6366; #6407; #3384; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + initialULBWPsubcarrierSpacing = 1; + #rach-ConfigCommon + #rach-ConfigGeneric + prach_ConfigurationIndex = 4; +#prach_msg1_FDM +#0 = one, 1=two, 2=four, 3=eight + prach_msg1_FDM = 0; + prach_msg1_FrequencyStart = 74; + zeroCorrelationZoneConfig = 13; + preambleReceivedTargetPower = -118; + #preambleReceivedTargetPower = -104; + #preambleReceivedTargetPower = -108; +#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 = 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; +#oneHalf (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 + ra_ContentionResolutionTimer = 7; + rsrp_ThresholdSSB = 19; +#prach-RootSequenceIndex_PR +#1 = 839, 2 = 139 + prach_RootSequenceIndex_PR = 1; + 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, + # pusch-ConfigCommon (up to 16 elements) + initialULBWPk2_0 = 2; + initialULBWPmappingType_0 = 1 + # this is SS=0 L=11 + initialULBWPstartSymbolAndLength_0 = 55; + + initialULBWPk2_1 = 2; + initialULBWPmappingType_1 = 1; + # this is SS=0 L=12 + initialULBWPstartSymbolAndLength_1 = 69; + + initialULBWPk2_2 = 7; + initialULBWPmappingType_2 = 1; + # this is SS=10 L=4 + initialULBWPstartSymbolAndLength_2 = 52; + + msg3_DeltaPreamble = 1; + #p0_NominalWithGrant =-90; + p0_NominalWithGrant =-118; + +# pucch-ConfigCommon setup : +# pucchGroupHopping +# 0 = neither, 1= group hopping, 2=sequence hopping + pucchGroupHopping = 0; + hoppingId = 40; + #p0_nominal = -90; + p0_nominal = -118; +# ssb_PositionsInBurs_BitmapPR +# 1=short, 2=medium, 3=long + ssb_PositionsInBurst_PR = 2; + ssb_PositionsInBurst_Bitmap = 1; #0x80; + +# 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; //8; //7; + nrofDownlinkSymbols = 6; //0; //6; + nrofUplinkSlots = 2; + nrofUplinkSymbols = 4; //0; //4; + + #ssPBCH_BlockPower = 10; + ssPBCH_BlockPower = -35; + } + + ); + + + # ------- SCTP definitions + SCTP : + { + # Number of streams to use in input/output + SCTP_INSTREAMS = 2; + SCTP_OUTSTREAMS = 2; + }; + + + ////////// MME parameters: + mme_ip_address = ( { ipv4 = "CI_MME_IP_ADDR"; + ipv6 = "192:168:30::17"; + active = "yes"; + preference = "ipv4"; + } + ); + + ///X2 + enable_x2 = "yes"; + t_reloc_prep = 1000; /* unit: millisecond */ + tx2_reloc_overall = 2000; /* unit: millisecond */ + t_dc_prep = 1000; /* unit: millisecond */ + t_dc_overall = 2000; /* unit: millisecond */ + target_enb_x2_ip_address = ( + { ipv4 = "127.0.0.1"; + ipv6 = "192:168:30::17"; + preference = "ipv4"; + } + ); + + NETWORK_INTERFACES : + { + + GNB_INTERFACE_NAME_FOR_S1_MME = "eth0"; + GNB_IPV4_ADDRESS_FOR_S1_MME = "CI_GNB_IP_ADDR"; + GNB_INTERFACE_NAME_FOR_S1U = "eth0"; + GNB_IPV4_ADDRESS_FOR_S1U = "CI_GNB_IP_ADDR"; + GNB_PORT_FOR_S1U = 2152; # Spec 2152 + GNB_IPV4_ADDRESS_FOR_X2C = "127.0.0.2/24"; + GNB_PORT_FOR_X2C = 36422; # Spec 36422 + }; + } +); + +MACRLCs = ( + { + num_cc = 1; + tr_s_preference = "local_L1"; + tr_n_preference = "local_RRC"; + } +); + +L1s = ( + { + num_cc = 1; + tr_n_preference = "local_mac"; + pusch_proc_threads = 8; + } +); + +RUs = ( + { + local_rf = "no" + nb_tx = 1 + nb_rx = 1 + att_tx = 0 + att_rx = 0; + bands = [7]; + max_pdschReferenceSignalPower = -27; + max_rxgain = 114; + eNB_instances = [0]; + //clock_src = "internal"; + clock_src = "external"; + + local_if_name = "dpdk"; + sdr_addrs = "softmodem -m 2048 -l 34 -n 3 -b 0000:81:00.2 --proc-type auto --file-prefix hhh -- -p 0x1"; + remote_address = "127.0.0.2"; + local_address = "127.0.0.1"; + local_portc = 50000; + remote_portc = 50000; + local_portd = 50001; + remote_portd = 50001; + tr_preference = "raw_if4p5" + + } +); + +THREAD_STRUCT = ( + { + #three config for level of parallelism "PARALLEL_SINGLE_THREAD", "PARALLEL_RU_L1_SPLIT", or "PARALLEL_RU_L1_TRX_SPLIT" + //parallel_config = "PARALLEL_RU_L1_TRX_SPLIT"; + parallel_config = "PARALLEL_SINGLE_THREAD"; + #two option for worker "WORKER_DISABLE" or "WORKER_ENABLE" + worker_config = "WORKER_DISABLE"; + } +); + + log_config : + { + global_log_level ="info"; + global_log_verbosity ="medium"; + hw_log_level ="info"; + hw_log_verbosity ="medium"; + phy_log_level ="info"; + phy_log_verbosity ="medium"; + mac_log_level ="info"; + mac_log_verbosity ="high"; + rlc_log_level ="info"; + rlc_log_verbosity ="medium"; + pdcp_log_level ="info"; + pdcp_log_verbosity ="medium"; + rrc_log_level ="info"; + rrc_log_verbosity ="medium"; + }; + diff --git a/ci-scripts/conf_files/gnb.band66.tm1.106PRB.usrpn300.conf b/ci-scripts/conf_files/gnb.band66.tm1.106PRB.usrpn300.conf new file mode 100644 index 0000000000..32de0aa4f5 --- /dev/null +++ b/ci-scripts/conf_files/gnb.band66.tm1.106PRB.usrpn300.conf @@ -0,0 +1,292 @@ +Active_gNBs = ( "gNB-Eurecom-5GNRBox"); +# Asn1_verbosity, choice in: none, info, annoying +Asn1_verbosity = "none"; + +gNBs = +( + { + ////////// Identification parameters: + gNB_ID = 0xe00; + + cell_type = "CELL_MACRO_GNB"; + + gNB_name = "gNB-Eurecom-5GNRBox"; + + // Tracking area code, 0x0000 and 0xfffe are reserved values + tracking_area_code = 1; + + plmn_list = ({mcc = 208; mnc = 93; mnc_length = 2;}); + + tr_s_preference = "local_mac" + + ////////// Physical parameters: + + ssb_SubcarrierOffset = 0; + pdsch_AntennaPorts = 1; + + servingCellConfigCommon = ( + { + #spCellConfigCommon + + physCellId = 0; + +# downlinkConfigCommon + #frequencyInfoDL + # this is 2150 MHz + 43 PRBs@30kHz SCS (same as initial BWP) + absoluteFrequencySSB = 433096; + dl_frequencyBand = 66; + # this is 2150 MHz + dl_absoluteFrequencyPointA = 430000; + #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=0,L=50 (275*(L-1))+RBstart + initialDLBWPlocationAndBandwidth = 13475; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + initialDLBWPsubcarrierSpacing = 1; + #pdcch-ConfigCommon + initialDLBWPcontrolResourceSetZero = 12; + initialDLBWPsearchSpaceZero = 0; + #pdsch-ConfigCommon + #pdschTimeDomainAllocationList (up to 16 entries) + initialDLBWPk0_0 = 0; + #initialULBWPmappingType + #0=typeA,1=typeB + initialDLBWPmappingType_0 = 0; + #this is SS=1,L=13 + initialDLBWPstartSymbolAndLength_0 = 40; + + initialDLBWPk0_1 = 0; + initialDLBWPmappingType_1 = 0; + #this is SS=2,L=12 + initialDLBWPstartSymbolAndLength_1 = 53; + + initialDLBWPk0_2 = 0; + initialDLBWPmappingType_2 = 0; + #this is SS=1,L=12 + initialDLBWPstartSymbolAndLength_2 = 54; + + initialDLBWPk0_3 = 0; + initialDLBWPmappingType_3 = 0; + #this is SS=1,L=4 + initialDLBWPstartSymbolAndLength_3 = 57; + #uplinkConfigCommon + #frequencyInfoUL + ul_frequencyBand = 66; + ul_absoluteFrequencyPointA = 350000; + #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 = 13475; +# 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 = -118; +#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; +#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; +#oneHalf (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, + # pusch-ConfigCommon (up to 16 elements) + initialULBWPk2_0 = 6; + initialULBWPmappingType_0 = 1 + # this is SS=0 L=11 + initialULBWPstartSymbolAndLength_0 = 55; + + initialULBWPk2_1 = 6; + initialULBWPmappingType_1 = 1; + # this is SS=0 L=12 + initialULBWPstartSymbolAndLength_1 = 69; + + initialULBWPk2_2 = 7; + initialULBWPmappingType_2 = 1; + # this is SS=10 L=4 + initialULBWPstartSymbolAndLength_2 = 52; + 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 = 10; + } + + ); + + + # ------- SCTP definitions + SCTP : + { + # Number of streams to use in input/output + SCTP_INSTREAMS = 2; + SCTP_OUTSTREAMS = 2; + }; + + + ////////// MME parameters: + mme_ip_address = ( { ipv4 = "192.168.12.26"; + ipv6 = "192:168:30::17"; + active = "yes"; + preference = "ipv4"; + } + ); + + NETWORK_INTERFACES : + { + + GNB_INTERFACE_NAME_FOR_S1_MME = "eth0"; + GNB_IPV4_ADDRESS_FOR_S1_MME = "192.168.12.111/24"; + GNB_INTERFACE_NAME_FOR_S1U = "eth0"; + GNB_IPV4_ADDRESS_FOR_S1U = "192.168.12.111/24"; + GNB_PORT_FOR_S1U = 2152; # Spec 2152 + }; + } +); + +MACRLCs = ( + { + num_cc = 1; + tr_s_preference = "local_L1"; + tr_n_preference = "local_RRC"; + } +); + +L1s = ( + { + num_cc = 1; + tr_n_preference = "local_mac"; + pusch_proc_threads = 8; + } +); + +RUs = ( + { + local_rf = "yes" + nb_tx = 1; + nb_rx = 1; + att_tx = 0; + att_rx = 0; + bands = [7]; + max_pdschReferenceSignalPower = -27; + max_rxgain = 75; + eNB_instances = [0]; + ##beamforming 1x2 matrix: 1 layer x 2 antennas + bf_weights = [0x00007fff, 0x0000]; + ##beamforming 1x4 matrix: 1 layer x 4 antennas + #bf_weights = [0x00007fff, 0x0000,0x0000, 0x0000]; + ## beamforming 2x2 matrix: + # bf_weights = [0x00007fff, 0x00000000, 0x00000000, 0x00007fff]; + ## beamforming 4x4 matrix: + #bf_weights = [0x00007fff, 0x0000, 0x0000, 0x0000, 0x00000000, 0x00007fff, 0x0000, 0x0000, 0x0000, 0x0000, 0x00007fff, 0x0000, 0x0000, 0x0000, 0x0000, 0x00007fff]; + + sdr_addrs = "addr=192.168.10.2,mgmt_addr=192.168.10.2,second_addr=192.168.20.2"; + clock_src = "external"; + # if_freq = 3700000000L; + # if_offset = 1000000; + } +); + +THREAD_STRUCT = ( + { + #three config for level of parallelism "PARALLEL_SINGLE_THREAD", "PARALLEL_RU_L1_SPLIT", or "PARALLEL_RU_L1_TRX_SPLIT" + parallel_config = "PARALLEL_RU_L1_TRX_SPLIT"; + #two option for worker "WORKER_DISABLE" or "WORKER_ENABLE" + worker_config = "WORKER_ENABLE"; + } +); + + log_config : + { + global_log_level ="info"; + global_log_verbosity ="medium"; + hw_log_level ="info"; + hw_log_verbosity ="medium"; + phy_log_level ="info"; + phy_log_verbosity ="medium"; + mac_log_level ="info"; + mac_log_verbosity ="high"; + rlc_log_level ="info"; + rlc_log_verbosity ="medium"; + pdcp_log_level ="info"; + pdcp_log_verbosity ="medium"; + rrc_log_level ="info"; + rrc_log_verbosity ="medium"; + }; + diff --git a/ci-scripts/conf_files/gnb.band78.tm1.106PRB.usrpn300.conf b/ci-scripts/conf_files/gnb.band78.tm1.106PRB.usrpn300.conf index aeba400cad..decaa392d7 100644 --- a/ci-scripts/conf_files/gnb.band78.tm1.106PRB.usrpn300.conf +++ b/ci-scripts/conf_files/gnb.band78.tm1.106PRB.usrpn300.conf @@ -23,7 +23,7 @@ gNBs = ssb_SubcarrierOffset = 0; pdsch_AntennaPorts = 1; - + servingCellConfigCommon = ( { #spCellConfigCommon @@ -227,14 +227,15 @@ MACRLCs = ( num_cc = 1; tr_s_preference = "local_L1"; tr_n_preference = "local_RRC"; - } + } ); L1s = ( - { + { num_cc = 1; tr_n_preference = "local_mac"; - } + pusch_proc_threads = 8; + } ); RUs = ( @@ -248,8 +249,15 @@ RUs = ( max_pdschReferenceSignalPower = -27; max_rxgain = 75; eNB_instances = [0]; - #beamforming 1x4 matrix: - bf_weights = [0x00007fff, 0x0000, 0x0000, 0x0000]; + ##beamforming 1x2 matrix: 1 layer x 2 antennas + bf_weights = [0x00007fff, 0x0000]; + ##beamforming 1x4 matrix: 1 layer x 4 antennas + #bf_weights = [0x00007fff, 0x0000,0x0000, 0x0000]; + ## beamforming 2x2 matrix: + # bf_weights = [0x00007fff, 0x00000000, 0x00000000, 0x00007fff]; + ## beamforming 4x4 matrix: + #bf_weights = [0x00007fff, 0x0000, 0x0000, 0x0000, 0x00000000, 0x00007fff, 0x0000, 0x0000, 0x0000, 0x0000, 0x00007fff, 0x0000, 0x0000, 0x0000, 0x0000, 0x00007fff]; + sdr_addrs = "addr=192.168.10.2,mgmt_addr=192.168.10.2,second_addr=192.168.20.2"; clock_src = "external"; } diff --git a/ci-scripts/createVM.sh b/ci-scripts/createVM.sh index 237a1a5d5e..b67668f0bc 100755 --- a/ci-scripts/createVM.sh +++ b/ci-scripts/createVM.sh @@ -87,6 +87,12 @@ function create_vm { echo "VM_CPU = $VM_CPU" echo "VM_DISK = $VM_DISK GBytes" + if [[ "$VM_NAME" == *"-enb-usrp"* ]] + then + echo "This VM type is no longer supported in the pipeline framework" + return + fi + echo "############################################################" echo "Creating VM ($VM_NAME) on Ubuntu Cloud Image base" echo "############################################################" diff --git a/ci-scripts/docker_log_split.py b/ci-scripts/docker_log_split.py new file mode 100644 index 0000000000..8c3c9e41dc --- /dev/null +++ b/ci-scripts/docker_log_split.py @@ -0,0 +1,92 @@ +#/* +# * 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 Libs +#----------------------------------------------------------- +import sys # arg +import re # reg +import os +import subprocess + + +class SplitReport(): + def __init__(self): + self.logfilename = '' + self.destinationFolder = '' + + def split(self): + self.destinationFolder = self.logfilename.replace(".log","") + if os.path.isfile(self.logfilename): + newImageLog = open(self.logfilename + '.new', 'w') + copyFlag = True + with open(self.logfilename, 'r') as imageLog: + for line in imageLog: + header = False + ret = re.search('====== Start of log for ([0-9\.A-Za-z\-\_]+) ======', line) + if ret is not None: + copyFlag = False + header = True + detailedLogFile = open(self.destinationFolder + '/' + ret.group(1), 'w') + if copyFlag: + newImageLog.write(line) + ret = re.search('====== End of log for ([0-9\.A-Za-z\-\_]+) ======', line) + if ret is not None: + copyFlag = True + detailedLogFile.close() + elif not copyFlag and not header: + detailedLogFile.write(line) + imageLog.close() + newImageLog.close() + os.rename(self.logfilename + '.new', self.logfilename) + else: + print('Cannot split unfound file') + +#-------------------------------------------------------------------------------------------------------- +# +# Start of main +# +#-------------------------------------------------------------------------------------------------------- + +argvs = sys.argv +argc = len(argvs) + +SP = SplitReport() + +while len(argvs) > 1: + myArgv = argvs.pop(1) + if re.match('^\-\-logfilename=(.+)$', myArgv, re.IGNORECASE): + matchReg = re.match('^\-\-logfilename=(.+)$', myArgv, re.IGNORECASE) + SP.logfilename = matchReg.group(1) + +SP.split() + +sys.exit(0) diff --git a/ci-scripts/oai-ci-vm-tool b/ci-scripts/oai-ci-vm-tool index 9b9fe462f1..d8f088b707 100755 --- a/ci-scripts/oai-ci-vm-tool +++ b/ci-scripts/oai-ci-vm-tool @@ -172,6 +172,7 @@ function setvar_usage { function variant__v1__enb_usrp { NB_PATTERN_FILES=9 BUILD_OPTIONS="--eNB -w USRP --mu" + VM_MEMORY=3072 } function variant__v2__basic_sim { @@ -213,15 +214,15 @@ function variant__v6__nr_ue_usrp { function variant__v7__enb_ethernet { VM_MEMORY=4096 ARCHIVES_LOC=enb_eth - NB_PATTERN_FILES=8 - BUILD_OPTIONS="--eNB" + NB_PATTERN_FILES=9 + BUILD_OPTIONS="--eNB -w USRP" } function variant__v8__ue_ethernet { VM_MEMORY=4096 ARCHIVES_LOC=ue_eth - NB_PATTERN_FILES=12 - BUILD_OPTIONS="--UE" + NB_PATTERN_FILES=13 + BUILD_OPTIONS="--UE -w USRP" } function variant__v10__flexran_rtc { diff --git a/ci-scripts/ran.py b/ci-scripts/ran.py index 774d7f19c6..783adb98e6 100644 --- a/ci-scripts/ran.py +++ b/ci-scripts/ran.py @@ -239,6 +239,7 @@ class RANManagement(): while (count > 0) and buildOAIprocess: mySSH.command('ps aux | grep --color=never build_ | grep -v grep', '\$', 6) result = re.search('build_oai', mySSH.getBefore()) + print(result) if result is None: buildOAIprocess = False else: @@ -464,7 +465,7 @@ class RANManagement(): self.prematureExit = True return else: - mySSH.command('stdbuf -o0 cat enb_' + self.testCase_id + '.log | egrep --text --color=never -i "wait|sync|Starting"', '\$', 4) + mySSH.command('stdbuf -o0 cat enb_' + self.testCase_id + '.log | egrep --text --color=never -i "wait|sync|Starting|Started"', '\$', 4) if rruCheck: result = re.search('wait RUs', mySSH.getBefore()) else: diff --git a/ci-scripts/reportBuildLocally.sh b/ci-scripts/reportBuildLocally.sh index 44d200c3b6..19a486303f 100755 --- a/ci-scripts/reportBuildLocally.sh +++ b/ci-scripts/reportBuildLocally.sh @@ -580,16 +580,42 @@ function report_build { sca_summary_table_row ./archives/cppcheck/cppcheck.xml "Expression depends on order of evaluation of side effects" unknownEvaluationOrder sca_summary_table_footer ./archives/cppcheck/cppcheck.xml - summary_table_header "OAI Build: 4G LTE eNB -- USRP option" ./archives/enb_usrp - summary_table_row "LTE SoftModem - Release 15" ./archives/enb_usrp/lte-softmodem.Rel15.txt "Built target lte-softmodem" ./enb_usrp_row1.html - summary_table_row "Coding - Release 15" ./archives/enb_usrp/coding.Rel15.txt "Built target coding" ./enb_usrp_row2.html - summary_table_row "OAI USRP device if - Release 15" ./archives/enb_usrp/oai_usrpdevif.Rel15.txt "Built target oai_usrpdevif" ./enb_usrp_row3.html - summary_table_row "OAI ETHERNET transport - Release 15" ./archives/enb_usrp/oai_eth_transpro.Rel15.txt "Built target oai_eth_transpro" ./enb_usrp_row4.html - summary_table_row "Parameters Lib Config - Release 15" ./archives/enb_usrp/params_libconfig.Rel15.txt "Built target params_libconfig" ./enb_usrp_row5.html - summary_table_row "NASMESH - Release 15" ./archives/enb_usrp/nasmesh.Rel15.txt "Built target nasmesh" ./enb_usrp_row6.html - summary_table_row "RB Tool - Release 15" ./archives/enb_usrp/rb_tool.Rel15.txt "Built target rb_tool" ./enb_usrp_row7.html - summary_table_row "RF Simulator - Release 15" ./archives/enb_usrp/rfsimulator.Rel15.txt "Built target rfsimulator" ./enb_usrp_row8.html - summary_table_row "TCP Bridge - Release 15" ./archives/enb_usrp/tcp_bridge_oai.Rel15.txt "Built target tcp_bridge_oai" ./enb_usrp_row9.html +# summary_table_header "OAI Build: 4G LTE eNB -- USRP option" ./archives/enb_usrp +# summary_table_row "LTE SoftModem - Release 15" ./archives/enb_usrp/lte-softmodem.Rel15.txt "Built target lte-softmodem" ./enb_usrp_row1.html +# summary_table_row "Coding - Release 15" ./archives/enb_usrp/coding.Rel15.txt "Built target coding" ./enb_usrp_row2.html +# summary_table_row "OAI USRP device if - Release 15" ./archives/enb_usrp/oai_usrpdevif.Rel15.txt "Built target oai_usrpdevif" ./enb_usrp_row3.html +# summary_table_row "OAI ETHERNET transport - Release 15" ./archives/enb_usrp/oai_eth_transpro.Rel15.txt "Built target oai_eth_transpro" ./enb_usrp_row4.html +# summary_table_row "Parameters Lib Config - Release 15" ./archives/enb_usrp/params_libconfig.Rel15.txt "Built target params_libconfig" ./enb_usrp_row5.html +# summary_table_row "NASMESH - Release 15" ./archives/enb_usrp/nasmesh.Rel15.txt "Built target nasmesh" ./enb_usrp_row6.html +# summary_table_row "RB Tool - Release 15" ./archives/enb_usrp/rb_tool.Rel15.txt "Built target rb_tool" ./enb_usrp_row7.html +# summary_table_row "RF Simulator - Release 15" ./archives/enb_usrp/rfsimulator.Rel15.txt "Built target rfsimulator" ./enb_usrp_row8.html +# summary_table_row "TCP Bridge - Release 15" ./archives/enb_usrp/tcp_bridge_oai.Rel15.txt "Built target tcp_bridge_oai" ./enb_usrp_row9.html +# summary_table_footer +# + summary_table_header "OAI Build: 4G LTE eNB -- USRP option" ./archives/enb_eth + summary_table_row "LTE SoftModem - Release 15" ./archives/enb_eth/lte-softmodem.Rel15.txt "Built target lte-softmodem" ./enb_eth_row1.html + summary_table_row "Coding - Release 15" ./archives/enb_eth/coding.Rel15.txt "Built target coding" ./enb_eth_row2.html + summary_table_row "OAI ETHERNET transport - Release 15" ./archives/enb_eth/oai_eth_transpro.Rel15.txt "Built target oai_eth_transpro" ./enb_eth_row3.html + summary_table_row "Parameters Lib Config - Release 15" ./archives/enb_eth/params_libconfig.Rel15.txt "Built target params_libconfig" ./enb_eth_row4.html + summary_table_row "RF Simulator - Release 15" ./archives/enb_eth/rfsimulator.Rel15.txt "Built target rfsimulator" ./enb_eth_row5.html + summary_table_row "TCP OAI Bridge - Release 15" ./archives/enb_eth/tcp_bridge_oai.Rel15.txt "Built target tcp_bridge_oai" ./enb_eth_row6.html + summary_table_row "OAI USRP device if - Release 15" ./archives/enb_eth/oai_usrpdevif.Rel15.txt "Built target oai_usrpdevif" ./enb_eth_row7.html + summary_table_row "NASMESH - Release 15" ./archives/enb_eth/nasmesh.Rel15.txt "Built target nasmesh" ./enb_eth_row8.html + summary_table_row "RB Tool - Release 15" ./archives/enb_eth/rb_tool.Rel15.txt "Built target rb_tool" ./enb_eth_row9.html + summary_table_footer + + summary_table_header "OAI Build: 4G LTE UE -- USRP option" ./archives/ue_eth + summary_table_row "LTE UE SoftModem - Release 15" ./archives/ue_eth/lte-uesoftmodem.Rel15.txt "Built target lte-uesoftmodem" ./ue_eth_row1.html + summary_table_row "Coding - Release 15" ./archives/ue_eth/coding.Rel15.txt "Built target coding" ./ue_eth_row2.html + summary_table_row "OAI ETHERNET transport - Release 15" ./archives/ue_eth/oai_eth_transpro.Rel15.txt "Built target oai_eth_transpro" ./ue_eth_row3.html + summary_table_row "Parameters Lib Config - Release 15" ./archives/ue_eth/params_libconfig.Rel15.txt "Built target params_libconfig" ./ue_eth_row4.html + summary_table_row "RF Simulator - Release 15" ./archives/ue_eth/rfsimulator.Rel15.txt "Built target rfsimulator" ./ue_eth_row5.html + summary_table_row "TCP OAI Bridge - Release 15" ./archives/ue_eth/tcp_bridge_oai.Rel15.txt "Built target tcp_bridge_oai" ./ue_eth_row6.html + summary_table_row "Conf 2 UE Data - Release 15" ./archives/ue_eth/conf2uedata.Rel15.txt "Built target conf2uedata" ./ue_eth_row7.html + summary_table_row "NVRAM - Release 15" ./archives/ue_eth/nvram.Rel15.txt "Built target nvram" ./ue_eth_row8.html + summary_table_row "UE IP - Release 15" ./archives/ue_eth/ue_ip.Rel15.txt "Built target ue_ip" ./ue_eth_row9.html + summary_table_row "USIM - Release 15" ./archives/ue_eth/usim.Rel15.txt "Built target usim" ./ue_eth_row9a.html + summary_table_row "OAI USRP device if - Release 15" ./archives/ue_eth/oai_usrpdevif.Rel15.txt "Built target oai_usrpdevif" ./ue_eth_row9b.html summary_table_footer summary_table_header "OAI Build: 4G LTE basic simulator option" ./archives/basic_sim @@ -676,28 +702,6 @@ function report_build { summary_table_footer fi - summary_table_header "OAI Build: 4G LTE eNB -- ETHERNET transport option" ./archives/enb_eth - summary_table_row "LTE SoftModem - Release 15" ./archives/enb_eth/lte-softmodem.Rel15.txt "Built target lte-softmodem" ./enb_eth_row1.html - summary_table_row "Coding - Release 15" ./archives/enb_eth/coding.Rel15.txt "Built target coding" ./enb_eth_row2.html - summary_table_row "OAI ETHERNET transport - Release 15" ./archives/enb_eth/oai_eth_transpro.Rel15.txt "Built target oai_eth_transpro" ./enb_eth_row3.html - summary_table_row "Parameters Lib Config - Release 15" ./archives/enb_eth/params_libconfig.Rel15.txt "Built target params_libconfig" ./enb_eth_row4.html - summary_table_row "RF Simulator - Release 15" ./archives/enb_eth/rfsimulator.Rel15.txt "Built target rfsimulator" ./enb_eth_row5.html - summary_table_row "TCP OAI Bridge - Release 15" ./archives/enb_eth/tcp_bridge_oai.Rel15.txt "Built target tcp_bridge_oai" ./enb_eth_row6.html - summary_table_footer - - summary_table_header "OAI Build: 4G LTE UE -- ETHERNET transport option" ./archives/ue_eth - summary_table_row "LTE UE SoftModem - Release 15" ./archives/ue_eth/lte-uesoftmodem.Rel15.txt "Built target lte-uesoftmodem" ./ue_eth_row1.html - summary_table_row "Coding - Release 15" ./archives/ue_eth/coding.Rel15.txt "Built target coding" ./ue_eth_row2.html - summary_table_row "OAI ETHERNET transport - Release 15" ./archives/ue_eth/oai_eth_transpro.Rel15.txt "Built target oai_eth_transpro" ./ue_eth_row3.html - summary_table_row "Parameters Lib Config - Release 15" ./archives/ue_eth/params_libconfig.Rel15.txt "Built target params_libconfig" ./ue_eth_row4.html - summary_table_row "RF Simulator - Release 15" ./archives/ue_eth/rfsimulator.Rel15.txt "Built target rfsimulator" ./ue_eth_row5.html - summary_table_row "TCP OAI Bridge - Release 15" ./archives/ue_eth/tcp_bridge_oai.Rel15.txt "Built target tcp_bridge_oai" ./ue_eth_row6.html - summary_table_row "Conf 2 UE Data - Release 15" ./archives/ue_eth/conf2uedata.Rel15.txt "Built target conf2uedata" ./ue_eth_row7.html - summary_table_row "NVRAM - Release 15" ./archives/ue_eth/nvram.Rel15.txt "Built target nvram" ./ue_eth_row8.html - summary_table_row "UE IP - Release 15" ./archives/ue_eth/ue_ip.Rel15.txt "Built target ue_ip" ./ue_eth_row9.html - summary_table_row "USIM - Release 15" ./archives/ue_eth/usim.Rel15.txt "Built target usim" ./ue_eth_row9a.html - summary_table_footer - if [ -e ./archives/red_hat ] then echo "

Red Hat Enterprise Linux Server release 7.6) -- Summary

" >> ./build_results.html @@ -714,9 +718,23 @@ function report_build { echo " " >> ./build_results.html echo "
" >> ./build_results.html - if [ -f ./enb_usrp_row1.html ] || [ -f ./enb_usrp_row2.html ] || [ -f ./enb_usrp_row3.html ] || [ -f ./enb_usrp_row4.html ] +# if [ -f ./enb_usrp_row1.html ] || [ -f ./enb_usrp_row2.html ] || [ -f ./enb_usrp_row3.html ] || [ -f ./enb_usrp_row4.html ] +# then +# for DETAILS_TABLE in `ls ./enb_usrp_row*.html` +# do +# cat $DETAILS_TABLE >> ./build_results.html +# done +# fi + if [ -f ./enb_eth_row1.html ] || [ -f ./enb_eth_row2.html ] || [ -f ./enb_eth_row3.html ] || [ -f ./enb_eth_row4.html ] || [ -f ./enb_eth_row5.html ] || [ -f ./enb_eth_row6.html ] || [ -f ./enb_eth_row7.html ] || [ -f ./enb_eth_row8.html ] || [ -f ./enb_eth_row9.html ] then - for DETAILS_TABLE in `ls ./enb_usrp_row*.html` + for DETAILS_TABLE in `ls ./enb_eth_row*.html` + do + cat $DETAILS_TABLE >> ./build_results.html + done + fi + if [ -f ./ue_eth_row1.html ] || [ -f ./ue_eth_row2.html ] || [ -f ./ue_eth_row3.html ] || [ -f ./ue_eth_row4.html ] || [ -f ./ue_eth_row5.html ] || [ -f ./ue_eth_row6.html ] || [ -f ./ue_eth_row7.html ] || [ -f ./ue_eth_row8.html ] || [ -f ./ue_eth_row9.html ] || [ -f ./ue_eth_row9a.html ] || [ -f ./ue_eth_row9b.html ] + then + for DETAILS_TABLE in `ls ./ue_eth_row*.html` do cat $DETAILS_TABLE >> ./build_results.html done @@ -749,20 +767,6 @@ function report_build { cat $DETAILS_TABLE >> ./build_results.html done fi - if [ -f ./enb_eth_row1.html ] || [ -f ./enb_eth_row2.html ] || [ -f ./enb_eth_row3.html ] || [ -f ./enb_eth_row4.html ] || [ -f ./enb_eth_row5.html ] || [ -f ./enb_eth_row6.html ] - then - for DETAILS_TABLE in `ls ./enb_eth_row*.html` - do - cat $DETAILS_TABLE >> ./build_results.html - done - fi - if [ -f ./ue_eth_row1.html ] || [ -f ./ue_eth_row2.html ] || [ -f ./ue_eth_row3.html ] || [ -f ./ue_eth_row4.html ] || [ -f ./ue_eth_row5.html ] || [ -f ./ue_eth_row6.html ] - then - for DETAILS_TABLE in `ls ./ue_eth_row*.html` - do - cat $DETAILS_TABLE >> ./build_results.html - done - fi if [ -f ./enb_usrp_rh_row1.html ] || [ -f ./enb_usrp_rh_row2.html ] || [ -f ./enb_usrp_rh_row3.html ] || [ -f ./enb_usrp_rh_row4.html ] then for DETAILS_TABLE in `ls ./enb_usrp_rh_row*.html` diff --git a/ci-scripts/reportTestLocally.sh b/ci-scripts/reportTestLocally.sh index 8562f4b2de..415ded57a4 100755 --- a/ci-scripts/reportTestLocally.sh +++ b/ci-scripts/reportTestLocally.sh @@ -749,7 +749,7 @@ function report_test { echo " " >> ./test_simulator_results.html EPC_CONFIGS=("noS1") - TRANS_MODES=("tdd") + TRANS_MODES=("fdd" "tdd") BW_CASES=(106) for CN_CONFIG in ${EPC_CONFIGS[@]} do diff --git a/ci-scripts/runTestOnVM.sh b/ci-scripts/runTestOnVM.sh index 70eabb7b69..f818685049 100755 --- a/ci-scripts/runTestOnVM.sh +++ b/ci-scripts/runTestOnVM.sh @@ -379,7 +379,7 @@ function check_iperf { local LOC_IS_DL=`echo $LOC_BASE_LOG | grep -c _dl` local LOC_IS_BASIC_SIM=`echo $LOC_BASE_LOG | grep -c basic_sim` local LOC_IS_RF_SIM=`echo $LOC_BASE_LOG | grep -c rf_sim` - local LOC_IS_NR=`echo $LOC_BASE_LOG | grep -c tdd_106prb` + local LOC_IS_NR=`echo $LOC_BASE_LOG | grep -c _106prb` if [ -f ${LOC_BASE_LOG}_client.txt ] then local FILE_COMPLETE=`egrep -c "Server Report" ${LOC_BASE_LOG}_client.txt` @@ -2189,39 +2189,50 @@ function run_test_on_vm { if [[ "$RUN_OPTIONS" == "complex" ]] && [[ $VM_NAME =~ .*-rf-sim.* ]] then - CN_CONFIG="noS1" - CONF_FILE=gnb.band78.tm1.106PRB.usrpn300.conf - S1_NOS1_CFG=0 - PRB=106 - FREQUENCY=3510 - if [ ! -d $ARCHIVES_LOC ] then mkdir --parents $ARCHIVES_LOC fi - local try_cnt=0 - NR_STATUS=0 + CN_CONFIG="noS1" + S1_NOS1_CFG=0 ######### start of RA TEST loop - while [ $try_cnt -lt 5 ] #5 because it hardly succeed within CI + # for the moment only TDD + TRANS_MODES=("tdd") + for TMODE in ${TRANS_MODES[@]} do + if [[ $TMODE =~ .*fdd.* ]] + then + CONF_FILE=gnb.band66.tm1.106PRB.usrpn300.conf + PRB=106 + FREQUENCY=37000 + else + CONF_FILE=gnb.band78.tm1.106PRB.usrpn300.conf + PRB=106 + FREQUENCY=3510 + fi + local try_cnt=0 + NR_STATUS=0 + while [ $try_cnt -lt 5 ] #5 because it hardly succeed within CI + + do SYNC_STATUS=0 RA_STATUS=0 - rm -f $ARCHIVES_LOC/tdd_${PRB}prb_${CN_CONFIG}*ra_test.log + rm -f $ARCHIVES_LOC/${TMODE}_${PRB}prb_${CN_CONFIG}*ra_test.log echo "############################################################" - echo "${CN_CONFIG} : Starting the gNB" + echo "${CN_CONFIG} : Starting the gNB in ${TMODE} mode (RA TEST)" echo "############################################################" - CURRENT_GNB_LOG_FILE=tdd_${PRB}prb_${CN_CONFIG}_gnb_ra_test.log + CURRENT_GNB_LOG_FILE=${TMODE}_${PRB}prb_${CN_CONFIG}_gnb_ra_test.log #last argument = 1 is to enable --do-ra for RA test start_rf_sim_gnb $GNB_VM_CMDS "$GNB_VM_IP_ADDR" $CURRENT_GNB_LOG_FILE $PRB $CONF_FILE $S1_NOS1_CFG 1 echo "############################################################" - echo "${CN_CONFIG} : Starting the NR-UE" + echo "${CN_CONFIG} : Starting the NR-UE in ${TMODE} mode (RA TEST)" echo "############################################################" - CURRENT_NR_UE_LOG_FILE=tdd_${PRB}prb_${CN_CONFIG}_ue_ra_test.log + CURRENT_NR_UE_LOG_FILE=${TMODE}_${PRB}prb_${CN_CONFIG}_ue_ra_test.log #last argument = 1 is to enable --do-ra for RA test start_rf_sim_nr_ue $NR_UE_VM_CMDS $NR_UE_VM_IP_ADDR $GNB_VM_IP_ADDR $CURRENT_NR_UE_LOG_FILE $PRB $FREQUENCY $S1_NOS1_CFG 1 if [ $NR_UE_SYNC -eq 0 ] @@ -2260,35 +2271,47 @@ function run_test_on_vm { else try_cnt=$((try_cnt+10)) fi + done done ########### end RA test sleep 30 - ######### start of PHY TEST loop - try_cnt=0 - while [ $try_cnt -lt 4 ] + SYNC_STATUS=0 + PING_STATUS=0 + IPERF_STATUS=0 + TRANS_MODES=("fdd tdd") + for TMODE in ${TRANS_MODES[@]} do + if [[ $TMODE =~ .*fdd.* ]] + then + CONF_FILE=gnb.band66.tm1.106PRB.usrpn300.conf + PRB=106 + FREQUENCY=37000 + else + CONF_FILE=gnb.band78.tm1.106PRB.usrpn300.conf + PRB=106 + FREQUENCY=3510 + fi - - SYNC_STATUS=0 - PING_STATUS=0 - IPERF_STATUS=0 - rm -f $ARCHIVES_LOC/tdd_${PRB}prb_${CN_CONFIG}_gnb.log $ARCHIVES_LOC/tdd_${PRB}prb_${CN_CONFIG}_ue.log - rm -f $ARCHIVES_LOC/tdd_${PRB}prb_${CN_CONFIG}_ping_gnb_from_nrue.log $ARCHIVES_LOC/tdd_${PRB}prb_${CN_CONFIG}_ping_from_gnb_nrue.log - rm -f $ARCHIVES_LOC/tdd_${PRB}prb_${CN_CONFIG}_iperf_dl*txt $ARCHIVES_LOC/tdd_${PRB}prb_${CN_CONFIG}_iperf_ul*txt + try_cnt=0 + while [ $try_cnt -lt 4 ] + do + rm -f $ARCHIVES_LOC/${TMODE}_${PRB}prb_${CN_CONFIG}_gnb.log $ARCHIVES_LOC/${TMODE}_${PRB}prb_${CN_CONFIG}_ue.log + rm -f $ARCHIVES_LOC/${TMODE}_${PRB}prb_${CN_CONFIG}_ping_gnb_from_nrue.log $ARCHIVES_LOC/${TMODE}_${PRB}prb_${CN_CONFIG}_ping_from_gnb_nrue.log + rm -f $ARCHIVES_LOC/${TMODE}_${PRB}prb_${CN_CONFIG}_iperf_dl*txt $ARCHIVES_LOC/${TMODE}_${PRB}prb_${CN_CONFIG}_iperf_ul*txt echo "############################################################" - echo "${CN_CONFIG} : Starting the gNB" + echo "${CN_CONFIG} : Starting the gNB in ${TMODE} mode (PHY TEST)" echo "############################################################" - CURRENT_GNB_LOG_FILE=tdd_${PRB}prb_${CN_CONFIG}_gnb.log + CURRENT_GNB_LOG_FILE=${TMODE}_${PRB}prb_${CN_CONFIG}_gnb.log start_rf_sim_gnb $GNB_VM_CMDS "$GNB_VM_IP_ADDR" $CURRENT_GNB_LOG_FILE $PRB $CONF_FILE $S1_NOS1_CFG 0 echo "############################################################" - echo "${CN_CONFIG} : Starting the NR-UE" + echo "${CN_CONFIG} : Starting the NR-UE in ${TMODE} mode (PHY TEST)" echo "############################################################" - CURRENT_NR_UE_LOG_FILE=tdd_${PRB}prb_${CN_CONFIG}_ue.log + CURRENT_NR_UE_LOG_FILE=${TMODE}_${PRB}prb_${CN_CONFIG}_ue.log start_rf_sim_nr_ue $NR_UE_VM_CMDS $NR_UE_VM_IP_ADDR $GNB_VM_IP_ADDR $CURRENT_NR_UE_LOG_FILE $PRB $FREQUENCY $S1_NOS1_CFG 0 if [ $NR_UE_SYNC -eq 0 ] then @@ -2306,7 +2329,7 @@ function run_test_on_vm { echo "${CN_CONFIG} : Pinging the gNB from NR-UE" echo "############################################################" get_enb_noS1_ip_addr $GNB_VM_CMDS $GNB_VM_IP_ADDR - PING_LOG_FILE=tdd_${PRB}prb_${CN_CONFIG}_ping_gnb_from_nrue.log + PING_LOG_FILE=${TMODE}_${PRB}prb_${CN_CONFIG}_ping_gnb_from_nrue.log ping_epc_ip_addr $NR_UE_VM_CMDS $NR_UE_VM_IP_ADDR $ENB_IP_ADDR $PING_LOG_FILE 1 0 scp -o StrictHostKeyChecking=no ubuntu@$NR_UE_VM_IP_ADDR:/home/ubuntu/$PING_LOG_FILE $ARCHIVES_LOC check_ping_result $ARCHIVES_LOC/$PING_LOG_FILE 20 @@ -2315,7 +2338,7 @@ function run_test_on_vm { echo "${CN_CONFIG} : Pinging the NR-UE from gNB" echo "############################################################" get_ue_ip_addr $NR_UE_VM_CMDS $NR_UE_VM_IP_ADDR 1 - PING_LOG_FILE=tdd_${PRB}prb_${CN_CONFIG}_ping_from_gnb_nrue.log + PING_LOG_FILE=${TMODE}_${PRB}prb_${CN_CONFIG}_ping_from_gnb_nrue.log ping_enb_ip_addr $GNB_VM_CMDS $GNB_VM_IP_ADDR $UE_IP_ADDR $PING_LOG_FILE 0 scp -o StrictHostKeyChecking=no ubuntu@$GNB_VM_IP_ADDR:/home/ubuntu/$PING_LOG_FILE $ARCHIVES_LOC check_ping_result $ARCHIVES_LOC/$PING_LOG_FILE 20 @@ -2324,7 +2347,7 @@ function run_test_on_vm { echo "${CN_CONFIG} : iperf DL -- NR-UE is server and gNB is client" echo "############################################################" THROUGHPUT="30K" - CURR_IPERF_LOG_BASE=tdd_${PRB}prb_${CN_CONFIG}_iperf_dl + CURR_IPERF_LOG_BASE=${TMODE}_${PRB}prb_${CN_CONFIG}_iperf_dl get_enb_noS1_ip_addr $GNB_VM_CMDS $GNB_VM_IP_ADDR get_ue_ip_addr $NR_UE_VM_CMDS $NR_UE_VM_IP_ADDR 1 generic_iperf $NR_UE_VM_CMDS $NR_UE_VM_IP_ADDR $UE_IP_ADDR $GNB_VM_CMDS $GNB_VM_IP_ADDR $ENB_IP_ADDR $THROUGHPUT $CURR_IPERF_LOG_BASE 1 0 @@ -2346,7 +2369,7 @@ function run_test_on_vm { echo "${CN_CONFIG} : iperf UL -- gNB is server and NR-UE is client" echo "############################################################" THROUGHPUT="30K" - CURR_IPERF_LOG_BASE=tdd_${PRB}prb_${CN_CONFIG}_iperf_ul + CURR_IPERF_LOG_BASE=${TMODE}_${PRB}prb_${CN_CONFIG}_iperf_ul get_enb_noS1_ip_addr $GNB_VM_CMDS $GNB_VM_IP_ADDR get_ue_ip_addr $NR_UE_VM_CMDS $NR_UE_VM_IP_ADDR 1 generic_iperf $GNB_VM_CMDS $GNB_VM_IP_ADDR $ENB_IP_ADDR $NR_UE_VM_CMDS $NR_UE_VM_IP_ADDR $UE_IP_ADDR $THROUGHPUT $CURR_IPERF_LOG_BASE 1 0 @@ -2368,6 +2391,7 @@ function run_test_on_vm { else try_cnt=$((try_cnt+10)) fi + done done ######### end of loop full_l2_sim_destroy diff --git a/ci-scripts/waitBuildOnVM.sh b/ci-scripts/waitBuildOnVM.sh index f066dacd81..ff2129a187 100755 --- a/ci-scripts/waitBuildOnVM.sh +++ b/ci-scripts/waitBuildOnVM.sh @@ -47,6 +47,12 @@ function wait_on_vm_build { echo "ARCHIVES_LOC = $ARCHIVES_LOC" echo "BUILD_OPTIONS = $BUILD_OPTIONS" + if [[ "$VM_NAME" == *"-enb-usrp"* ]] + then + echo "This VM type is no longer supported in the pipeline framework" + return + fi + IS_VM_ALIVE=`uvt-kvm list | grep -c $VM_NAME` if [ $IS_VM_ALIVE -eq 0 ] @@ -84,6 +90,12 @@ function wait_on_vm_build { } function check_on_vm_build { + if [[ "$VM_NAME" == *"-enb-usrp"* ]] + then + echo "This VM type is no longer supported in the pipeline framework" + return + fi + echo "############################################################" echo "Creating a tmp folder to store results and artifacts" echo "############################################################" diff --git a/ci-scripts/xml_files/fr1_multi_node_test.xml b/ci-scripts/xml_files/benetel_multi_node_build.xml similarity index 50% rename from ci-scripts/xml_files/fr1_multi_node_test.xml rename to ci-scripts/xml_files/benetel_multi_node_build.xml index 8c56f0bcec..5ac28951b4 100644 --- a/ci-scripts/xml_files/fr1_multi_node_test.xml +++ b/ci-scripts/xml_files/benetel_multi_node_build.xml @@ -21,57 +21,34 @@ --> - test-fr1-tm1 - Test-FR1-TM1 - tasks - 1 + build-tab + Build + wrench - 030000 - 040000 - 000001 - 070001 - 070000 + 000001 000002 - - - - - Initialize_eNB - Initialize eNB - -O ci-scripts/conf_files/enb.band7.tm1.fr1.25PRB.usrpb210.conf - 0 - 0 - lte - - - - Initialize_eNB - Initialize gNB (3/4 sampling rate) - -O ci-scripts/conf_files/gnb.band78.tm1.fr1.106PRB.usrpb210.conf -E - 1 - 1 - nr - + - IdleSleep - Sleep - 30 - - - - Terminate_eNB - Terminate eNB + Build_eNB + Build eNB + --eNB -t benetel4g -w None + True 0 0 - - Terminate_eNB - Terminate gNB + + + Build_eNB + Build gNB + --gNB -t benetel5g -w None + True 1 1 - + + + diff --git a/ci-scripts/xml_files/benetel_nsa_base.xml b/ci-scripts/xml_files/benetel_nsa_base.xml new file mode 100644 index 0000000000..0aed28dffa --- /dev/null +++ b/ci-scripts/xml_files/benetel_nsa_base.xml @@ -0,0 +1,162 @@ + + + TEST-FR1-TM1 + FR1 + tasks + + 010000 + 030000 + 040000 + 010001 + 000001 + 050000 + 050001 + 000001 + 060000 + 060001 + 000001 + 070000 + 070001 + 010002 + 000001 + 080001 + 080000 + 010003 + + + + + Initialize_UE + Initialize UE + + + + Terminate_UE + Terminate UE + + + + Attach_UE + Attach UE + + + + Detach_UE + Detach UE + + + + + Initialize_eNB + Initialize eNB + -O ci-scripts/conf_files/benetel-4g.conf + 0 + 0 + lte + + + + + Initialize_eNB + Initialize gNB + -O ci-scripts/conf_files/benetel-5g.conf + 1 + 1 + nr + + + + IdleSleep + Sleep + 20 + + + + Ping + Ping: 20pings in 20sec + -c 20 + 50 + + + + Ping + Ping: 100pings in 20sec + -c 100 -i 0.2 + 50 + + + + + Iperf + iperf (DL/2.5Mbps/UDP)(60 sec)(single-ue profile) + -u -b 2.5M -t 60 -i 1 + 50 + single-ue + + + + Iperf + iperf (UL/1.5Mbps/UDP)(60 sec)(single-ue profile) + -u -b 1.5M -t 60 -i 1 -R + 50 + single-ue + + + + + Iperf + iperf (DL/20Mbps/UDP)(20 sec)(single-ue profile) + -u -b 20M -t 20 -i 1 + 50 + single-ue + + + + Iperf + iperf (UL/3Mbps/UDP)(20 sec)(single-ue profile) + -u -b 3M -t 20 -i 1 -R + 50 + single-ue + + + + + + Terminate_eNB + Terminate eNB + 0 + 0 + lte + + + + Terminate_eNB + Terminate gNB + 1 + 1 + nr + + + + diff --git a/ci-scripts/xml_files/fr1_image_build.xml b/ci-scripts/xml_files/container_image_build.xml similarity index 93% rename from ci-scripts/xml_files/fr1_image_build.xml rename to ci-scripts/xml_files/container_image_build.xml index 9dd386b646..430729c49c 100644 --- a/ci-scripts/xml_files/fr1_image_build.xml +++ b/ci-scripts/xml_files/container_image_build.xml @@ -22,7 +22,7 @@ --> build-tab - Build + Build Container Images wrench 000001 @@ -31,7 +31,7 @@ Build_Image - Build eNB Image + Build all Images all 0 0 diff --git a/ci-scripts/xml_files/fr1_multi_node_build.xml b/ci-scripts/xml_files/fr1_multi_node_build.xml index 7b4eacef3a..57c4685341 100644 --- a/ci-scripts/xml_files/fr1_multi_node_build.xml +++ b/ci-scripts/xml_files/fr1_multi_node_build.xml @@ -37,6 +37,7 @@ 0 0 True + True @@ -53,6 +54,7 @@ 1 1 True + True diff --git a/ci-scripts/xml_files/fr1_ran_ue_iperf.xml b/ci-scripts/xml_files/fr1_nsa_base.xml similarity index 80% rename from ci-scripts/xml_files/fr1_ran_ue_iperf.xml rename to ci-scripts/xml_files/fr1_nsa_base.xml index 8ead3afc62..96bdc79f0f 100644 --- a/ci-scripts/xml_files/fr1_ran_ue_iperf.xml +++ b/ci-scripts/xml_files/fr1_nsa_base.xml @@ -21,8 +21,8 @@ --> - TEST-FR1-TM1 - FR1 + TEST-NSA-FR1-TM1 + NSA FULL tasks 010000 @@ -31,14 +31,17 @@ 010001 000001 050000 + 050001 000001 060000 060001 000001 + 070000 + 070001 010002 000001 - 070001 - 070000 + 080001 + 080000 010003 @@ -96,6 +99,13 @@ 50 + + Ping + Ping: 100pings in 20sec + -c 100 -i 0.2 + 50 + + Iperf @@ -113,7 +123,26 @@ single-ue + + Iperf + iperf (DL/20Mbps/UDP)(20 sec)(single-ue profile) + -u -b 20M -t 20 -i 1 + 50 + single-ue + + + + Iperf + iperf (UL/3Mbps/UDP)(20 sec)(single-ue profile) + -u -b 3M -t 20 -i 1 -R + 50 + single-ue + + + + + Terminate_eNB Terminate eNB 0 @@ -121,7 +150,7 @@ lte - + Terminate_eNB Terminate gNB 1 diff --git a/ci-scripts/xml_files/fr1_ran_ue_base.xml b/ci-scripts/xml_files/fr1_nsa_base_ref.xml similarity index 80% rename from ci-scripts/xml_files/fr1_ran_ue_base.xml rename to ci-scripts/xml_files/fr1_nsa_base_ref.xml index 847967f81e..fd47db10b2 100644 --- a/ci-scripts/xml_files/fr1_ran_ue_base.xml +++ b/ci-scripts/xml_files/fr1_nsa_base_ref.xml @@ -21,8 +21,8 @@ --> - TEST-FR1-TM1 - FR1 + TEST-NSA-FR1-TM1 + NSA FULL tasks 010000 @@ -32,16 +32,15 @@ 000001 050000 050001 - 050002 - 050002 000001 060000 060001 000001 + 070000 010002 000001 - 070001 - 070000 + 080001 + 080000 010003 @@ -100,13 +99,6 @@ - Ping - Ping: 5pings in 1sec - -c 5 -i 0.2 - 50 - - - Ping Ping: 100pings in 20sec -c 100 -i 0.2 @@ -116,21 +108,40 @@ Iperf - iperf (DL/1Mbps/UDP)(30 sec)(single-ue profile) - -u -b 1M -t 30 -i 1 + iperf (DL/3Mbps/UDP)(20 sec)(single-ue profile) + -u -b 3M -t 20 -i 1 50 single-ue Iperf - iperf (UL/1Mbps/UDP)(30 sec)(single-ue profile) - -u -b 1M -t 30 -i 1 -R + iperf (UL/1Mbps/UDP)(20 sec)(single-ue profile) + -u -b 1M -t 20 -i 1 -R 50 single-ue + + Iperf + iperf (DL/20Mbps/UDP)(20 sec)(single-ue profile) + -u -b 20M -t 20 -i 1 + 50 + single-ue + + + + Iperf + iperf (UL/3Mbps/UDP)(20 sec)(single-ue profile) + -u -b 3M -t 20 -i 1 -R + 50 + single-ue + + + + + Terminate_eNB Terminate eNB 0 @@ -138,7 +149,7 @@ lte - + Terminate_eNB Terminate gNB 1 diff --git a/cmake_targets/CMakeLists.txt b/cmake_targets/CMakeLists.txt index e11c850b8e..626d938625 100644 --- a/cmake_targets/CMakeLists.txt +++ b/cmake_targets/CMakeLists.txt @@ -926,6 +926,9 @@ set_target_properties(tcp_bridge_oai PROPERTIES COMPILE_FLAGS "-fvisibility=hidd # Benetel 4G library ###################################################################### + +include_directories ("/usr/include/dpdk") + set(HWLIB_BENETEL_4G_SOURCE ${OPENAIR_TARGETS}/ARCH/ETHERNET/benetel/4g/benetel.c ${OPENAIR_TARGETS}/ARCH/ETHERNET/benetel/4g/shared_buffers.c @@ -1967,7 +1970,8 @@ set(NR_PDCP_SRC ${OPENAIR2_DIR}/LAYER2/nr_pdcp/nr_pdcp_oai_api.c ${OPENAIR2_DIR}/LAYER2/nr_pdcp/nr_pdcp_ue_manager.c ${OPENAIR2_DIR}/LAYER2/nr_pdcp/nr_pdcp_entity.c - ${OPENAIR2_DIR}/LAYER2/nr_pdcp/nr_pdcp_entity_drb_am.c + ${OPENAIR2_DIR}/LAYER2/nr_pdcp/nr_pdcp_sdu.c + ${OPENAIR2_DIR}/LAYER2/nr_pdcp/nr_pdcp_timer_thread.c ${OPENAIR2_DIR}/LAYER2/nr_pdcp/nr_pdcp_security_nea2.c ${OPENAIR2_DIR}/LAYER2/nr_pdcp/asn1_utils.c ) @@ -3141,7 +3145,7 @@ target_link_libraries (nr-uesoftmodem RRC_LIB NR_RRC_LIB NGAP_LIB NGAP_GNB SECU_CN SECU_OSA UTIL HASHTABLE SCTP_CLIENT UDP SCHED_RU_LIB SCHED_UE_LIB SCHED_NR_UE_LIB PHY_COMMON PHY_NR_COMMON PHY_UE PHY_NR_UE PHY_RU LFDS NR_L2_UE L2_UE_LTE_NR MAC_NR_COMMON NFAPI_COMMON_LIB NFAPI_LIB NFAPI_PNF_LIB NFAPI_USER_LIB MISC_NFAPI_NR_LIB S1AP_LIB S1AP_ENB - ${MSC_LIB} ${RAL_LIB} ${NAS_UE_LIB} ${ITTI_LIB} ${FLPT_MSG_LIB} ${ASYNC_IF_LIB} LFDS7 ${ATLAS_LIBRARIES} + ${MSC_LIB} ${RAL_LIB} ${NAS_UE_LIB} ${ITTI_LIB} ${FLPT_MSG_LIB} ${ASYNC_IF_LIB} LFDS7 ${ATLAS_LIBRARIES} NFAPI_USER_LIB S1AP_LIB S1AP_ENB ${MSC_LIB} ${RAL_LIB} ${NAS_UE_LIB} ${ITTI_LIB} ${FLPT_MSG_LIB} ${ASYNC_IF_LIB} LFDS7 ${ATLAS_LIBRARIES} LIB_5GNAS_GNB -Wl,--end-group z dl) diff --git a/cmake_targets/autotests/test_case_list.xml b/cmake_targets/autotests/test_case_list.xml index 089d0503fd..016c76dc06 100644 --- a/cmake_targets/autotests/test_case_list.xml +++ b/cmake_targets/autotests/test_case_list.xml @@ -1294,7 +1294,8 @@ (Test10: SC-FDMA, 75 PRBs), (Test11: SC-FDMA, 216 PRBs), (Test12: SC-FDMA, 273 PRBs), - (Test13: SC-FDMA, 3 DMRS) + (Test13: SC-FDMA, 3 DMRS), + (Test14: MCS 16 50 PRBs 2 RX_Antenna) $OPENAIR_DIR/cmake_targets/build_oai --phy_simulators -c @@ -1313,9 +1314,10 @@ -n100 -s2 -Z -r75 -n100 -s2 -Z -r216 -R217 -n100 -s2 -Z -r270 -R273 - -n100 -s2 -Z -U 2 0 2 + -n100 -s2 -Z -U 2 0 2 + -n100 -m16 -s10 -z2 - nr_ulsim.test1 nr_ulsim.test2 nr_ulsim.test3 nr_ulsim.test4 nr_ulsim.test5 nr_ulsim.test6 nr_ulsim.test7 nr_ulsim.test8 nr_ulsim.test9 nr_ulsim.test10 nr_ulsim.test11 nr_ulsim.test12 nr_ulsim.test13 + nr_ulsim.test1 nr_ulsim.test2 nr_ulsim.test3 nr_ulsim.test4 nr_ulsim.test5 nr_ulsim.test6 nr_ulsim.test7 nr_ulsim.test8 nr_ulsim.test9 nr_ulsim.test10 nr_ulsim.test11 nr_ulsim.test12 nr_ulsim.test13 nr_ulsim.test14 PUSCH test OK segmentation fault|assertion|exiting|fatal 3 diff --git a/cmake_targets/build_oai b/cmake_targets/build_oai index 960b241047..dba6d7da6d 100755 --- a/cmake_targets/build_oai +++ b/cmake_targets/build_oai @@ -48,8 +48,9 @@ DEADLINE_SCHEDULER_FLAG_USER="" CPU_AFFINITY_FLAG_USER="False" #Only valid when low-latency flag is set to False REL="Rel15" HW="None" -TP="None" +TP="Ethernet" EPC=0 +VERBOSE_CI=0 VERBOSE_COMPILE=0 CFLAGS_PROCESSOR_USER="" RUN_GROUP=0 @@ -289,6 +290,9 @@ function main() { esac echo_info "Setting hardware to: $HW" shift 2;; + -t | --transport) + TP=$2 + shift 2;; -P | --phy_simulators) SIMUS_PHY=1 echo_info "Will compile dlsim, ulsim, ..." @@ -324,6 +328,10 @@ function main() { HWLAT_TEST=1 echo_info "Will compile hw latency test program" shift;; + --verbose-ci) + VERBOSE_CI=1 + echo_info "Will compile with verbose instructions in CI Docker env" + shift;; --verbose-compile) VERBOSE_COMPILE=1 echo_info "Will compile with verbose instructions" @@ -936,12 +944,30 @@ function main() { echo_info "Building transport protocol libraries" rm -f liboai_transpro.so rm -f $dbin/liboai_transpro.so - compilations \ - $build_dir oai_eth_transpro \ - liboai_eth_transpro.so $dbin/liboai_eth_transpro.so.$REL - ln -sf liboai_eth_transpro.so liboai_transpro.so - ln -sf $dbin/liboai_eth_transpro.so.$REL $dbin/liboai_transpro.so - echo_info "liboai_transpro.so is linked to ETHERNET transport" + if [ "$TP" == "Ethernet" ]; then + compilations \ + $build_dir oai_eth_transpro \ + liboai_eth_transpro.so $dbin/liboai_eth_transpro.so.$REL + ln -sf liboai_eth_transpro.so liboai_transpro.so + ln -sf $dbin/liboai_eth_transpro.so.$REL $dbin/liboai_transpro.so + echo_info "liboai_transpro.so is linked to ETHERNET transport" + fi + if [ "$TP" == "benetel4g" ]; then + compilations \ + $build_dir benetel_4g \ + libbenetel_4g.so $dbin/libbenetel_4g.$REL + ln -sf libbenetel_4g.so liboai_transpro.so + ln -sf $dbin/libbenetel_4g.so.$REL $dbin/liboai_transpro.so + echo_info "liboai_transpro.so is linked to BENETEL4G transport" + fi + if [ "$TP" == "benetel5g" ]; then + compilations \ + $build_dir benetel_5g \ + libbenetel_5g.so $dbin/libbenetel_5g.$REL + ln -sf libbenetel_5g.so liboai_transpro.so + ln -sf $dbin/libbenetel_5g.so.$REL $dbin/liboai_transpro.so + echo_info "liboai_transpro.so is linked to BENETEL4G transport" + fi fi fi diff --git a/cmake_targets/tools/build_helper b/cmake_targets/tools/build_helper index 674d4a0cac..9b8363fc2b 100755 --- a/cmake_targets/tools/build_helper +++ b/cmake_targets/tools/build_helper @@ -41,7 +41,7 @@ KERNEL_VERSION=$(uname -r | cut -d '.' -f1) KERNEL_MAJOR=$(uname -r | cut -d '.' -f2) #check if we run inside a container -IS_CONTAINER=`egrep -c "docker|podman|kubepods" /proc/self/cgroup || true` +IS_CONTAINER=`egrep -c "docker|podman|kubepods|libpod|buildah" /proc/self/cgroup || true` #sudo is not needed when we are root if [ "$UID" = 0 ] then @@ -221,6 +221,11 @@ compilations() { ret=$? } > $dlog/$2.$REL.txt 2>&1 set -e + if [ "$VERBOSE_CI" == "1" ]; then + echo_info "====== Start of log for $2.$REL.txt ======" + cat $dlog/$2.$REL.txt + echo_info "====== End of log for $2.$REL.txt ======" + fi if [[ $ret -ne 0 ]]; then check_warnings "$dlog/$2.$REL.txt" check_errors "$dlog/$2.$REL.txt" @@ -273,6 +278,10 @@ install_protobuf_from_source(){ make -j`nproc` $SUDO make install $SUDO ldconfig + if [[ -v CI_ENV ]]; then + cd /tmp + $SUDO rm -rf protobuf* + fi ) >& $protobuf_install_log } @@ -295,6 +304,10 @@ install_protobuf_c_from_source(){ make -j`nproc` $SUDO make install $SUDO ldconfig + if [[ -v CI_ENV ]]; then + cd /tmp + $SUDO rm -rf protobuf* + fi ) >& $protobuf_c_install_log } @@ -351,10 +364,10 @@ check_install_usrp_uhd_driver(){ elif [[ "$OS_BASEDISTRO" == "fedora" ]]; then if [ $IS_CONTAINER -eq 0 ] then - $SUDO $INSTALLER -y install python boost libusb-devel libusbx-devel boost-devel python-mako python-docutils cmake + $SUDO $INSTALLER -y install python boost libusb-devel libusbx-devel boost-devel python-mako python-docutils $CMAKE $SUDO -H pip install requests else - $SUDO $INSTALLER -y install boost boost-devel cmake3 + $SUDO $INSTALLER -y install boost boost-devel $CMAKE $SUDO pip3 install mako requests fi if [[ "$OS_DISTRO" == "rhel" ]] || [[ "$OS_DISTRO" == "centos" ]]; then @@ -480,7 +493,7 @@ install_soapy_from_source(){ #git checkout tags/release_003_010_001_001 mkdir -p build cd build - cmake ../ + $CMAKE ../ echo "Compiling SoapyRemote" make -j`nproc` $SUDO make install @@ -499,7 +512,7 @@ install_soapy_iris_from_source(){ cd sklk-soapyiris mkdir -p build cd build - cmake ../ + $CMAKE ../ echo "Compiling SoapyIris" make -j`nproc` $SUDO make install @@ -676,7 +689,7 @@ check_install_oai_software() { automake \ bison \ build-essential \ - cmake \ + $CMAKE \ cmake-curses-gui \ ninja-build \ doxygen \ @@ -831,6 +844,9 @@ install_asn1c_from_source(){ $SUDO make install cd - $SUDO ldconfig + if [[ -v CI_ENV ]]; then + $SUDO rm -rf /tmp/asn1c + fi ) > $asn1_install_log 2>&1 } diff --git a/common/utils/LOG/log.c b/common/utils/LOG/log.c index 9fd67a6dbb..4e6ec9d3db 100644 --- a/common/utils/LOG/log.c +++ b/common/utils/LOG/log.c @@ -88,7 +88,8 @@ int write_file_matlab(const char *fname, void *data, int length, int dec, - unsigned int format) + unsigned int format, + int multiVec) { FILE *fp=NULL; int i; @@ -100,8 +101,7 @@ int write_file_matlab(const char *fname, //printf("Writing %d elements of type %d to %s\n",length,format,fname); - - if (format == 10 || format ==11 || format == 12 || format == 13 || format == 14) { + if (format == 10 || format ==11 || format == 12 || format == 13 || format == 14 || multiVec) { fp = fopen(fname,"a+"); } else if (format != 10 && format !=11 && format != 12 && format != 13 && format != 14) { fp = fopen(fname,"w+"); @@ -137,8 +137,7 @@ int write_file_matlab(const char *fname, return(0); } - - if (format != 10 && format !=11 && format != 12 && format != 13 && format != 14) + if ((format != 10 && format !=11 && format != 12 && format != 13 && format != 14) || multiVec) fprintf(fp,"%s = [",vname); switch (format) { @@ -247,7 +246,7 @@ int write_file_matlab(const char *fname, AssertFatal(false, "unknown dump format: %d\n", format); } - if (format != 10 && format !=11 && format !=12 && format != 13 && format != 15) { + if ((format != 10 && format !=11 && format !=12 && format != 13 && format != 15) || multiVec) { fprintf(fp,"];\n"); fclose(fp); return(0); diff --git a/common/utils/LOG/log.h b/common/utils/LOG/log.h index 49c6bdfd4c..0cbae7ae2c 100644 --- a/common/utils/LOG/log.h +++ b/common/utils/LOG/log.h @@ -335,6 +335,7 @@ typedef struct { @param length length of data vector to output @param dec decimation level @param format data format (0 = real 16-bit, 1 = complex 16-bit,2 real 32-bit, 3 complex 32-bit,4 = real 8-bit, 5 = complex 8-bit) +@param multiVec create new file or append to existing (useful for writing multiple vectors to same file. Just call the function multiple times with same file name and with this parameter set to 1) */ #define MATLAB_RAW (1<<31) #define MATLAB_SHORT 0 @@ -354,7 +355,7 @@ typedef struct { #define MATLAB_CSHORT_BRACKET2 14 #define MATLAB_CSHORT_BRACKET3 15 -int32_t write_file_matlab(const char *fname, const char *vname, void *data, int length, int dec, unsigned int format); +int32_t write_file_matlab(const char *fname, const char *vname, void *data, int length, int dec, unsigned int format, int multiVec); /*----------------macro definitions for reading log configuration from the config module */ #define CONFIG_STRING_LOG_PREFIX "log_config" @@ -414,7 +415,7 @@ int32_t write_file_matlab(const char *fname, const char *vname, void *data, int /* bitmask dependent macros, to generate debug file such as matlab file or message dump */ # define LOG_DUMPFLAG(D) (g_log->dump_mask & D) -# define LOG_M(file, vector, data, len, dec, format) do { write_file_matlab(file, vector, data, len, dec, format);} while(0)/* */ +# define LOG_M(file, vector, data, len, dec, format) do { write_file_matlab(file, vector, data, len, dec, format, 0);} while(0)/* */ /* define variable only used in LOG macro's */ # define LOG_VAR(A,B) A B # else /* T_TRACER: remove all debugging and tracing messages, except errors */ @@ -431,7 +432,7 @@ int32_t write_file_matlab(const char *fname, const char *vname, void *data, int # define LOG_DUMPFLAG(D) (g_log->debug_mask & D) # define LOG_DUMPMSG(c, f, b, s, x...) do { if(g_log->dump_mask & f) log_dump(c, b, s, LOG_DUMP_CHAR, x) ;} while (0) /* */ -# define LOG_M(file, vector, data, len, dec, format) do { write_file_matlab(file, vector, data, len, dec, format);} while(0) +# define LOG_M(file, vector, data, len, dec, format) do { write_file_matlab(file, vector, data, len, dec, format, 0);} while(0) # define LOG_VAR(A,B) A B # endif /* T_TRACER */ /* avoid warnings for variables only used in LOG macro's but set outside debug section */ @@ -439,9 +440,10 @@ int32_t write_file_matlab(const char *fname, const char *vname, void *data, int #define LOG_USEDINLOG_VAR(A,B) GCC_NOTUSED A B /* unfiltered macros, useful for simulators or messages at init time, before log is configured */ -#define LOG_UM(file, vector, data, len, dec, format) do { write_file_matlab(file, vector, data, len, dec, format);} while(0) +#define LOG_UM(file, vector, data, len, dec, format) do { write_file_matlab(file, vector, data, len, dec, format, 0);} while(0) #define LOG_UI(c, x...) do {logRecord_mt(__FILE__, __FUNCTION__, __LINE__,c, OAILOG_INFO, x) ; } while(0) #define LOG_UDUMPMSG(c, b, s, f, x...) do { log_dump(c, b, s, f, x) ;} while (0) /* */ +# define LOG_MM(file, vector, data, len, dec, format) do { write_file_matlab(file, vector, data, len, dec, format, 1);} while(0) /* @}*/ diff --git a/common/utils/T/.gitignore b/common/utils/T/.gitignore index d754ff7c38..6a6e5817c5 100644 --- a/common/utils/T/.gitignore +++ b/common/utils/T/.gitignore @@ -4,6 +4,7 @@ T_IDs.h T_messages.txt.h genids tracer/enb +tracer/gnb tracer/extract_config tracer/record tracer/replay diff --git a/common/utils/T/T_messages.txt b/common/utils/T/T_messages.txt index bad6444e13..fedc50cf5d 100644 --- a/common/utils/T/T_messages.txt +++ b/common/utils/T/T_messages.txt @@ -1,7 +1,3 @@ -ID = BENETEL - GROUP = ALL - FORMAT = int,frame : int,slot : buffer,rxdataF - #general logs ID = ENB_MASTER_TICK DESC = eNodeB master tick - one tick per ms, to be used as "reference clock", mostly for ticktime view @@ -93,6 +89,10 @@ ID = GNB_PHY_MIB DESC = NR MIB data GROUP = ALL:PHY:GNB:WIRESHARK FORMAT = int,gNB_ID : int,frame : int,slot : buffer,data +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 #MAC logs ID = ENB_MAC_UE_DL_SDU diff --git a/common/utils/T/tracer/Makefile b/common/utils/T/tracer/Makefile index 792c2a407c..0713d9a3df 100644 --- a/common/utils/T/tracer/Makefile +++ b/common/utils/T/tracer/Makefile @@ -7,7 +7,8 @@ LIBS=-lm XLIBS=-lX11 -lpng -lXft all: record replay extract_config textlog enb ue vcd macpdu2wireshark \ - extract_input_subframe extract_output_subframe to_vcd extract multi + extract_input_subframe extract_output_subframe to_vcd extract multi \ + gnb record: utils.o record.o database.o config.o $(CC) $(CFLAGS) -o record $^ $(LIBS) @@ -60,6 +61,11 @@ macpdu2wireshark: macpdu2wireshark.o database.o utils.o handler.o event.o \ multi: multi.o utils.o database.o config.o $(CC) $(CFLAGS) -o multi $^ $(LIBS) +gnb: utils.o gnb.o database.o event.o handler.o config.o \ + view/view.a gui/gui.a logger/logger.a \ + filter/filter.a + $(CC) $(CFLAGS) -o gnb $^ $(LIBS) $(XLIBS) + multi.o: ../T_IDs.h ../T_IDs.h: @@ -85,7 +91,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 + rm -f extract_output_subframe to_vcd extract multi gnb cd gui && $(MAKE) clean cd view && $(MAKE) clean cd logger && $(MAKE) clean diff --git a/common/utils/T/tracer/gnb.c b/common/utils/T/tracer/gnb.c new file mode 100644 index 0000000000..4aaa4898a1 --- /dev/null +++ b/common/utils/T/tracer/gnb.c @@ -0,0 +1,172 @@ +#include +#include +#include +#include +#include +#include "database.h" +#include "handler.h" +#include "config.h" +#include "logger/logger.h" +#include "view/view.h" +#include "gui/gui.h" + +typedef struct { + widget *pucch_pusch_iq_plot; + logger *pucch_pusch_iq_logger; +} gnb_gui; + +typedef struct { + int socket; + int *is_on; + int nevents; + pthread_mutex_t lock; + gnb_gui *e; + void *database; +} gnb_data; + +void is_on_changed(void *_d) +{ + gnb_data *d = _d; + char t; + + if (pthread_mutex_lock(&d->lock)) abort(); + + if (d->socket == -1) goto no_connection; + + t = 1; + if (socket_send(d->socket, &t, 1) == -1 || + socket_send(d->socket, &d->nevents, sizeof(int)) == -1 || + socket_send(d->socket, d->is_on, d->nevents * sizeof(int)) == -1) + goto connection_dies; + +no_connection: + if (pthread_mutex_unlock(&d->lock)) abort(); + return; + +connection_dies: + close(d->socket); + d->socket = -1; + if (pthread_mutex_unlock(&d->lock)) 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); +} + +static void *gui_thread(void *_g) +{ + gui *g = _g; + gui_loop(g); + return NULL; +} + +static void gnb_main_gui(gnb_gui *e, gui *g, event_handler *h, void *database, + gnb_data *ed) +{ + widget *main_window; + widget *top_container; + widget *line; + widget *w; + logger *l; + view *v; + + main_window = new_toplevel_window(g, 500, 300, "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); + + /* PUCCH/PUSCH IQ data */ + w = new_xy_plot(g, 55, 55, "", 50); + e->pucch_pusch_iq_plot = w; + widget_add_child(g, line, w, -1); + xy_plot_set_range(g, w, -1000, 1000, -1000, 1000); + xy_plot_set_title(g, w, "rxdataF"); + l = new_iqlog_full(h, database, "GNB_PHY_PUCCH_PUSCH_IQ", "rxdataF"); + v = new_view_xy(300*12*14,10,g,w,new_color(g,"#000"),XY_FORCED_MODE); + logger_add_view(l, v); + e->pucch_pusch_iq_logger = l; +} + +int main(int n, char **v) +{ + char *database_filename = NULL; + void *database; + char *ip = DEFAULT_REMOTE_IP; + int port = DEFAULT_REMOTE_PORT; + int *is_on; + int number_of_events; + int i; + event_handler *h; + gnb_data gnb_data; + gui *g; + gnb_gui eg; + + 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; } + 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(); + + h = new_handler(database); + + on_off(database, "GNB_PHY_PUCCH_PUSCH_IQ", is_on, 1); + + gnb_data.database = database; + gnb_data.socket = -1; + gnb_data.is_on = is_on; + gnb_data.nevents = number_of_events; + if (pthread_mutex_init(&gnb_data.lock, NULL)) abort(); + + g = gui_init(); + new_thread(gui_thread, g); + + gnb_main_gui(&eg, g, h, database, &gnb_data); + + OBUF ebuf = { osize: 0, omaxsize: 0, obuf: NULL }; + +restart: + clear_remote_config(); + if (gnb_data.socket != -1) close(gnb_data.socket); + gnb_data.socket = connect_to(ip, port); + + /* send the first message - activate selected traces */ + is_on_changed(&gnb_data); + + /* read messages */ + while (1) { + event e; + e = get_event(gnb_data.socket, &ebuf, database); + if (e.type == -1) goto restart; + if (pthread_mutex_lock(&gnb_data.lock)) abort(); + handle_event(h, e); + if (pthread_mutex_unlock(&gnb_data.lock)) abort(); + } + + return 0; +} diff --git a/common/utils/T/tracer/logger/iqlog.c b/common/utils/T/tracer/logger/iqlog.c index 168c50e39b..1947de2bca 100644 --- a/common/utils/T/tracer/logger/iqlog.c +++ b/common/utils/T/tracer/logger/iqlog.c @@ -74,6 +74,44 @@ static void _event(void *p, event e) l->common.v[i]->append(l->common.v[i], l->i, l->q, count); } +static void _event_full(void *p, event e) +{ + struct iqlog *l = p; + int i; + void *buffer; + int bsize; + int nsamples; + float *idst, *qdst; + + if (l->common.filter != NULL && filter_eval(l->common.filter, e) == 0) + return; + + buffer = e.e[l->buffer_arg].b; + bsize = e.e[l->buffer_arg].bsize; + + nsamples = bsize / 4; + + if (nsamples > l->max_length) { + l->i = realloc(l->i, nsamples * sizeof(float)); + if (l->i == NULL) abort(); + l->q = realloc(l->q, nsamples * sizeof(float)); + if (l->q == NULL) abort(); + l->max_length = nsamples; + } + + idst = l->i; + qdst = l->q; + for (i = 0; i < nsamples; i++) { + *idst = ((int16_t *)buffer)[i * 2]; + *qdst = ((int16_t *)buffer)[i * 2 + 1]; + idst++; + qdst++; + } + + for (i = 0; i < l->common.vsize; i++) + l->common.v[i]->append(l->common.v[i], l->i, l->q, nsamples); +} + logger *new_iqlog(event_handler *h, void *database, char *event_name, char *nb_rb, char *N_RB_UL, char *symbols_per_tti, char *buffer_varname) @@ -149,3 +187,43 @@ logger *new_iqlog(event_handler *h, void *database, return ret; } + +logger *new_iqlog_full(event_handler *h, void *database, char *event_name, + char *buffer_varname) +{ + struct iqlog *ret; + int event_id; + database_event_format f; + int i; + + ret = calloc(1, sizeof(struct iqlog)); if (ret == NULL) abort(); + + ret->common.event_name = strdup(event_name); + if (ret->common.event_name == NULL) abort(); + ret->database = database; + + event_id = event_id_from_name(database, event_name); + + ret->common.handler_id = register_handler_function(h, event_id, _event_full, + ret); + + f = get_format(database, event_id); + + /* look for args */ + ret->buffer_arg = -1; + for (i = 0; i < f.count; i++) { + if (!strcmp(f.name[i], buffer_varname)) ret->buffer_arg = i; + } + if (ret->buffer_arg == -1) { + printf("%s:%d: buffer argument '%s' not found in event '%s'\n", + __FILE__, __LINE__, buffer_varname, event_name); + abort(); + } + if (strcmp(f.type[ret->buffer_arg], "buffer") != 0) { + printf("%s:%d: argument '%s' has wrong type (should be 'buffer')\n", + __FILE__, __LINE__, buffer_varname); + abort(); + } + + return ret; +} diff --git a/common/utils/T/tracer/logger/logger.h b/common/utils/T/tracer/logger/logger.h index 7c019b4797..d746161e70 100644 --- a/common/utils/T/tracer/logger/logger.h +++ b/common/utils/T/tracer/logger/logger.h @@ -23,6 +23,8 @@ logger *new_ticklog(void *event_handler, void *database, logger *new_iqlog(void *event_handler, void *database, char *event_name, char *nb_rb, char *N_RB_UL, char *symbols_per_tti, char *buffer_varname); +logger *new_iqlog_full(void *event_handler, void *database, char *event_name, + char *buffer_varname); logger *new_iqdotlog(void *event_handler, void *database, char *event_name, char *I, char *Q); diff --git a/common/utils/nr/nr_common.c b/common/utils/nr/nr_common.c index 5f07fc00aa..0671aed813 100644 --- a/common/utils/nr/nr_common.c +++ b/common/utils/nr/nr_common.c @@ -32,6 +32,81 @@ #include #include "assertions.h" +#include "nr_common.h" + +// Table 5.2-1 NR operating bands in FR1 & FR2 (3GPP TS 38.101) +// Table 5.4.2.3-1 Applicable NR-ARFCN per operating band in FR1 & FR2 (3GPP TS 38.101) +// Notes: +// - N_OFFs for bands from 80 to 89 and band 95 is referred to UL +// - Frequencies are expressed in KHz +// - col: NR_band ul_min ul_max dl_min dl_max step N_OFFs_DL deltaf_raster +nr_bandentry_t nr_bandtable[] = { + {1, 1920000, 1980000, 2110000, 2170000, 20, 422000, 100}, + {2, 1850000, 1910000, 1930000, 1990000, 20, 386000, 100}, + {3, 1710000, 1785000, 1805000, 1880000, 20, 361000, 100}, + {5, 824000, 849000, 869000, 894000, 20, 173800, 100}, + {7, 2500000, 2570000, 2620000, 2690000, 20, 524000, 100}, + {8, 880000, 915000, 925000, 960000, 20, 185000, 100}, + {12, 698000, 716000, 729000, 746000, 20, 145800, 100}, + {14, 788000, 798000, 758000, 768000, 20, 151600, 100}, + {18, 815000, 830000, 860000, 875000, 20, 172000, 100}, + {20, 832000, 862000, 791000, 821000, 20, 158200, 100}, + {25, 1850000, 1915000, 1930000, 1995000, 20, 386000, 100}, + {26, 814000, 849000, 859000, 894000, 20, 171800, 100}, + {28, 703000, 758000, 758000, 813000, 20, 151600, 100}, + {29, 000, 000, 717000, 728000, 20, 143400, 100}, + {30, 2305000, 2315000, 2350000, 2360000, 20, 470000, 100}, + {34, 2010000, 2025000, 2010000, 2025000, 20, 402000, 100}, + {38, 2570000, 2620000, 2570000, 2630000, 20, 514000, 100}, + {39, 1880000, 1920000, 1880000, 1920000, 20, 376000, 100}, + {40, 2300000, 2400000, 2300000, 2400000, 20, 460000, 100}, + {41, 2496000, 2690000, 2496000, 2690000, 3, 499200, 15}, + {41, 2496000, 2690000, 2496000, 2690000, 6, 499200, 30}, + {47, 5855000, 5925000, 5855000, 5925000, 1, 790334, 15}, + //{48, 3550000, 3700000, 3550000, 3700000, 1, 636667, 15}, + //{48, 3550000, 3700000, 3550000, 3700000, 2, 636668, 30}, + {50, 1432000, 1517000, 1432000, 1517000, 20, 286400, 100}, + {51, 1427000, 1432000, 1427000, 1432000, 20, 285400, 100}, + {53, 2483500, 2495000, 2483500, 2495000, 20, 496700, 100}, + {65, 1920000, 2010000, 2110000, 2200000, 20, 422000, 100}, + {66, 1710000, 1780000, 2110000, 2200000, 20, 422000, 100}, + {70, 1695000, 1710000, 1995000, 2020000, 20, 399000, 100}, + {71, 663000, 698000, 617000, 652000, 20, 123400, 100}, + {74, 1427000, 1470000, 1475000, 1518000, 20, 295000, 100}, + {75, 000, 000, 1432000, 1517000, 20, 286400, 100}, + {76, 000, 000, 1427000, 1432000, 20, 285400, 100}, + {77, 3300000, 4200000, 3300000, 4200000, 1, 620000, 15}, + {77, 3300000, 4200000, 3300000, 4200000, 2, 620000, 30}, + {78, 3300000, 3800000, 3300000, 3800000, 1, 620000, 15}, + {78, 3300000, 3800000, 3300000, 3800000, 2, 620000, 30}, + {79, 4400010, 5000000, 4400010, 5000000, 1, 693334, 15}, + {79, 4400010, 5000000, 4400010, 5000000, 2, 693334, 30}, + {80, 1710000, 1785000, 000, 000, 20, 342000, 100}, + {81, 880000, 915000, 000, 000, 20, 176000, 100}, + {82, 832000, 862000, 000, 000, 20, 166400, 100}, + {83, 703000, 748000, 000, 000, 20, 140600, 100}, + {84, 1920000, 1980000, 000, 000, 20, 384000, 100}, + {86, 1710000, 1785000, 000, 000, 20, 342000, 100}, + {89, 824000, 849000, 000, 000, 20, 342000, 100}, + {90, 2496000, 2690000, 2496000, 2690000, 3, 499200, 15}, + {90, 2496000, 2690000, 2496000, 2690000, 6, 499200, 30}, + {90, 2496000, 2690000, 2496000, 2690000, 20, 499200, 100}, + {91, 832000, 862000, 1427000, 1432000, 20, 285400, 100}, + {92, 832000, 862000, 1432000, 1517000, 20, 286400, 100}, + {93, 880000, 915000, 1427000, 1432000, 20, 285400, 100}, + {94, 880000, 915000, 1432000, 1517000, 20, 286400, 100}, + {95, 2010000, 2025000, 000, 000, 20, 402000, 100}, + {257,26500020,29500000,26500020,29500000, 1,2054166, 60}, + {257,26500080,29500000,26500080,29500000, 2,2054167, 120}, + {258,24250080,27500000,24250080,27500000, 1,2016667, 60}, + {258,24250080,27500000,24250080,27500000, 2,2016667, 120}, + {260,37000020,40000000,37000020,40000000, 1,2229166, 60}, + {260,37000080,40000000,37000080,40000000, 2,2229167, 120}, + {261,27500040,28350000,27500040,28350000, 1,2070833, 60}, + {261,27500040,28350000,27500040,28350000, 2,2070833, 120} +}; + +const size_t nr_bandtable_size = sizeof(nr_bandtable) / sizeof(nr_bandentry_t); int NRRIV2BW(int locationAndBandwidth,int N_RB) { int tmp = locationAndBandwidth/N_RB; diff --git a/common/utils/nr/nr_common.h b/common/utils/nr/nr_common.h index 5601c0fcbf..6389c2c094 100644 --- a/common/utils/nr/nr_common.h +++ b/common/utils/nr/nr_common.h @@ -36,6 +36,20 @@ #include #include "assertions.h" +typedef struct nr_bandentry_s { + int16_t band; + uint64_t ul_min; + uint64_t ul_max; + uint64_t dl_min; + uint64_t dl_max; + uint64_t step_size; + uint64_t N_OFFs_DL; + uint8_t deltaf_raster; +} nr_bandentry_t; + +extern const size_t nr_bandtable_size; +extern nr_bandentry_t nr_bandtable[]; + int NRRIV2BW(int locationAndBandwidth,int N_RB); int NRRIV2PRBOFFSET(int locationAndBandwidth,int N_RB); int PRBalloc_to_locationandbandwidth0(int NPRB,int RBstart,int BWPsize); diff --git a/doc/NFAPI_archi.md b/doc/NFAPI_archi.md new file mode 100644 index 0000000000..61c66bd043 --- /dev/null +++ b/doc/NFAPI_archi.md @@ -0,0 +1,132 @@ +# global + +xnf is pnf or vnf + +The xnf starting functions are configure_nfapi_xnf() + +The OAI code that read the configuration parameters call these functions that will create autonomous thread for xnf control part + +These control threads create a SCTP socket by Linux API call (no use of OpenAir internal architecture with SCTP itti thread). + +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 + +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, ... + +## signaling (P5) xnf main loop + +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 + +nfapi_pnf_start() initiate connection to vnf until it has a link. Then it enter a similar infinite loop in pnf_message_pump() + +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 + +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; +``` + +These loops are autonomous in their thread waiting incoming message. + +## P7 xnf 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) + +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) + +So, we have the logic for UL reception in vnf, and DL reception in pnf + +## 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). + +After decoding, results are accumulated into the xNB->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, + +``` + +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) { + oai_nfapi_nr_rach_indication(&UL_info->rach_ind); //This function calls the routines required for packing + transmission through socket + UL_info->rach_ind.number_of_pdus = 0; + } + } + +``` + +## P7 UL reception at VNF + +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 message, UL_INFO struct on the VNF side gets populated. The NR_UL_indication() function is then called at the VNF, which uses UL_INFO. + +``` + +// have a p7 message + if(FD_ISSET(vnf_p7->socket, &rfds)) + { + vnf_nr_p7_read_dispatch_message(vnf_p7); + + // Call the scheduler + struct PHY_VARS_gNB_s *gNB = RC.gNB[0]; + pthread_mutex_lock(&gNB->UL_INFO_mutex); + gNB->UL_INFO.frame = vnf_frame; + gNB->UL_INFO.slot = vnf_slot; + + gNB->UL_INFO.module_id = gNB->Mod_id; + gNB->UL_INFO.CC_id = gNB->CC_id; + gNB->if_inst->NR_UL_indication(&gNB->UL_INFO); + pthread_mutex_unlock(&gNB->UL_INFO_mutex); + } + +``` + +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() after processing of UL_INFO. The function performing the scheduling of channels (and consequently p7 messages in nFAPI) is gNB_dlsch_ulsch_scheduler(). + +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) +{ + oai_nfapi_tx_data_req(Sched_INFO->TX_req); +} + +``` + +## 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. + +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). A point to note is 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). Ideally, it should be received within a duration significantly lesser than slot_ahead so that there is adequate time for PHY processing. + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/doc/RUNMODEM.md b/doc/RUNMODEM.md index d13b193ff9..8d84646e07 100644 --- a/doc/RUNMODEM.md +++ b/doc/RUNMODEM.md @@ -132,9 +132,9 @@ With the RF simulator (on the same machine): `sudo RFSIMULATOR=127.0.0.1 ./nr-uesoftmodem --do-ra --rfsim --parallel-config PARALLEL_SINGLE_THREAD` -## sa setup with OAI +## SA setup with OAI -The sa flag is used to run gNB in standalone mode. Currently OAI in NR standalone mode transmits and receives SIB1. +The sa flag is used to run gNB in standalone mode. Currently OAI in NR standalone mode transmits and receives SIB1 and triggers the RA procedure for initial access. In order to run gNB in standalone mode, the following flag is needed at gNB: @@ -147,8 +147,9 @@ At the gNB the --sa flag does the following - it encodes the RRCConfiguration and the RBconfig message and stores them in the binary files rbconfig.raw and reconfig.raw - the RRC encodes SIB1 according the configuration file and transmits it through PDSCH -At the UE the --sa flag will -- read the binary files rbconfig.raw and reconfig.raw from the current directory (a different directory can be specified with the flag --rrc_config_path) and process them. +At the UE the --sa flag will: +- Read the binary files rbconfig.raw and reconfig.raw from the current directory (a different directory can be specified with the flag --rrc_config_path) and process them +- After the successful decoding of a SIB1 at RRC, the UE will start the 5G NR Initial Access Procedure by triggering the RA procedure. From the `cmake_targets/ran_build/build` folder: @@ -168,7 +169,7 @@ With the RF simulator (on the same machine): ## IF setup with OAI -The -C and -CO flags can be used together at UE side to set custom downlink and uplink FR1 intermediate frequencies for the IF equipment. +The -C and --CO flags can be used together at UE side to set custom downlink and uplink FR1 arbitrary frequencies for the IF equipment. In order to run this setup, the following flags are needed at the UE side: @@ -182,9 +183,11 @@ and the following parameters must be configured in the RUs section of the gNB co `if_offset` -### Run OAI with custom DL/UL intermediate frequencies +The values must be given in Hz. -The following example uses DL frequency 2169.080 MHz and UL frequency offset -400 MHz, with a configuration file for band 66 at gNB side. +### Run OAI with custom DL/UL arbitrary frequencies + +The following example uses DL frequency 2169.080 MHz and UL frequency offset -400 MHz, with a configuration file for band 66 (FDD) at gNB side. From the `cmake_targets/ran_build/build` folder: diff --git a/docker/Dockerfile.eNB.rhel8.2 b/docker/Dockerfile.eNB.rhel8.2 index 5fcd5a7b9f..aa8b9aa228 100644 --- a/docker/Dockerfile.eNB.rhel8.2 +++ b/docker/Dockerfile.eNB.rhel8.2 @@ -27,14 +27,15 @@ FROM localhost/ran-build:latest AS enb-build +RUN rm -Rf /oai-ran WORKDIR /oai-ran +COPY . . #run build_oai to build the target image RUN /bin/sh oaienv && \ cd cmake_targets && \ - rm -Rf log && \ mkdir -p log && \ - ./build_oai --eNB --ninja -w USRP + ./build_oai --eNB --ninja -w USRP --verbose-ci # debug #RUN ldconfig -v && ldd /oai-ran/targets/bin/lte-softmodem.Rel15 diff --git a/docker/Dockerfile.eNB.ubuntu18 b/docker/Dockerfile.eNB.ubuntu18 index cdfb37ebfc..95d7194c31 100644 --- a/docker/Dockerfile.eNB.ubuntu18 +++ b/docker/Dockerfile.eNB.ubuntu18 @@ -27,14 +27,15 @@ FROM ran-build:latest AS enb-build +RUN rm -Rf /oai-ran WORKDIR /oai-ran +COPY . . #run build_oai to build the target image RUN /bin/sh oaienv && \ cd cmake_targets && \ - rm -Rf log && \ mkdir -p log && \ - ./build_oai --eNB --ninja -w USRP + ./build_oai --eNB --ninja -w USRP --verbose-ci RUN apt-get install -y python3-pip && \ pip3 install --ignore-installed pyyaml && \ diff --git a/docker/Dockerfile.gNB.rhel8.2 b/docker/Dockerfile.gNB.rhel8.2 index fb9ade927f..6969c691fd 100644 --- a/docker/Dockerfile.gNB.rhel8.2 +++ b/docker/Dockerfile.gNB.rhel8.2 @@ -27,14 +27,15 @@ FROM localhost/ran-build:latest AS gnb-build +RUN rm -Rf /oai-ran WORKDIR /oai-ran +COPY . . #run build_oai to build the target image RUN /bin/sh oaienv && \ cd cmake_targets && \ - rm -Rf log && \ mkdir -p log && \ - ./build_oai --gNB --ninja -w USRP + ./build_oai --gNB --ninja -w USRP --verbose-ci #debug #RUN ldconfig -v diff --git a/docker/Dockerfile.gNB.ubuntu18 b/docker/Dockerfile.gNB.ubuntu18 index d43ad4709d..276d6989c4 100644 --- a/docker/Dockerfile.gNB.ubuntu18 +++ b/docker/Dockerfile.gNB.ubuntu18 @@ -27,14 +27,15 @@ FROM ran-build:latest AS gnb-build +RUN rm -Rf /oai-ran WORKDIR /oai-ran +COPY . . #run build_oai to build the target image RUN /bin/sh oaienv && \ cd cmake_targets && \ - rm -Rf log && \ mkdir -p log && \ - ./build_oai --gNB --ninja -w USRP + ./build_oai --gNB --ninja -w USRP --verbose-ci #debug RUN ldconfig -v diff --git a/docker/Dockerfile.lteUE.rhel8.2 b/docker/Dockerfile.lteUE.rhel8.2 index 0a853dcd6b..e22343d63c 100644 --- a/docker/Dockerfile.lteUE.rhel8.2 +++ b/docker/Dockerfile.lteUE.rhel8.2 @@ -27,15 +27,15 @@ FROM localhost/ran-build:latest AS lte-ue-build - +RUN rm -Rf /oai-ran WORKDIR /oai-ran +COPY . . #run build_oai to build the target image RUN /bin/sh oaienv && \ cd cmake_targets && \ - rm -Rf log && \ mkdir -p log && \ - ./build_oai --UE --ninja -w USRP + ./build_oai --UE --ninja -w USRP --verbose-ci # debug #RUN ldconfig -v && ldd /oai-ran/targets/bin/lte-uesoftmodem.Rel15 diff --git a/docker/Dockerfile.lteUE.ubuntu18 b/docker/Dockerfile.lteUE.ubuntu18 index 8793cc54f7..6af2e61991 100644 --- a/docker/Dockerfile.lteUE.ubuntu18 +++ b/docker/Dockerfile.lteUE.ubuntu18 @@ -27,14 +27,15 @@ FROM ran-build:latest AS lte-ue-build +RUN rm -Rf /oai-ran WORKDIR /oai-ran +COPY . . #run build_oai to build the target image RUN /bin/sh oaienv && \ cd cmake_targets && \ - rm -Rf log && \ mkdir -p log && \ - ./build_oai --UE --ninja -w USRP + ./build_oai --UE --ninja -w USRP --verbose-ci # debug #RUN ldconfig -v diff --git a/docker/Dockerfile.nrUE.rhel8.2 b/docker/Dockerfile.nrUE.rhel8.2 index f9f3f8e4bf..01988fd6ff 100644 --- a/docker/Dockerfile.nrUE.rhel8.2 +++ b/docker/Dockerfile.nrUE.rhel8.2 @@ -27,14 +27,15 @@ FROM localhost/ran-build:latest AS nr-ue-build +RUN rm -Rf /oai-ran WORKDIR /oai-ran +COPY . . #run build_oai to build the target image RUN /bin/sh oaienv && \ cd cmake_targets && \ - rm -Rf log && \ mkdir -p log && \ - ./build_oai --nrUE --ninja -w USRP + ./build_oai --nrUE --ninja -w USRP --verbose-ci # debug #RUN ldconfig -v diff --git a/docker/Dockerfile.nrUE.ubuntu18 b/docker/Dockerfile.nrUE.ubuntu18 index 5450194f35..c96bcf80ef 100644 --- a/docker/Dockerfile.nrUE.ubuntu18 +++ b/docker/Dockerfile.nrUE.ubuntu18 @@ -27,14 +27,15 @@ FROM ran-build:latest AS nr-ue-build +RUN rm -Rf /oai-ran WORKDIR /oai-ran +COPY . . #run build_oai to build the target image RUN /bin/sh oaienv && \ cd cmake_targets && \ - rm -Rf log && \ mkdir -p log && \ - ./build_oai --nrUE --ninja -w USRP + ./build_oai --nrUE --ninja -w USRP --verbose-ci # debug #RUN ldconfig -v diff --git a/executables/nr-gnb.c b/executables/nr-gnb.c index 2f7944e313..410c41d9b1 100644 --- a/executables/nr-gnb.c +++ b/executables/nr-gnb.c @@ -81,10 +81,11 @@ #include "s1ap_eNB.h" #include "SIMULATION/ETH_TRANSPORT/proto.h" - +#include #include "T.h" #include "nfapi/oai_integration/vendor_ext.h" +#include //#define DEBUG_THREADS 1 //#define USRP_DEBUG 1 @@ -92,17 +93,6 @@ // extern openair0_device openair0; -extern volatile int start_gNB; -extern volatile int start_UE; -extern volatile int oai_exit; - -extern openair0_config_t openair0_cfg[MAX_CARDS]; - -extern int transmission_mode; - -extern uint16_t sf_ahead; -extern uint16_t sl_ahead; - //pthread_t main_gNB_thread; time_stats_t softmodem_stats_mt; // main thread @@ -111,40 +101,43 @@ time_stats_t softmodem_stats_rxtx_sf; // total tx time time_stats_t nfapi_meas; // total tx time time_stats_t softmodem_stats_rx_sf; // total rx time -/* mutex, cond and variable to serialize phy proc TX calls - * (this mechanism may be relaxed in the future for better - * performances) - */ -static struct { - pthread_mutex_t mutex_phy_proc_tx; - pthread_cond_t cond_phy_proc_tx; - volatile uint8_t phy_proc_CC_id; -} sync_phy_proc; -extern double cpuf; - -void init_gNB(int,int); -void stop_gNB(int nb_inst); - -int wakeup_txfh(PHY_VARS_gNB *gNB, gNB_L1_rxtx_proc_t *proc, int frame_tx, int slot_tx, uint64_t timestamp_tx); -int wakeup_tx(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx, int frame_tx, int slot_tx, uint64_t timestamp_tx); #include "executables/thread-common.h" -//extern PARALLEL_CONF_t get_thread_parallel_conf(void); -//extern WORKER_CONF_t get_thread_worker_conf(void); -void wakeup_prach_gNB(PHY_VARS_gNB *gNB, RU_t *ru, int frame, int subframe); - -extern uint8_t nfapi_mode; -extern void oai_subframe_ind(uint16_t sfn, uint16_t sf); -extern void oai_slot_ind(uint16_t sfn, uint16_t slot); -extern void add_subframe(uint16_t *frameP, uint16_t *subframeP, int offset); - //#define TICK_TO_US(ts) (ts.diff) #define TICK_TO_US(ts) (ts.trials==0?0:ts.diff/ts.trials) -static inline int rxtx(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx, int frame_tx, int slot_tx, char *thread_name) { +void tx_func(void *param) { + + processingData_L1_t *info = (processingData_L1_t *) param; + PHY_VARS_gNB *gNB = info->gNB; + int frame_tx = info->frame_tx; + int slot_tx = info->slot_tx; + + phy_procedures_gNB_TX(gNB, frame_tx,slot_tx, 1); + + // start FH TX processing + notifiedFIFO_elt_t *res; + res = pullTpool(gNB->resp_RU_tx, gNB->threadPool); + processingData_RU_t *syncMsg = (processingData_RU_t *)NotifiedFifoData(res); + syncMsg->frame_tx = frame_tx; + syncMsg->slot_tx = slot_tx; + syncMsg->timestamp_tx = info->timestamp_tx; + syncMsg->ru = gNB->RU_list[0]; + res->key = slot_tx; + pushTpool(gNB->threadPool, res); +} + +void rx_func(void *param) { + //printf("inside rx func. \n"); + processingData_L1_t *info = (processingData_L1_t *) param; + PHY_VARS_gNB *gNB = info->gNB; + int frame_rx = info->frame_rx; + int slot_rx = info->slot_rx; + int frame_tx = info->frame_tx; + int slot_tx = info->slot_tx; sl_ahead = sf_ahead*gNB->frame_parms.slots_per_subframe; nfapi_nr_config_request_scf_t *cfg = &gNB->gNB_config; @@ -235,22 +228,18 @@ static inline int rxtx(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx, int frame_t rnti_to_remove_count = 0; if (pthread_mutex_unlock(&rnti_to_remove_mutex)) exit(1); - /* - // if this is IF5 or 3GPP_gNB - if (gNB && gNB->RU_list && gNB->RU_list[0] && gNB->RU_list[0]->function < NGFI_RAU_IF4p5) { - wakeup_prach_gNB(gNB,NULL,proc->frame_rx,proc->slot_rx); - } - */ // Call the scheduler - pthread_mutex_lock(&gNB->UL_INFO_mutex); - gNB->UL_INFO.frame = frame_rx; - gNB->UL_INFO.slot = slot_rx; - gNB->UL_INFO.module_id = gNB->Mod_id; - gNB->UL_INFO.CC_id = gNB->CC_id; - gNB->if_inst->NR_UL_indication(&gNB->UL_INFO); - pthread_mutex_unlock(&gNB->UL_INFO_mutex); - + if(NFAPI_MODE == NFAPI_MONOLITHIC) + { + pthread_mutex_lock(&gNB->UL_INFO_mutex); + gNB->UL_INFO.frame = frame_rx; + gNB->UL_INFO.slot = slot_rx; + gNB->UL_INFO.module_id = gNB->Mod_id; + gNB->UL_INFO.CC_id = gNB->CC_id; + gNB->if_inst->NR_UL_indication(&gNB->UL_INFO); + pthread_mutex_unlock(&gNB->UL_INFO_mutex); + } // RX processing int tx_slot_type; int rx_slot_type; if(NFAPI_MODE != NFAPI_MONOLITHIC) { //slot selection routines not working properly in nfapi, so temporarily hardcoding @@ -298,23 +287,24 @@ static inline int rxtx(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx, int frame_t phy_procedures_gNB_uespec_RX(gNB, frame_rx, slot_rx); } - if (oai_exit) return(-1); - - // ***************************************** - // TX processing for subframe n+sf_ahead - // run PHY TX procedures the one after the other for all CCs to avoid race conditions - // (may be relaxed in the future for performance reasons) - // ***************************************** - - if (tx_slot_type == NR_DOWNLINK_SLOT || tx_slot_type == NR_MIXED_SLOT) { - - if(get_thread_parallel_conf() != PARALLEL_RU_L1_TRX_SPLIT) { - phy_procedures_gNB_TX(gNB, frame_tx,slot_tx, 1); - } - } - stop_meas( &softmodem_stats_rxtx_sf ); LOG_D(PHY,"%s() Exit proc[rx:%d%d tx:%d%d]\n", __FUNCTION__, frame_rx, slot_rx, frame_tx, slot_tx); + + notifiedFIFO_elt_t *res; + + if (tx_slot_type == NR_DOWNLINK_SLOT || tx_slot_type == NR_MIXED_SLOT) { + res = pullTpool(gNB->resp_L1_tx, gNB->threadPool); + processingData_L1_t *syncMsg = (processingData_L1_t *)NotifiedFifoData(res); + syncMsg->gNB = gNB; + syncMsg->frame_rx = frame_rx; + syncMsg->slot_rx = slot_rx; + syncMsg->frame_tx = frame_tx; + syncMsg->slot_tx = slot_tx; + syncMsg->timestamp_tx = info->timestamp_tx; + res->key = slot_tx; + pushTpool(gNB->threadPool, res); + } + #if 0 LOG_D(PHY, "rxtx:%lld nfapi:%lld phy:%lld tx:%lld rx:%lld prach:%lld ofdm:%lld ", softmodem_stats_rxtx_sf.diff_now, nfapi_meas.diff_now, @@ -354,477 +344,7 @@ static inline int rxtx(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx, int frame_t TICK_TO_US(gNB->ulsch_tc_intl2_stats) ); #endif - return(0); } - -static void *gNB_L1_thread_tx(void *param) { - PHY_VARS_gNB *gNB = (PHY_VARS_gNB *)param; - gNB_L1_proc_t *gNB_proc = &gNB->proc; - gNB_L1_rxtx_proc_t *L1_proc_tx = &gNB_proc->L1_proc_tx; - //PHY_VARS_gNB *gNB = RC.gNB[0][proc->CC_id]; - char thread_name[100]; - - sprintf(thread_name,"gNB_L1_thread_tx\n"); - - while (!oai_exit) { - if (wait_on_condition(&L1_proc_tx->mutex,&L1_proc_tx->cond,&L1_proc_tx->instance_cnt,thread_name)<0) break; - - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_gNB_PROC_RXTX1, 1 ); - - if (oai_exit) break; - - // ***************************************** - // TX processing for subframe n+4 - // run PHY TX procedures the one after the other for all CCs to avoid race conditions - // (may be relaxed in the future for performance reasons) - // ***************************************** - int frame_tx = L1_proc_tx->frame_tx; - int slot_tx = L1_proc_tx->slot_tx; - uint64_t timestamp_tx = L1_proc_tx->timestamp_tx; - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_SLOT_NUMBER_TX1_GNB,slot_tx); - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_TX1_GNB,frame_tx); - phy_procedures_gNB_TX(gNB, frame_tx,slot_tx, 1); - - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_WAKEUP_TXFH, 1 ); - pthread_mutex_lock( &L1_proc_tx->mutex ); - L1_proc_tx->instance_cnt = -1; - - // the thread can now be woken up - if (pthread_cond_signal(&L1_proc_tx->cond) != 0) { - LOG_E( PHY, "[gNB] ERROR pthread_cond_signal for gNB TXnp4 thread\n"); - exit_fun( "ERROR pthread_cond_signal" ); - } - pthread_mutex_unlock(&L1_proc_tx->mutex); - - wakeup_txfh(gNB,L1_proc_tx,frame_tx,slot_tx,timestamp_tx); - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_WAKEUP_TXFH, 0 ); - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_gNB_PROC_RXTX1, 0 ); - } - - return 0; -} - -/*! - * \brief The RX UE-specific and TX thread of gNB. - * \param param is a \ref gNB_L1_proc_t structure which contains the info what to process. - * \returns a pointer to an int. The storage is not on the heap and must not be freed. - */ - -static void *gNB_L1_thread( void *param ) { - static int gNB_thread_rxtx_status; - PHY_VARS_gNB *gNB = (PHY_VARS_gNB *)param; - gNB_L1_proc_t *gNB_proc = &gNB->proc; - gNB_L1_rxtx_proc_t *L1_proc = &gNB_proc->L1_proc; - //PHY_VARS_gNB *gNB = RC.gNB[0][proc->CC_id]; - char thread_name[100]; - // set default return value - // set default return value - gNB_thread_rxtx_status = 0; - - sprintf(thread_name,"gNB_L1_thread"); - - - while (!oai_exit) { - - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_gNB_PROC_RXTX0, 0 ); - int frame_rx = L1_proc->frame_rx; - int slot_rx; - if (NFAPI_MODE == NFAPI_MODE_PNF) - slot_rx = (L1_proc->slot_rx) + 1; - else - slot_rx = L1_proc->slot_rx; - int frame_tx = L1_proc->frame_tx; - int slot_tx = L1_proc->slot_tx; - uint64_t timestamp_tx = L1_proc->timestamp_tx; - if(NFAPI_MODE==NFAPI_MODE_VNF) - if (gNB->CC_id==0) { - int next_slot; - next_slot = (slot_rx + 1) % 20; - if (rxtx(gNB,frame_rx,next_slot,frame_tx,next_slot,thread_name) < 0) break; - } - if (wait_on_condition(&L1_proc->mutex,&L1_proc->cond,&L1_proc->instance_cnt,thread_name)<0) break; - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_gNB_PROC_RXTX0, 1 ); - - - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_SLOT_NUMBER_TX0_GNB,slot_tx); - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_SLOT_NUMBER_RX0_GNB,slot_rx); - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_TX0_GNB,frame_tx); - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_RX0_GNB,frame_rx); - - if (oai_exit) break; - - if (gNB->CC_id==0) { - if (rxtx(gNB,frame_rx,slot_rx,frame_tx,slot_tx,thread_name) < 0) break; - } - - - if (release_thread(&L1_proc->mutex,&L1_proc->instance_cnt,thread_name)<0) break; - - if (get_thread_parallel_conf() == PARALLEL_RU_L1_TRX_SPLIT) wakeup_tx(gNB,frame_rx,slot_rx,frame_tx,slot_tx,timestamp_tx); - else if(get_thread_parallel_conf() == PARALLEL_RU_L1_SPLIT) wakeup_txfh(gNB,L1_proc,frame_tx,slot_tx,timestamp_tx); - } // while !oai_exit - - LOG_D(PHY, " *** Exiting gNB thread RXn_TXnp4\n"); - gNB_thread_rxtx_status = 0; - return &gNB_thread_rxtx_status; -} - - -#if 0 -// Wait for gNB application initialization to be complete (gNB registration to MME) -static void wait_system_ready (char *message, volatile int *start_flag) { - static char *indicator[] = {". ", ".. ", "... ", ".... ", ".....", - " ....", " ...", " ..", " .", " " - }; - int i = 0; - - while ((!oai_exit) && (*start_flag == 0)) { - LOG_N(EMU, message, indicator[i]); - fflush(stdout); - i = (i + 1) % (sizeof(indicator) / sizeof(indicator[0])); - usleep(200000); - } - - LOG_D(EMU,"\n"); -} -#endif - - - - - -void gNB_top(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx, char *string, struct RU_t_s *ru) { - gNB_L1_proc_t *proc = &gNB->proc; - gNB_L1_rxtx_proc_t *L1_proc = &proc->L1_proc; - NR_DL_FRAME_PARMS *fp = ru->nr_frame_parms; - RU_proc_t *ru_proc=&ru->proc; - proc->frame_rx = frame_rx; - proc->slot_rx = slot_rx; - sl_ahead = sf_ahead*fp->slots_per_subframe; - - if (!oai_exit) { - T(T_ENB_MASTER_TICK, T_INT(0), T_INT(proc->frame_rx), T_INT(proc->slot_rx)); - L1_proc->timestamp_tx = ru_proc->timestamp_rx + (sf_ahead*fp->samples_per_subframe); - L1_proc->frame_rx = ru_proc->frame_rx; - L1_proc->slot_rx = ru_proc->tti_rx; - L1_proc->frame_tx = (L1_proc->slot_rx > (fp->slots_per_frame-1-(fp->slots_per_subframe*sf_ahead))) ? (L1_proc->frame_rx+1)&1023 : L1_proc->frame_rx; - L1_proc->slot_tx = (L1_proc->slot_rx + (fp->slots_per_subframe*sf_ahead))%fp->slots_per_frame; - - if (rxtx(gNB,L1_proc->frame_rx,L1_proc->slot_rx,L1_proc->frame_tx,L1_proc->slot_tx,string) < 0) LOG_E(PHY,"gNB %d CC_id %d failed during execution\n",gNB->Mod_id,gNB->CC_id); - - ru_proc->timestamp_tx = L1_proc->timestamp_tx; - ru_proc->tti_tx = L1_proc->slot_tx; - ru_proc->frame_tx = L1_proc->frame_tx; - } -} - -int wakeup_txfh(PHY_VARS_gNB *gNB,gNB_L1_rxtx_proc_t *proc,int frame_tx,int slot_tx,uint64_t timestamp_tx) { - - RU_t *ru; - RU_proc_t *ru_proc; - - int waitret = 0, ret = 0, time_ns = 1000*1000; - struct timespec now, abstime; - // note this should depend on the numerology used by the TX L1 thread, set here for 500us slot time - // note this should depend on the numerology used by the TX L1 thread, set here for 500us slot time - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_GAIN_CONTROL,1); - time_ns = time_ns/gNB->frame_parms.slots_per_subframe; - AssertFatal((ret = pthread_mutex_lock(&proc->mutex_RUs_tx))==0,"mutex_lock returns %d\n",ret); - while (proc->instance_cnt_RUs < 0) { - clock_gettime(CLOCK_REALTIME, &now); - abstime.tv_sec = now.tv_sec; - abstime.tv_nsec = now.tv_nsec + time_ns; - - if (abstime.tv_nsec >= 1000*1000*1000) { - abstime.tv_nsec -= 1000*1000*1000; - abstime.tv_sec += 1; - } - if((waitret = pthread_cond_timedwait(&proc->cond_RUs,&proc->mutex_RUs_tx,&abstime)) == 0) break; // this unlocks mutex_rxtx while waiting and then locks it again - } - proc->instance_cnt_RUs = -1; - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_RX0_UE,proc->instance_cnt_RUs); - AssertFatal((ret = pthread_mutex_unlock(&proc->mutex_RUs_tx))==0,"mutex_unlock returns %d\n",ret); - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_GAIN_CONTROL,0); - - if (waitret == ETIMEDOUT) { - LOG_W(PHY,"Dropping TX slot (%d.%d) because FH is blocked more than 1 slot times (500us)\n",frame_tx,slot_tx); - - AssertFatal((ret=pthread_mutex_lock(&gNB->proc.mutex_RU_tx))==0,"mutex_lock returns %d\n",ret); - gNB->proc.RU_mask_tx = 0; - AssertFatal((ret=pthread_mutex_unlock(&gNB->proc.mutex_RU_tx))==0,"mutex_unlock returns %d\n",ret); - AssertFatal((ret=pthread_mutex_lock(&proc->mutex_RUs_tx))==0,"mutex_lock returns %d\n",ret); - proc->instance_cnt_RUs = 0; - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_RX0_UE,proc->instance_cnt_RUs); - AssertFatal((ret=pthread_mutex_unlock(&proc->mutex_RUs_tx))==0,"mutex_unlock returns %d\n",ret); - - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_TX0_UE,1); - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_TX0_UE,0); - - return(-1); - } - - for(int i=0; inum_RU; i++) - { - ru = gNB->RU_list[i]; - ru_proc = &ru->proc; - - - if (ru_proc->instance_cnt_gNBs == 0) { - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TST_UE, 1); - LOG_E(PHY,"Frame %d, subframe %d: TX FH thread busy, dropping Frame %d, subframe %d\n", ru_proc->frame_tx, ru_proc->tti_tx, proc->frame_rx, proc->slot_rx); - AssertFatal((ret=pthread_mutex_lock(&gNB->proc.mutex_RU_tx))==0,"mutex_lock returns %d\n",ret); - gNB->proc.RU_mask_tx = 0; - AssertFatal((ret=pthread_mutex_unlock(&gNB->proc.mutex_RU_tx))==0,"mutex_unlock returns %d\n",ret); - - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TST_UE, 0); - return(-1); - } - AssertFatal((ret = pthread_mutex_lock(&ru_proc->mutex_gNBs))==0,"ERROR pthread_mutex_lock failed on mutex_gNBs L1_thread_tx with ret=%d\n",ret); - - ru_proc->instance_cnt_gNBs = 0; - ru_proc->timestamp_tx = timestamp_tx; - ru_proc->tti_tx = slot_tx; - ru_proc->frame_tx = frame_tx; - - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_RX1_UE, ru_proc->instance_cnt_gNBs); - - LOG_D(PHY,"Signaling tx_thread_fh for %d.%d\n",frame_tx,slot_tx); - // the thread can now be woken up - AssertFatal(pthread_cond_signal(&ru_proc->cond_gNBs) == 0, - "[gNB] ERROR pthread_cond_signal for gNB TXnp4 thread\n"); - AssertFatal((ret=pthread_mutex_unlock(&ru_proc->mutex_gNBs))==0,"mutex_unlock returned %d\n",ret); - - } - return(0); -} - -int wakeup_tx(PHY_VARS_gNB *gNB,int frame_rx,int slot_rx,int frame_tx,int slot_tx,uint64_t timestamp_tx) { - - - gNB_L1_rxtx_proc_t *L1_proc_tx = &gNB->proc.L1_proc_tx; - - int ret; - - - AssertFatal((ret = pthread_mutex_lock(&L1_proc_tx->mutex))==0,"mutex_lock returns %d\n",ret); - - - while(L1_proc_tx->instance_cnt == 0) { - pthread_cond_wait(&L1_proc_tx->cond,&L1_proc_tx->mutex); - } - - L1_proc_tx->instance_cnt = 0; - - - L1_proc_tx->slot_rx = slot_rx; - L1_proc_tx->frame_rx = frame_rx; - L1_proc_tx->slot_tx = slot_tx; - L1_proc_tx->frame_tx = frame_tx; - L1_proc_tx->timestamp_tx = timestamp_tx; - - - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_TX1_UE,1); - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_TX1_UE,0); - // the thread can now be woken up - // the thread can now be woken up - AssertFatal(pthread_cond_signal(&L1_proc_tx->cond) == 0, "ERROR pthread_cond_signal for gNB L1 thread\n"); - - AssertFatal((ret=pthread_mutex_unlock(&L1_proc_tx->mutex))==0,"mutex_unlock returns %d\n",ret); - - return(0); -} - -int wakeup_rxtx(PHY_VARS_gNB *gNB,RU_t *ru) { - gNB_L1_proc_t *proc=&gNB->proc; - gNB_L1_rxtx_proc_t *L1_proc=&proc->L1_proc; - NR_DL_FRAME_PARMS *fp = &gNB->frame_parms; - RU_proc_t *ru_proc=&ru->proc; - int ret; - int i; - struct timespec abstime; - int time_ns = 50000; - int wait_timer = 0; - bool do_last_check = 1; - - AssertFatal((ret=pthread_mutex_lock(&proc->mutex_RU))==0,"mutex_lock returns %d\n",ret); - for (i=0; inum_RU; i++) { - if (ru == gNB->RU_list[i]) { - if ((proc->RU_mask&(1< 0) - LOG_E(PHY,"gNB %d frame %d, subframe %d : previous information from RU %d (num_RU %d,mask %x) has not been served yet!\n", - gNB->Mod_id,proc->frame_rx,proc->slot_rx,ru->idx,gNB->num_RU,proc->RU_mask); - proc->RU_mask |= (1<RU_mask != (1<num_RU)-1) { // not all RUs have provided their information so return - LOG_E(PHY,"Not all RUs have provided their info\n"); - AssertFatal((ret=pthread_mutex_unlock(&proc->mutex_RU))==0,"mutex_unlock returns %d\n",ret); - return(0); - } - else { // all RUs have provided their information so continue on and wakeup gNB processing - proc->RU_mask = 0; - AssertFatal((ret=pthread_mutex_unlock(&proc->mutex_RU))==0,"muex_unlock returns %d\n",ret); - } - - // wake up TX for subframe n+sf_ahead - // lock the TX mutex and make sure the thread is ready - while (wait_timer < 200) { - clock_gettime(CLOCK_REALTIME, &abstime); - abstime.tv_nsec = abstime.tv_nsec + time_ns; - - if (abstime.tv_nsec >= 1000*1000*1000) { - abstime.tv_nsec -= 1000*1000*1000; - abstime.tv_sec += 1; - } - - AssertFatal((ret=pthread_mutex_timedlock(&L1_proc->mutex, &abstime)) == 0,"mutex_lock returns %d\n", ret); - - if (L1_proc->instance_cnt == 0) { // L1_thread is busy so wait for a bit - AssertFatal((ret=pthread_mutex_unlock( &L1_proc->mutex))==0,"muex_unlock return %d\n",ret); - wait_timer += 50; - usleep(50); - } - else { - do_last_check = 0; - break; - } - } - if (do_last_check) { - AssertFatal((ret=pthread_mutex_timedlock(&L1_proc->mutex, &abstime)) == 0,"mutex_lock returns %d\n", ret); - if (L1_proc->instance_cnt == 0) { // L1_thread is busy so abort the subframe - AssertFatal((ret=pthread_mutex_unlock( &L1_proc->mutex))==0,"muex_unlock return %d\n",ret); - LOG_W(PHY,"L1_thread isn't ready in %d.%d, aborting RX processing\n",ru_proc->frame_rx,ru_proc->tti_rx); - return (-1); - } - } - - ++L1_proc->instance_cnt; - // We have just received and processed the common part of a subframe, say n. - // TS_rx is the last received timestamp (start of 1st slot), TS_tx is the desired - // transmitted timestamp of the next TX slot (first). - - // The last (TS_rx mod samples_per_frame) was n*samples_per_tti, - // we want to generate subframe (n+sf_ahead), so TS_tx = TX_rx+sf_ahead*samples_per_tti, - // and proc->slot_tx = proc->slot_rx+sf_ahead - L1_proc->timestamp_tx = ru_proc->timestamp_rx + (sf_ahead*fp->samples_per_subframe); - L1_proc->frame_rx = ru_proc->frame_rx; - L1_proc->slot_rx = ru_proc->tti_rx; - L1_proc->frame_tx = (L1_proc->slot_rx > (fp->slots_per_frame-1-(fp->slots_per_subframe*sf_ahead))) ? (L1_proc->frame_rx+1)&1023 : L1_proc->frame_rx; - L1_proc->slot_tx = (L1_proc->slot_rx + (fp->slots_per_subframe*sf_ahead))%fp->slots_per_frame; - - LOG_D(PHY,"wakeupL1: passing parameter IC = %d, RX: %d.%d, TX: %d.%d to L1 sf_ahead = %d\n", L1_proc->instance_cnt, L1_proc->frame_rx, L1_proc->slot_rx, L1_proc->frame_tx, L1_proc->slot_tx, sf_ahead); - - pthread_mutex_unlock( &L1_proc->mutex ); - - // the thread can now be woken up - if (pthread_cond_signal(&L1_proc->cond) != 0) { - LOG_E( PHY, "[gNB] ERROR pthread_cond_signal for gNB RXn-TXnp4 thread\n"); - exit_fun( "ERROR pthread_cond_signal" ); - return(-1); - } - - return(0); -} -/* -void wakeup_prach_gNB(PHY_VARS_gNB *gNB,RU_t *ru,int frame,int subframe) { - - gNB_L1_proc_t *proc = &gNB->proc; - LTE_DL_FRAME_PARMS *fp=&gNB->frame_parms; - int i; - - if (ru!=NULL) { - pthread_mutex_lock(&proc->mutex_RU_PRACH); - for (i=0;inum_RU;i++) { - if (ru == gNB->RU_list[i]) { - LOG_D(PHY,"frame %d, subframe %d: RU %d for gNB %d signals PRACH (mask %x, num_RU %d)\n",frame,subframe,i,gNB->Mod_id,proc->RU_mask_prach,gNB->num_RU); - if ((proc->RU_mask_prach&(1< 0) - LOG_E(PHY,"gNB %d frame %d, subframe %d : previous information (PRACH) from RU %d (num_RU %d, mask %x) has not been served yet!\n", - gNB->Mod_id,frame,subframe,ru->idx,gNB->num_RU,proc->RU_mask_prach); - proc->RU_mask_prach |= (1<RU_mask_prach != (1<num_RU)-1) { // not all RUs have provided their information so return - pthread_mutex_unlock(&proc->mutex_RU_PRACH); - return; - } - else { // all RUs have provided their information so continue on and wakeup gNB processing - proc->RU_mask_prach = 0; - pthread_mutex_unlock(&proc->mutex_RU_PRACH); - } - } - - // check if we have to detect PRACH first - if (is_prach_subframe(fp,frame,subframe)>0) { - LOG_D(PHY,"Triggering prach processing, frame %d, subframe %d\n",frame,subframe); - if (proc->instance_cnt_prach == 0) { - LOG_W(PHY,"[gNB] Frame %d Subframe %d, dropping PRACH\n", frame,subframe); - return; - } - - // wake up thread for PRACH RX - if (pthread_mutex_lock(&proc->mutex_prach) != 0) { - LOG_E( PHY, "[gNB] ERROR pthread_mutex_lock for gNB PRACH thread %d (IC %d)\n", proc->thread_index, proc->instance_cnt_prach); - exit_fun( "error locking mutex_prach" ); - return; - } - - ++proc->instance_cnt_prach; - // set timing for prach thread - proc->frame_prach = frame; - proc->subframe_prach = subframe; - - // the thread can now be woken up - if (pthread_cond_signal(&proc->cond_prach) != 0) { - LOG_E( PHY, "[gNB] ERROR pthread_cond_signal for gNB PRACH thread %d\n", proc->thread_index); - exit_fun( "ERROR pthread_cond_signal" ); - return; - } - - pthread_mutex_unlock( &proc->mutex_prach ); - } - -}*/ - -/*! - * \brief The prach receive thread of gNB. - * \param param is a \ref gNB_L1_proc_t structure which contains the info what to process. - * \returns a pointer to an int. The storage is not on the heap and must not be freed. - */ -/* -static void* gNB_thread_prach( void* param ) { - static int gNB_thread_prach_status; - - - PHY_VARS_gNB *gNB= (PHY_VARS_gNB *)param; - gNB_L1_proc_t *proc = &gNB->proc; - - // set default return value - gNB_thread_prach_status = 0; - - - - while (!oai_exit) { - - if (oai_exit) break; - - - if (wait_on_condition(&proc->mutex_prach,&proc->cond_prach,&proc->instance_cnt_prach,"gNB_prach_thread") < 0) break; - - LOG_D(PHY,"Running gNB prach procedures\n"); - prach_procedures(gNB ,0); - - if (release_thread(&proc->mutex_prach,&proc->instance_cnt_prach,"gNB_prach_thread") < 0) break; - } - - LOG_I(PHY, "Exiting gNB thread PRACH\n"); - - gNB_thread_prach_status = 0; - return &gNB_thread_prach_status; -} -*/ - -extern void init_td_thread(PHY_VARS_gNB *); -extern void init_te_thread(PHY_VARS_gNB *); - static void *process_stats_thread(void *param) { PHY_VARS_gNB *gNB = (PHY_VARS_gNB *)param; @@ -845,71 +365,13 @@ static void *process_stats_thread(void *param) { return(NULL); } - -void init_gNB_proc(int inst) { - int i=0; - int CC_id = 0; +void init_gNB_Tpool(int inst) { PHY_VARS_gNB *gNB; - gNB_L1_proc_t *proc; - gNB_L1_rxtx_proc_t *L1_proc,*L1_proc_tx; -// LOG_I(PHY,"%s(inst:%d) RC.nb_nr_CC[inst]:%d \n",__FUNCTION__,inst,RC.nb_nr_CC[inst]); gNB = RC.gNB[inst]; - LOG_I(PHY,"Initializing gNB processes instance:%d CC_id %d \n",inst,CC_id); - - proc = &gNB->proc; - L1_proc = &proc->L1_proc; - L1_proc_tx = &proc->L1_proc_tx; - L1_proc->instance_cnt = -1; - L1_proc_tx->instance_cnt = -1; - L1_proc->instance_cnt_RUs = 0; - L1_proc_tx->instance_cnt_RUs = 0; - proc->instance_cnt_prach = -1; - proc->instance_cnt_asynch_rxtx = -1; - proc->CC_id = CC_id; - proc->first_rx =1; - proc->first_tx =1; - proc->RU_mask =0; - proc->RU_mask_tx = (1<num_RU)-1; - proc->RU_mask_prach =0; - pthread_mutex_init( &gNB->UL_INFO_mutex, NULL); - pthread_mutex_init( &L1_proc->mutex, NULL); - pthread_mutex_init( &L1_proc_tx->mutex, NULL); - pthread_cond_init( &L1_proc->cond, NULL); - pthread_cond_init( &L1_proc_tx->cond, NULL); - pthread_mutex_init( &proc->mutex_prach, NULL); - pthread_mutex_init( &proc->mutex_asynch_rxtx, NULL); - pthread_mutex_init( &proc->mutex_RU,NULL); - pthread_mutex_init( &proc->mutex_RU_tx,NULL); - pthread_mutex_init( &proc->mutex_RU_PRACH,NULL); - pthread_cond_init( &proc->cond_prach, NULL); - pthread_cond_init( &proc->cond_asynch_rxtx, NULL); - LOG_I(PHY,"gNB->single_thread_flag:%d\n", gNB->single_thread_flag); - - if (get_thread_parallel_conf() == PARALLEL_RU_L1_SPLIT || get_thread_parallel_conf() == PARALLEL_RU_L1_TRX_SPLIT) { - threadCreate( &L1_proc->pthread, gNB_L1_thread, gNB, "L1_proc", -1, OAI_PRIORITY_RT ); - threadCreate( &L1_proc_tx->pthread, gNB_L1_thread_tx, gNB,"L1_proc_tx", -1, OAI_PRIORITY_RT); - } - - if(opp_enabled == 1) threadCreate(&proc->L1_stats_thread, process_stats_thread,(void *)gNB, "time_meas", -1, OAI_PRIORITY_RT_LOW); - //pthread_create( &proc->pthread_prach, attr_prach, gNB_thread_prach, gNB ); - char name[16]; - - if (gNB->single_thread_flag==0) { - snprintf( name, sizeof(name), "L1 %d", i ); - pthread_setname_np( L1_proc->pthread, name ); - snprintf( name, sizeof(name), "L1TX %d", i ); - pthread_setname_np( L1_proc_tx->pthread, name ); - } - - AssertFatal(proc->instance_cnt_prach == -1,"instance_cnt_prach = %d\n",proc->instance_cnt_prach); - - /* setup PHY proc TX sync mechanism */ - pthread_mutex_init(&sync_phy_proc.mutex_phy_proc_tx, NULL); - pthread_cond_init(&sync_phy_proc.cond_phy_proc_tx, NULL); - sync_phy_proc.phy_proc_CC_id = 0; + gNB_L1_proc_t *proc = &gNB->proc; + // ULSCH decoding threadpool gNB->threadPool = (tpool_t*)malloc(sizeof(tpool_t)); - gNB->respDecode = (notifiedFIFO_t*) malloc(sizeof(notifiedFIFO_t)); int numCPU = sysconf(_SC_NPROCESSORS_ONLN); int threadCnt = min(numCPU, gNB->pusch_proc_threads); char ul_pool[80]; @@ -920,70 +382,40 @@ void init_gNB_proc(int inst) { s_offset += 3; } initTpool(ul_pool, gNB->threadPool, false); + // ULSCH decoder result FIFO + gNB->respDecode = (notifiedFIFO_t*) malloc(sizeof(notifiedFIFO_t)); initNotifiedFIFO(gNB->respDecode); -} + // L1 RX result FIFO + gNB->resp_L1 = (notifiedFIFO_t*) malloc(sizeof(notifiedFIFO_t)); + initNotifiedFIFO(gNB->resp_L1); + + // L1 TX result FIFO + gNB->resp_L1_tx = (notifiedFIFO_t*) malloc(sizeof(notifiedFIFO_t)); + initNotifiedFIFO(gNB->resp_L1_tx); + + // RU TX result FIFO + gNB->resp_RU_tx = (notifiedFIFO_t*) malloc(sizeof(notifiedFIFO_t)); + initNotifiedFIFO(gNB->resp_RU_tx); + + // Stats measurement thread + if(opp_enabled == 1) threadCreate(&proc->L1_stats_thread, process_stats_thread,(void *)gNB, "time_meas", -1, OAI_PRIORITY_RT_LOW); +} /*! * \brief Terminate gNB TX and RX threads. */ void kill_gNB_proc(int inst) { - int *status; PHY_VARS_gNB *gNB; - gNB_L1_proc_t *proc; - gNB_L1_rxtx_proc_t *L1_proc, *L1_proc_tx; gNB=RC.gNB[inst]; - proc = &gNB->proc; - L1_proc = &proc->L1_proc; - L1_proc_tx = &proc->L1_proc_tx; - LOG_I(PHY, "Killing TX inst %d\n",inst ); - if (get_thread_parallel_conf() == PARALLEL_RU_L1_SPLIT || get_thread_parallel_conf() == PARALLEL_RU_L1_TRX_SPLIT) { - pthread_mutex_lock(&L1_proc->mutex); - L1_proc->instance_cnt = 0; - pthread_cond_signal(&L1_proc->cond); - pthread_mutex_unlock(&L1_proc->mutex); - pthread_mutex_lock(&L1_proc_tx->mutex); - L1_proc_tx->instance_cnt = 0; - pthread_cond_signal(&L1_proc_tx->cond); - pthread_mutex_unlock(&L1_proc_tx->mutex); - } - - proc->instance_cnt_prach = 0; - pthread_cond_signal( &proc->cond_prach ); - pthread_cond_signal( &proc->cond_asynch_rxtx ); - pthread_cond_broadcast(&sync_phy_proc.cond_phy_proc_tx); - // LOG_D(PHY, "joining pthread_prach\n"); - // pthread_join( proc->pthread_prach, (void**)&status ); - LOG_I(PHY, "Destroying prach mutex/cond\n"); - pthread_mutex_destroy( &proc->mutex_prach ); - pthread_cond_destroy( &proc->cond_prach ); LOG_I(PHY, "Destroying UL_INFO mutex\n"); pthread_mutex_destroy(&gNB->UL_INFO_mutex); - if (get_thread_parallel_conf() == PARALLEL_RU_L1_SPLIT || get_thread_parallel_conf() == PARALLEL_RU_L1_TRX_SPLIT) { - LOG_I(PHY, "Joining L1_proc mutex/cond\n"); - pthread_join( L1_proc->pthread, (void **)&status ); - LOG_I(PHY, "Joining L1_proc_tx mutex/cond\n"); - pthread_join( L1_proc_tx->pthread, (void **)&status ); - } - - LOG_I(PHY, "Destroying L1_proc mutex/cond\n"); - pthread_mutex_destroy( &L1_proc->mutex ); - pthread_cond_destroy( &L1_proc->cond ); - LOG_I(PHY, "Destroying L1_proc_tx mutex/cond\n"); - pthread_mutex_destroy( &L1_proc_tx->mutex ); - pthread_cond_destroy( &L1_proc_tx->cond ); - pthread_mutex_destroy( &proc->mutex_RU ); - pthread_mutex_destroy( &proc->mutex_RU_tx ); - } - - - void reset_opp_meas(void) { int sfn; reset_meas(&softmodem_stats_mt); @@ -1051,15 +483,9 @@ printf("after %p\n", gNB->common_vars.rxdataF[aa]); * (not tested in other modes). */ //init_precoding_weights(RC.gNB[inst]); - init_gNB_proc(inst); + init_gNB_Tpool(inst); } - for (ru_id=0; ru_idnr_wakeup_rxtx = wakeup_rxtx; - // RC.ru[ru_id]->wakeup_prach_eNB = wakeup_prach_gNB; - RC.ru[ru_id]->gNB_top = gNB_top; - } } void init_gNB(int single_thread_flag,int wait_for_sync) { diff --git a/executables/nr-ru.c b/executables/nr-ru.c index d0bc1a3e0e..1e8cae3adc 100644 --- a/executables/nr-ru.c +++ b/executables/nr-ru.c @@ -790,259 +790,6 @@ void tx_rf(RU_t *ru,int frame,int slot, uint64_t timestamp) { } } - - -/*! - * \brief The Asynchronous RX/TX FH thread of RAU/RCC/gNB/RRU. - * This handles the RX FH for an asynchronous RRU/UE - * \param param is a \ref gNB_L1_proc_t structure which contains the info what to process. - * \returns a pointer to an int. The storage is not on the heap and must not be freed. - */ -void *ru_thread_asynch_rxtx( void *param ) { - static int ru_thread_asynch_rxtx_status; - RU_t *ru = (RU_t *)param; - RU_proc_t *proc = &ru->proc; - nfapi_nr_config_request_scf_t *cfg = &ru->config; - int slot=0, frame=0; - // wait for top-level synchronization and do one acquisition to get timestamp for setting frame/subframe - wait_sync("ru_thread_asynch_rxtx"); - // wait for top-level synchronization and do one acquisition to get timestamp for setting frame/subframe - printf( "waiting for devices (ru_thread_asynch_rx)\n"); - wait_on_condition(&proc->mutex_asynch_rxtx,&proc->cond_asynch_rxtx,&proc->instance_cnt_asynch_rxtx,"thread_asynch"); - printf( "devices ok (ru_thread_asynch_rx)\n"); - - while (!oai_exit) { - - if (slot==ru->nr_frame_parms->slots_per_frame) { - slot=0; - frame++; - frame&=1023; - } else { - slot++; - } - - LOG_D(PHY,"ru_thread_asynch_rxtx: Waiting on incoming fronthaul\n"); - - // asynchronous receive from north (RRU IF4/IF5) - if (ru->fh_north_asynch_in) { - if ((nr_slot_select(cfg,frame,slot) & NR_DOWNLINK_SLOT)>0) - ru->fh_north_asynch_in(ru,&frame,&slot); - } else AssertFatal(1==0,"Unknown function in ru_thread_asynch_rxtx\n"); - } - - ru_thread_asynch_rxtx_status=0; - return(&ru_thread_asynch_rxtx_status); -} - - - - -/*! - * \brief The prach receive thread of RU. - * \param param is a \ref RU_proc_t structure which contains the info what to process. - * \returns a pointer to an int. The storage is not on the heap and must not be freed. - */ -void *ru_thread_prach( void *param ) { - static int ru_thread_prach_status; - RU_t *ru = (RU_t *)param; - RU_proc_t *proc = (RU_proc_t *)&ru->proc; - // set default return value - ru_thread_prach_status = 0; - - while (RC.ru_mask>0) { - usleep(1e6); - LOG_I(PHY,"%s() RACH waiting for RU to be configured\n", __FUNCTION__); - } - - LOG_I(PHY,"%s() RU configured - RACH processing thread running\n", __FUNCTION__); - - while (!oai_exit) { - - - if (wait_on_condition(&proc->mutex_prach,&proc->cond_prach,&proc->instance_cnt_prach,"ru_prach_thread") < 0) break; - - /*VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_RU_PRACH_RX, 1 ); - - if (ru->gNB_list[0]){ - prach_procedures( - ru->gNB_list[0],0 - ); - } - else { - rx_prach(NULL, - ru, - NULL, - NULL, - NULL, - proc->frame_prach, - 0,0 - ); - } - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_RU_PRACH_RX, 0 );*/ - if (release_thread(&proc->mutex_prach,&proc->instance_cnt_prach,"ru_prach_thread") < 0) break; - } - - LOG_I(PHY, "Exiting RU thread PRACH\n"); - ru_thread_prach_status = 0; - return &ru_thread_prach_status; -} - - -int wakeup_synch(RU_t *ru) { - struct timespec wait; - wait.tv_sec=0; - wait.tv_nsec=5000000L; - - // wake up synch thread - // lock the synch mutex and make sure the thread is ready - if (pthread_mutex_timedlock(&ru->proc.mutex_synch,&wait) != 0) { - LOG_E( PHY, "[RU] ERROR pthread_mutex_lock for RU synch thread (IC %d)\n", ru->proc.instance_cnt_synch ); - exit_fun( "error locking mutex_synch" ); - return(-1); - } - - ++ru->proc.instance_cnt_synch; - - // the thread can now be woken up - if (pthread_cond_signal(&ru->proc.cond_synch) != 0) { - LOG_E( PHY, "[RU] ERROR pthread_cond_signal for RU synch thread\n"); - exit_fun( "ERROR pthread_cond_signal" ); - return(-1); - } - - pthread_mutex_unlock( &ru->proc.mutex_synch ); - return(0); -} - -void do_ru_synch(RU_t *ru) { - NR_DL_FRAME_PARMS *fp = ru->nr_frame_parms; - RU_proc_t *proc = &ru->proc; - int i; - void *rxp[2],*rxp2[2]; - int32_t dummy_rx[ru->nb_rx][fp->samples_per_subframe] __attribute__((aligned(32))); - int rxs; - int ic; - - // initialize the synchronization buffer to the common_vars.rxdata - for (int i=0; inb_rx; i++) - rxp[i] = &ru->common.rxdata[i][0]; - - double temp_freq1 = ru->rfdevice.openair0_cfg->rx_freq[0]; - double temp_freq2 = ru->rfdevice.openair0_cfg->tx_freq[0]; - - for (i=0; i<4; i++) { - ru->rfdevice.openair0_cfg->rx_freq[i] = ru->rfdevice.openair0_cfg->tx_freq[i]; - ru->rfdevice.openair0_cfg->tx_freq[i] = temp_freq1; - } - - ru->rfdevice.trx_set_freq_func(&ru->rfdevice,ru->rfdevice.openair0_cfg,0); - - while ((ru->in_synch ==0)&&(!oai_exit)) { - // read in frame - rxs = ru->rfdevice.trx_read_func(&ru->rfdevice, - &(proc->timestamp_rx), - rxp, - fp->samples_per_subframe*10, - ru->nb_rx); - - if (rxs != fp->samples_per_subframe*10) LOG_E(PHY,"requested %d samples, got %d\n",fp->samples_per_subframe*10,rxs); - - // wakeup synchronization processing thread - wakeup_synch(ru); - ic=0; - - while ((ic>=0)&&(!oai_exit)) { - // continuously read in frames, 1ms at a time, - // until we are done with the synchronization procedure - for (i=0; inb_rx; i++) - rxp2[i] = (void *)&dummy_rx[i][0]; - - for (i=0; i<10; i++) - rxs = ru->rfdevice.trx_read_func(&ru->rfdevice, - &(proc->timestamp_rx), - rxp2, - fp->samples_per_subframe, - ru->nb_rx); - - pthread_mutex_lock(&ru->proc.mutex_synch); - ic = ru->proc.instance_cnt_synch; - pthread_mutex_unlock(&ru->proc.mutex_synch); - } // ic>=0 - } // in_synch==0 - - // read in rx_offset samples - LOG_I(PHY,"Resynchronizing by %d samples\n",ru->rx_offset); - rxs = ru->rfdevice.trx_read_func(&ru->rfdevice, - &(proc->timestamp_rx), - rxp, - ru->rx_offset, - ru->nb_rx); - - for (i=0; i<4; i++) { - ru->rfdevice.openair0_cfg->rx_freq[i] = temp_freq1; - ru->rfdevice.openair0_cfg->tx_freq[i] = temp_freq2; - } - - ru->rfdevice.trx_set_freq_func(&ru->rfdevice,ru->rfdevice.openair0_cfg,0); -} - - - -void wakeup_gNB_L1s(RU_t *ru) { - int i; - PHY_VARS_gNB **gNB_list = ru->gNB_list; - LOG_D(PHY,"wakeup_gNB_L1s (num %d) for RU %d ru->gNB_top:%p\n",ru->num_gNB,ru->idx, ru->gNB_top); - - if (ru->num_gNB==1 && ru->gNB_top!=0 && get_thread_parallel_conf() == PARALLEL_SINGLE_THREAD) { - // call gNB function directly - char string[20]; - sprintf(string,"Incoming RU %u",ru->idx); - LOG_D(PHY,"RU %d Call gNB_top\n",ru->idx); - ru->gNB_top(gNB_list[0],ru->proc.frame_rx,ru->proc.tti_rx,string,ru); - } else { - LOG_D(PHY,"ru->num_gNB:%d\n", ru->num_gNB); - - for (i=0; inum_gNB; i++) { - LOG_D(PHY,"ru->wakeup_rxtx:%p\n", ru->nr_wakeup_rxtx); - - if (ru->nr_wakeup_rxtx!=0 && ru->nr_wakeup_rxtx(gNB_list[i],ru) < 0) { - LOG_E(PHY,"could not wakeup gNB rxtx process for subframe %d\n", ru->proc.tti_rx); - } - } - } -} - -int wakeup_prach_ru(RU_t *ru) { - struct timespec wait; - wait.tv_sec=0; - wait.tv_nsec=5000000L; - - if (pthread_mutex_timedlock(&ru->proc.mutex_prach,&wait) !=0) { - LOG_E( PHY, "[RU] ERROR pthread_mutex_lock for RU prach thread (IC %d)\n", ru->proc.instance_cnt_prach); - exit_fun( "error locking mutex_rxtx" ); - return(-1); - } - - if (ru->proc.instance_cnt_prach==-1) { - ++ru->proc.instance_cnt_prach; - ru->proc.frame_prach = ru->proc.frame_rx; - ru->proc.subframe_prach = ru->proc.tti_rx; - - // DJP - think prach_procedures() is looking at gNB frame_prach - if (ru->gNB_list[0]) { - ru->gNB_list[0]->proc.frame_prach = ru->proc.frame_rx; - ru->gNB_list[0]->proc.slot_prach = ru->proc.tti_rx; - } - - LOG_I(PHY,"RU %d: waking up PRACH thread\n",ru->idx); - // the thread can now be woken up - AssertFatal(pthread_cond_signal(&ru->proc.cond_prach) == 0, "ERROR pthread_cond_signal for RU prach thread\n"); - } else LOG_W(PHY,"RU prach thread busy, skipping\n"); - - pthread_mutex_unlock( &ru->proc.mutex_prach ); - return(0); -} - // this is for RU with local RF unit void fill_rf_config(RU_t *ru, char *rf_config_file) { int i; @@ -1052,58 +799,21 @@ void fill_rf_config(RU_t *ru, char *rf_config_file) { int mu = config->ssb_config.scs_common.value; int N_RB = config->carrier_config.dl_grid_size[config->ssb_config.scs_common.value].value; - if (mu == NR_MU_0) { //or if LTE - if(N_RB == 100) { - if (fp->threequarter_fs) { - cfg->sample_rate=23.04e6; - cfg->samples_per_frame = 230400; - cfg->tx_bw = 10e6; - cfg->rx_bw = 10e6; - } else { - cfg->sample_rate=30.72e6; - cfg->samples_per_frame = 307200; - cfg->tx_bw = 10e6; - cfg->rx_bw = 10e6; - } - } else if(N_RB == 50) { - cfg->sample_rate=15.36e6; - cfg->samples_per_frame = 153600; - cfg->tx_bw = 5e6; - cfg->rx_bw = 5e6; - } else if (N_RB == 25) { - cfg->sample_rate=7.68e6; - cfg->samples_per_frame = 76800; - cfg->tx_bw = 2.5e6; - cfg->rx_bw = 2.5e6; - } else if (N_RB == 6) { - cfg->sample_rate=1.92e6; - cfg->samples_per_frame = 19200; - cfg->tx_bw = 1.5e6; - cfg->rx_bw = 1.5e6; - } else AssertFatal(1==0,"Unknown N_RB %d\n",N_RB); - } else if (mu == NR_MU_1) { - if(N_RB == 273) { - if (fp->threequarter_fs) { - AssertFatal(0 == 1,"three quarter sampling not supported for N_RB 273\n"); - } else { - cfg->sample_rate=122.88e6; - cfg->samples_per_frame = 1228800; - cfg->tx_bw = 100e6; - cfg->rx_bw = 100e6; - } - } else if(N_RB == 217) { + if (mu == NR_MU_0) { + switch(N_RB) { + case 270: if (fp->threequarter_fs) { cfg->sample_rate=92.16e6; cfg->samples_per_frame = 921600; - cfg->tx_bw = 80e6; - cfg->rx_bw = 80e6; + cfg->tx_bw = 50e6; + cfg->rx_bw = 50e6; } else { - cfg->sample_rate=122.88e6; - cfg->samples_per_frame = 1228800; - cfg->tx_bw = 80e6; - cfg->rx_bw = 80e6; + cfg->sample_rate=61.44e6; + cfg->samples_per_frame = 614400; + cfg->tx_bw = 50e6; + cfg->rx_bw = 50e6; } - } else if(N_RB == 106) { + case 216: if (fp->threequarter_fs) { cfg->sample_rate=46.08e6; cfg->samples_per_frame = 460800; @@ -1116,20 +826,154 @@ void fill_rf_config(RU_t *ru, char *rf_config_file) { cfg->tx_bw = 40e6; cfg->rx_bw = 40e6; } - } else { + break; + case 106: + if (fp->threequarter_fs) { + cfg->sample_rate=23.04e6; + cfg->samples_per_frame = 230400; + cfg->tx_bw = 20e6; + cfg->rx_bw = 20e6; + } + else { + cfg->sample_rate=30.72e6; + cfg->samples_per_frame = 307200; + cfg->tx_bw = 20e6; + cfg->rx_bw = 20e6; + } + break; + case 52: + if (fp->threequarter_fs) { + cfg->sample_rate=11.52e6; + cfg->samples_per_frame = 115200; + cfg->tx_bw = 10e6; + cfg->rx_bw = 10e6; + } + else { + cfg->sample_rate=15.36e6; + cfg->samples_per_frame = 153600; + cfg->tx_bw = 10e6; + cfg->rx_bw = 10e6; + } + case 25: + if (fp->threequarter_fs) { + cfg->sample_rate=5.76e6; + cfg->samples_per_frame = 57600; + cfg->tx_bw = 5e6; + cfg->rx_bw = 5e6; + } + else { + cfg->sample_rate=7.68e6; + cfg->samples_per_frame = 76800; + cfg->tx_bw = 5e6; + cfg->rx_bw = 5e6; + } + break; + default: + AssertFatal(0==1,"N_RB %d not yet supported for numerology %d\n",N_RB,mu); + } + } else if (mu == NR_MU_1) { + switch(N_RB) { + case 273: + if (fp->threequarter_fs) { + cfg->sample_rate=184.32e6; + cfg->samples_per_frame = 1843200; + cfg->tx_bw = 100e6; + cfg->rx_bw = 100e6; + } else { + cfg->sample_rate=122.88e6; + cfg->samples_per_frame = 1228800; + cfg->tx_bw = 100e6; + cfg->rx_bw = 100e6; + } + break; + case 217: + if (fp->threequarter_fs) { + cfg->sample_rate=92.16e6; + cfg->samples_per_frame = 921600; + cfg->tx_bw = 80e6; + cfg->rx_bw = 80e6; + } else { + cfg->sample_rate=122.88e6; + cfg->samples_per_frame = 1228800; + cfg->tx_bw = 80e6; + cfg->rx_bw = 80e6; + } + break; + case 106: + if (fp->threequarter_fs) { + cfg->sample_rate=46.08e6; + cfg->samples_per_frame = 460800; + cfg->tx_bw = 40e6; + cfg->rx_bw = 40e6; + } + else { + cfg->sample_rate=61.44e6; + cfg->samples_per_frame = 614400; + cfg->tx_bw = 40e6; + cfg->rx_bw = 40e6; + } + break; + case 51: + if (fp->threequarter_fs) { + cfg->sample_rate=23.04e6; + cfg->samples_per_frame = 230400; + cfg->tx_bw = 20e6; + cfg->rx_bw = 20e6; + } + else { + cfg->sample_rate=30.72e6; + cfg->samples_per_frame = 307200; + cfg->tx_bw = 20e6; + cfg->rx_bw = 20e6; + } + break; + case 24: + if (fp->threequarter_fs) { + cfg->sample_rate=11.52e6; + cfg->samples_per_frame = 115200; + cfg->tx_bw = 10e6; + cfg->rx_bw = 10e6; + } + else { + cfg->sample_rate=15.36e6; + cfg->samples_per_frame = 153600; + cfg->tx_bw = 10e6; + cfg->rx_bw = 10e6; + } + break; + default: AssertFatal(0==1,"N_RB %d not yet supported for numerology %d\n",N_RB,mu); } } else if (mu == NR_MU_3) { - if (N_RB == 66) { - cfg->sample_rate = 122.88e6; - cfg->samples_per_frame = 1228800; - cfg->tx_bw = 100e6; - cfg->rx_bw = 100e6; - } else if(N_RB == 32) { - cfg->sample_rate=61.44e6; - cfg->samples_per_frame = 614400; - cfg->tx_bw = 50e6; - cfg->rx_bw = 50e6; + switch(N_RB) { + case 66: + if (fp->threequarter_fs) { + cfg->sample_rate=184.32e6; + cfg->samples_per_frame = 1843200; + cfg->tx_bw = 100e6; + cfg->rx_bw = 100e6; + } else { + cfg->sample_rate = 122.88e6; + cfg->samples_per_frame = 1228800; + cfg->tx_bw = 100e6; + cfg->rx_bw = 100e6; + } + break; + case 32: + if (fp->threequarter_fs) { + cfg->sample_rate=92.16e6; + cfg->samples_per_frame = 921600; + cfg->tx_bw = 50e6; + cfg->rx_bw = 50e6; + } else { + cfg->sample_rate=61.44e6; + cfg->samples_per_frame = 614400; + cfg->tx_bw = 50e6; + cfg->rx_bw = 50e6; + } + break; + default: + AssertFatal(0==1,"N_RB %d not yet supported for numerology %d\n",N_RB,mu); } } else { AssertFatal(0 == 1,"Numerology %d not supported for the moment\n",mu); @@ -1176,60 +1020,52 @@ int setup_RU_buffers(RU_t *ru) { int i,j; int card,ant; //uint16_t N_TA_offset = 0; - NR_DL_FRAME_PARMS *frame_parms; + NR_DL_FRAME_PARMS *fp; nfapi_nr_config_request_scf_t *config = &ru->config; if (ru) { - frame_parms = ru->nr_frame_parms; - printf("setup_RU_buffers: frame_parms = %p\n",frame_parms); + fp = ru->nr_frame_parms; + printf("setup_RU_buffers: frame_parms = %p\n",fp); } else { printf("ru pointer is NULL\n"); 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; - if (config->cell_config.frame_duplex_type.value == TDD) { int N_TA_offset = config->carrier_config.uplink_frequency.value < 6000000 ? 400 : 431; // reference samples for 25600Tc @ 30.72 Ms/s for FR1, same @ 61.44 Ms/s for FR2 double factor=1; - switch (mu) { - case 0: //15 kHz scs - AssertFatal(N_TA_offset == 400,"scs_common 15kHz only for FR1\n"); - if (N_RB <= 25) factor = .25; // 7.68 Ms/s - else if (N_RB <=50) factor = .5; // 15.36 Ms/s - else if (N_RB <=75) factor = 1.0; // 30.72 Ms/s - else if (N_RB <=100) factor = 1.0; // 30.72 Ms/s - else AssertFatal(1==0,"Too many PRBS for mu=0\n"); - break; - case 1: //30 kHz sc - AssertFatal(N_TA_offset == 400,"scs_common 30kHz only for FR1\n"); - if (N_RB <= 106) factor = 2.0; // 61.44 Ms/s - else if (N_RB <= 275) factor = 4.0; // 122.88 Ms/s - break; - case 2: //60 kHz scs - AssertFatal(1==0,"scs_common should not be 60 kHz\n"); - break; - case 3: //120 kHz scs - AssertFatal(N_TA_offset == 431,"scs_common 120kHz only for FR2\n"); - break; - case 4: //240 kHz scs - AssertFatal(1==0,"scs_common should not be 60 kHz\n"); - if (N_RB <= 32) factor = 1.0; // 61.44 Ms/s - else if (N_RB <= 66) factor = 2.0; // 122.88 Ms/s - else AssertFatal(1==0,"N_RB %d is too big for curretn FR2 implementation\n",N_RB); - break; - - if (N_RB == 100) ru->N_TA_offset = 624; - else if (N_RB == 50) ru->N_TA_offset = 624/2; - else if (N_RB == 25) ru->N_TA_offset = 624/4; + case 0: //15 kHz scs + AssertFatal(N_TA_offset == 400, "scs_common 15kHz only for FR1\n"); + factor = fp->samples_per_subframe / 30720.0; + break; + case 1: //30 kHz sc + AssertFatal(N_TA_offset == 400, "scs_common 30kHz only for FR1\n"); + factor = fp->samples_per_subframe / 30720.0; + break; + case 2: //60 kHz scs + AssertFatal(1==0, "scs_common should not be 60 kHz\n"); + break; + case 3: //120 kHz scs + AssertFatal(N_TA_offset == 431, "scs_common 120kHz only for FR2\n"); + factor = fp->samples_per_subframe / 61440.0; + break; + case 4: //240 kHz scs + AssertFatal(N_TA_offset == 431, "scs_common 240kHz only for FR2\n"); + factor = fp->samples_per_subframe / 61440.0; + break; + default: + AssertFatal(1==0, "Invalid scs_common!\n"); } - if (frame_parms->threequarter_fs == 1) factor = factor*.75; + ru->N_TA_offset = (int)(N_TA_offset * factor); - LOG_I(PHY,"RU %d Setting N_TA_offset to %d samples (factor %f, UL Freq %d, N_RB %d)\n",ru->idx,ru->N_TA_offset,factor, - config->carrier_config.uplink_frequency.value, N_RB); + + LOG_I(PHY,"RU %d Setting N_TA_offset to %d samples (factor %f, UL Freq %d, N_RB %d, mu %d)\n",ru->idx,ru->N_TA_offset,factor, + config->carrier_config.uplink_frequency.value, N_RB, mu); } else ru->N_TA_offset = 0; @@ -1301,136 +1137,61 @@ void *ru_stats_thread(void *param) { return(NULL); } -void *ru_thread_tx( void *param ) { - RU_t *ru = (RU_t *)param; - RU_proc_t *proc = &ru->proc; - NR_DL_FRAME_PARMS *fp = ru->nr_frame_parms; - PHY_VARS_gNB *gNB; - gNB_L1_proc_t *gNB_proc; - gNB_L1_rxtx_proc_t *L1_proc; - char filename[40]; - int print_frame = 8; - int i = 0; - int ret; - +void ru_tx_func(void *param) { - wait_on_condition(&proc->mutex_FH1,&proc->cond_FH1,&proc->instance_cnt_FH1,"ru_thread_tx"); - printf( "ru_thread_tx ready\n"); + 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]; - while (!oai_exit) { + // do TX front-end processing if needed (precoding and/or IDFTs) + if (ru->feptx_prec) ru->feptx_prec(ru,frame_tx,slot_tx); - LOG_D(PHY,"ru_thread_tx: Waiting for TX processing\n"); - // wait until eNBs are finished subframe RX n and TX n+4 + // do OFDM with/without TX front-end processing if needed + if ((ru->fh_north_asynch_in == NULL) && (ru->feptx_ofdm)) ru->feptx_ofdm(ru,frame_tx,slot_tx); - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_RU_TX_WAIT, 1 ); - wait_on_condition(&proc->mutex_gNBs,&proc->cond_gNBs,&proc->instance_cnt_gNBs,"ru_thread_tx"); - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_RU_TX_WAIT, 0 ); + 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); - ret = pthread_mutex_lock(&proc->mutex_gNBs); - AssertFatal(ret == 0,"mutex_lock return %d\n",ret); - int frame_tx=proc->frame_tx; - int tti_tx =proc->tti_tx; - uint64_t timestamp_tx = proc->timestamp_tx; + if (ru->fh_north_out) ru->fh_north_out(ru); + } else { + if(frame_tx == print_frame) { + for (int i=0; inb_tx; i++) { - ret = pthread_mutex_unlock(&proc->mutex_gNBs); - AssertFatal(ret == 0,"mutex_lock returns %d\n",ret); + 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); - if (oai_exit) break; + 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); - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_TX0_RU, frame_tx ); - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TTI_NUMBER_TX0_RU, tti_tx ); - - // do TX front-end processing if needed (precoding and/or IDFTs) - if (ru->feptx_prec) ru->feptx_prec(ru,frame_tx,tti_tx); - - // do OFDM with/without TX front-end processing if needed - if ((ru->fh_north_asynch_in == NULL) && (ru->feptx_ofdm)) ru->feptx_ofdm(ru,frame_tx,tti_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,tti_tx,timestamp_tx); - - if (ru->fh_north_out) ru->fh_north_out(ru); - } else { - if(proc->frame_tx == print_frame) { - for (i=0; inb_tx; i++) { - - if(proc->tti_tx == 0) { - sprintf(filename,"gNBdataF_frame%d_sl%d.m", print_frame, proc->tti_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, proc->tti_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, proc->tti_tx); - LOG_M(filename,"txdataF_BF_frame",&ru->common.txdataF_BF[i][0],fp->samples_per_subframe_wCP, 1, 1); - } - - if(proc->tti_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(proc->tti_tx == 9) - }//for (i=0; inb_tx; i++) - }//if(proc->frame_tx == print_frame) - }//else emulate_rf - - release_thread(&proc->mutex_gNBs,&proc->instance_cnt_gNBs,"ru_thread_tx"); - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_RX1_UE, proc->instance_cnt_gNBs); - - for(i = 0; inum_gNB; i++) { - gNB = ru->gNB_list[i]; - gNB_proc = &gNB->proc; - L1_proc = (get_thread_parallel_conf() == PARALLEL_RU_L1_TRX_SPLIT)? &gNB_proc->L1_proc_tx : &gNB_proc->L1_proc; - ret = pthread_mutex_lock(&gNB_proc->mutex_RU_tx); - AssertFatal(ret == 0,"mutex_lock returns %d\n",ret); - - for (int j=0; jnum_RU; j++) { - if (ru == gNB->RU_list[j]) { - if ((gNB_proc->RU_mask_tx&(1< 0) - LOG_E(PHY,"gNB %d frame %d, subframe %d : previous information from RU tx %d (num_RU %d,mask %x) has not been served yet!\n", - gNB->Mod_id,gNB_proc->frame_rx,gNB_proc->slot_rx,ru->idx,gNB->num_RU,gNB_proc->RU_mask_tx); - - gNB_proc->RU_mask_tx |= (1<common.txdataF_BF[i][0],fp->samples_per_subframe_wCP, 1, 1); } - } - if (gNB_proc->RU_mask_tx != (1<num_RU)-1) { // not all RUs have provided their information so return - ret = pthread_mutex_unlock(&gNB_proc->mutex_RU_tx); - AssertFatal(ret == 0,"mutex_unlock returns %d\n",ret); - } else { // all RUs TX are finished so send the ready signal to gNB processing - gNB_proc->RU_mask_tx = 0; - ret = pthread_mutex_unlock(&gNB_proc->mutex_RU_tx); - AssertFatal(ret == 0,"mutex_unlock returns %d\n",ret); + 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"); - ret = pthread_mutex_lock(&L1_proc->mutex_RUs_tx); - AssertFatal(ret == 0,"mutex_lock returns %d\n",ret); - // the thread can now be woken up - if (L1_proc->instance_cnt_RUs == -1) { - L1_proc->instance_cnt_RUs = 0; - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_RX0_UE,L1_proc->instance_cnt_RUs); - AssertFatal(pthread_cond_signal(&L1_proc->cond_RUs) == 0, - "ERROR pthread_cond_signal for gNB_L1_thread\n"); - } //else AssertFatal(1==0,"gNB TX thread is not ready\n"); - ret = pthread_mutex_unlock(&L1_proc->mutex_RUs_tx); - AssertFatal(ret == 0,"mutex_unlock returns %d\n",ret); - } - } - } - - release_thread(&proc->mutex_FH1,&proc->instance_cnt_FH1,"ru_thread_tx"); - return 0; + 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 } void *ru_thread( void *param ) { @@ -1438,12 +1199,11 @@ void *ru_thread( void *param ) { RU_t *ru = (RU_t *)param; RU_proc_t *proc = &ru->proc; NR_DL_FRAME_PARMS *fp = ru->nr_frame_parms; + PHY_VARS_gNB *gNB = RC.gNB[0]; int ret; int slot = fp->slots_per_frame-1; int frame = 1023; - char filename[40], threadname[40]; - int print_frame = 8; - int i = 0; + char threadname[40]; int aa; nfapi_nr_config_request_scf_t *cfg = &ru->config; @@ -1503,6 +1263,15 @@ void *ru_thread( void *param ) { pthread_mutex_unlock(&RC.ru_mutex); wait_sync("ru_thread"); + notifiedFIFO_elt_t *msg = newNotifiedFIFO_elt(sizeof(processingData_L1_t),0,gNB->resp_L1,rx_func); + notifiedFIFO_elt_t *msgL1Tx = newNotifiedFIFO_elt(sizeof(processingData_L1_t),0,gNB->resp_L1_tx,tx_func); + notifiedFIFO_elt_t *msgRUTx = newNotifiedFIFO_elt(sizeof(processingData_L1_t),0,gNB->resp_RU_tx,ru_tx_func); + processingData_L1_t *syncMsg; + notifiedFIFO_elt_t *res; + pushNotifiedFIFO(gNB->resp_L1,msg); // to unblock the process in the beginning + pushNotifiedFIFO(gNB->resp_L1_tx,msgL1Tx); // to unblock the process in the beginning + pushNotifiedFIFO(gNB->resp_RU_tx,msgRUTx); // to unblock the process in the beginning + if(!emulate_rf) { // Start RF device if any if (ru->start_rf) { @@ -1511,19 +1280,6 @@ void *ru_thread( void *param ) { else LOG_I(PHY,"RU %d rf device ready\n",ru->idx); } else LOG_I(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 - - if ((ru->fh_south_asynch_in)||(ru->fh_north_asynch_in)) { - pthread_mutex_lock(&proc->mutex_asynch_rxtx); - proc->instance_cnt_asynch_rxtx=0; - pthread_mutex_unlock(&proc->mutex_asynch_rxtx); - pthread_cond_signal(&proc->cond_asynch_rxtx); - } else LOG_I(PHY,"RU %d no asynch_south interface\n",ru->idx); - - // if this is a slave RRU, try to synchronize on the DL frequency - if ((ru->is_slave) && (ru->if_south == LOCAL_RF)) do_ru_synch(ru); - // start trx write thread if(usrp_tx_thread == 1){ if (ru->start_write_thread){ @@ -1537,11 +1293,6 @@ void *ru_thread( void *param ) { } } - pthread_mutex_lock(&proc->mutex_FH1); - proc->instance_cnt_FH1 = 0; - pthread_mutex_unlock(&proc->mutex_FH1); - pthread_cond_signal(&proc->cond_FH1); - // 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); @@ -1585,24 +1336,17 @@ void *ru_thread( void *param ) { if (ru->fh_south_in) ru->fh_south_in(ru,&frame,&slot); else AssertFatal(1==0, "No fronthaul interface at south port"); + proc->timestamp_tx = proc->timestamp_rx + (sf_ahead*fp->samples_per_subframe); + proc->frame_tx = (proc->tti_rx > (fp->slots_per_frame-1-(fp->slots_per_subframe*sf_ahead))) ? (proc->frame_rx+1)&1023 : proc->frame_rx; + proc->tti_tx = (proc->tti_rx + (fp->slots_per_subframe*sf_ahead))%fp->slots_per_frame; + LOG_D(PHY,"AFTER fh_south_in - SFN/SL:%d%d RU->proc[RX:%d.%d TX:%d.%d] RC.gNB[0]:[RX:%d%d TX(SFN):%d]\n", frame,slot, proc->frame_rx,proc->tti_rx, proc->frame_tx,proc->tti_tx, RC.gNB[0]->proc.frame_rx,RC.gNB[0]->proc.slot_rx, - RC.gNB[0]->proc.frame_tx); - /* - LOG_D(PHY,"RU thread (do_prach %d, is_prach_subframe %d), received frame %d, subframe %d\n", - ru->do_prach, - is_prach_subframe(fp, proc->frame_rx, proc->tti_rx), - proc->frame_rx,proc->tti_rx); + RC.gNB[0]->proc.frame_tx); - if ((ru->do_prach>0) && (is_prach_subframe(fp, proc->frame_rx, proc->tti_rx)==1)) { - wakeup_prach_ru(ru); - }*/ - - // adjust for timing offset between RU - //printf("~~~~~~~~~~~~~~~~~~~~~~~~~~%d.%d in ru_thread is in process\n", proc->frame_rx, proc->tti_rx); if (ru->idx!=0) proc->frame_tx = (proc->frame_tx+proc->frame_offset)&1023; // do RX front-end processing (frequency-shift, dft) if needed @@ -1615,7 +1359,6 @@ void *ru_thread( void *param ) { if (slot == 8) slot_type = NR_UPLINK_SLOT; if (slot_type == NR_UPLINK_SLOT || slot_type == NR_MIXED_SLOT) { - //if (proc->tti_rx==8) { if (ru->feprx) { ru->feprx(ru,proc->tti_rx); @@ -1665,50 +1408,17 @@ void *ru_thread( void *param ) { } // At this point, all information for subframe has been received on FH interface + res = pullTpool(gNB->resp_L1, gNB->threadPool); + syncMsg = (processingData_L1_t *)NotifiedFifoData(res); + syncMsg->gNB = gNB; + syncMsg->frame_rx = proc->frame_rx; + syncMsg->slot_rx = proc->tti_rx; + syncMsg->frame_tx = proc->frame_tx; + syncMsg->slot_tx = proc->tti_tx; + syncMsg->timestamp_tx = proc->timestamp_tx; + res->key = proc->tti_rx; + pushTpool(gNB->threadPool, res); - // wakeup all gNB processes waiting for this RU - if (ru->num_gNB>0) wakeup_gNB_L1s(ru); - - if(get_thread_parallel_conf() == PARALLEL_SINGLE_THREAD || ru->num_gNB==0) { - // do TX front-end processing if needed (precoding and/or IDFTs) - if (ru->feptx_prec) ru->feptx_prec(ru,proc->frame_tx,proc->tti_tx); - - // do OFDM with/without TX front-end processing if needed - if ((ru->fh_north_asynch_in == NULL) && (ru->feptx_ofdm)) ru->feptx_ofdm(ru,proc->frame_tx,proc->tti_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,proc->frame_tx,proc->tti_tx,proc->timestamp_tx); - - if (ru->fh_north_out) ru->fh_north_out(ru); - } else { - if(proc->frame_tx == print_frame) { - for (i=0; inb_tx; i++) { - sprintf(filename,"tx%ddataF_frame%d_sl%d.m", i, print_frame, proc->tti_tx); - LOG_M(filename,"txdataF_frame",&ru->common.txdataF_BF[i][0],fp->samples_per_slot_wCP, 1, 1); - - if(proc->tti_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(proc->tti_tx == 9) - }//for (i=0; inb_tx; i++) - }//if(proc->frame_tx == print_frame) - }//else emulate_rf - - proc->emulate_rf_busy = 0; - }//if(get_thread_parallel_conf() == PARALLEL_SINGLE_THREAD) } printf( "Exiting ru_thread \n"); @@ -1719,85 +1429,13 @@ void *ru_thread( void *param ) { else LOG_I(PHY,"RU %d rf device stopped\n",ru->idx); } + delNotifiedFIFO_elt(msg); + delNotifiedFIFO_elt(msgL1Tx); + delNotifiedFIFO_elt(msgRUTx); + ru_thread_status = 0; return &ru_thread_status; } -/* -// This thread run the initial synchronization like a UE -void *ru_thread_synch(void *arg) { - - RU_t *ru = (RU_t*)arg; - NR_DL_FRAME_PARMS *fp=ru->nr_frame_parms; - int32_t sync_pos,sync_pos2; - uint32_t peak_val; - uint32_t sync_corr[307200] __attribute__((aligned(32))); - static int ru_thread_synch_status; - - - - wait_sync("ru_thread_synch"); - - // initialize variables for PSS detection - lte_sync_time_init(ru->nr_frame_parms); - - while (!oai_exit) { - - // wait to be woken up - if (wait_on_condition(&ru->proc.mutex_synch,&ru->proc.cond_synch,&ru->proc.instance_cnt_synch,"ru_thread_synch")<0) break; - - // if we're not in synch, then run initial synch - if (ru->in_synch == 0) { - // run intial synch like UE - LOG_I(PHY,"Running initial synchronization\n"); - - sync_pos = lte_sync_time_gNB(ru->common.rxdata, - fp, - fp->samples_per_subframe*5, - &peak_val, - sync_corr); - LOG_I(PHY,"RU synch: %d, val %d\n",sync_pos,peak_val); - - if (sync_pos >= 0) { - if (sync_pos >= fp->nb_prefix_samples) - sync_pos2 = sync_pos - fp->nb_prefix_samples; - else - sync_pos2 = sync_pos + (fp->samples_per_subframe*10) - fp->nb_prefix_samples; - - if (fp->frame_type == FDD) { - - // PSS is hypothesized in last symbol of first slot in Frame - int sync_pos_slot = (fp->samples_per_subframe>>1) - fp->ofdm_symbol_size - fp->nb_prefix_samples; - - if (sync_pos2 >= sync_pos_slot) - ru->rx_offset = sync_pos2 - sync_pos_slot; - else - ru->rx_offset = (fp->samples_per_subframe*10) + sync_pos2 - sync_pos_slot; - } - else { - - } - - LOG_I(PHY,"Estimated sync_pos %d, peak_val %d => timing offset %d\n",sync_pos,peak_val,ru->rx_offset); - - if ((peak_val > 300000) && (sync_pos > 0)) { - // if (sync_pos++ > 3) { - write_output("ru_sync.m","sync",(void*)&sync_corr[0],fp->samples_per_subframe*5,1,2); - write_output("ru_rx.m","rxs",(void*)ru->ru_time.rxdata[0][0],fp->samples_per_subframe*10,1,1); - exit(-1); - } - - ru->in_synch=1; - } - } - - if (release_thread(&ru->proc.mutex_synch,&ru->proc.instance_cnt_synch,"ru_synch_thread") < 0) break; - } // oai_exit - - ru_thread_synch_status = 0; - return &ru_thread_synch_status; - -} -*/ int nr_start_if(struct RU_t_s *ru, struct PHY_VARS_gNB_s *gNB) { return(ru->ifdevice.trx_start_func(&ru->ifdevice)); @@ -1819,17 +1457,10 @@ int start_write_thread(RU_t *ru) { void init_RU_proc(RU_t *ru) { int i=0; RU_proc_t *proc; - char name[100]; LOG_I(PHY,"Initializing RU proc %d (%s,%s),\n",ru->idx,NB_functions[ru->function],NB_timing[ru->if_timing]); proc = &ru->proc; memset((void *)proc,0,sizeof(RU_proc_t)); proc->ru = ru; - proc->instance_cnt_prach = -1; - proc->instance_cnt_synch = -1; - proc->instance_cnt_FH = -1; - proc->instance_cnt_FH1 = -1; - proc->instance_cnt_gNBs = -1; - proc->instance_cnt_asynch_rxtx = -1; proc->instance_cnt_emulateRF = -1; proc->first_rx = 1; proc->first_tx = 1; @@ -1840,44 +1471,13 @@ void init_RU_proc(RU_t *ru) { for (i=0; i<10; i++) proc->symbol_mask[i]=0; - pthread_mutex_init( &proc->mutex_prach, NULL); - pthread_mutex_init( &proc->mutex_asynch_rxtx, NULL); - 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_gNBs, 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_gNBs, NULL); threadCreate( &proc->pthread_FH, ru_thread, (void *)ru, "thread_FH", -1, OAI_PRIORITY_RT_MAX ); - if (get_thread_parallel_conf() == PARALLEL_RU_L1_SPLIT || get_thread_parallel_conf() == PARALLEL_RU_L1_TRX_SPLIT) - threadCreate( &proc->pthread_FH1, ru_thread_tx, (void *)ru, "thread_FH1", -1, OAI_PRIORITY_RT ); - if(emulate_rf) threadCreate( &proc->pthread_emulateRF, emulatedRF_thread, (void *)proc, "emulateRF", -1, OAI_PRIORITY_RT ); - if (ru->function == NGFI_RRU_IF4p5) { - threadCreate( &proc->pthread_prach, ru_thread_prach, (void *)ru, "RACH", -1, OAI_PRIORITY_RT ); - ///tmp deactivation of synch thread - // if (ru->is_slave == 1) pthread_create( &proc->pthread_synch, attr_synch, ru_thread_synch, (void*)ru); - - if ((ru->if_timing == synch_to_other) || - (ru->function == NGFI_RRU_IF5) || - (ru->function == NGFI_RRU_IF4p5)) threadCreate( &proc->pthread_asynch_rxtx, ru_thread_asynch_rxtx, (void *)ru, "asynch_rxtx", -1, OAI_PRIORITY_RT ); - - snprintf( name, sizeof(name), "ru_thread_FH %d", ru->idx ); - pthread_setname_np( proc->pthread_FH, name ); - } else if (ru->function == gNodeB_3GPP && ru->if_south == LOCAL_RF) { // DJP - need something else to distinguish between monolithic and PNF - LOG_I(PHY,"%s() DJP - added creation of pthread_prach\n", __FUNCTION__); - threadCreate( &proc->pthread_prach, ru_thread_prach, (void *)ru,"RACH", -1, OAI_PRIORITY_RT ); - } - if (get_thread_worker_conf() == WORKER_ENABLE) { if (ru->feprx) nr_init_feprx_thread(ru); @@ -1890,46 +1490,9 @@ void init_RU_proc(RU_t *ru) { void kill_NR_RU_proc(int inst) { RU_t *ru = RC.ru[inst]; RU_proc_t *proc = &ru->proc; - pthread_mutex_lock(&proc->mutex_FH); - proc->instance_cnt_FH = 0; - pthread_mutex_unlock(&proc->mutex_FH); - pthread_cond_signal(&proc->cond_FH); - pthread_mutex_lock(&proc->mutex_prach); - proc->instance_cnt_prach = 0; - pthread_mutex_unlock(&proc->mutex_prach); - pthread_cond_signal(&proc->cond_prach); - pthread_mutex_lock(&proc->mutex_synch); - proc->instance_cnt_synch = 0; - pthread_mutex_unlock(&proc->mutex_synch); - pthread_cond_signal(&proc->cond_synch); - pthread_mutex_lock(&proc->mutex_gNBs); - proc->instance_cnt_gNBs = 0; - pthread_mutex_unlock(&proc->mutex_gNBs); - pthread_cond_signal(&proc->cond_gNBs); - pthread_mutex_lock(&proc->mutex_asynch_rxtx); - proc->instance_cnt_asynch_rxtx = 0; - pthread_mutex_unlock(&proc->mutex_asynch_rxtx); - pthread_cond_signal(&proc->cond_asynch_rxtx); LOG_D(PHY, "Joining pthread_FH\n"); pthread_join(proc->pthread_FH, NULL); - if (ru->function == NGFI_RRU_IF4p5) { - LOG_D(PHY, "Joining pthread_prach\n"); - pthread_join(proc->pthread_prach, NULL); - - if (ru->is_slave) { - LOG_D(PHY, "Joining pthread_\n"); - pthread_join(proc->pthread_synch, NULL); - } - - if ((ru->if_timing == synch_to_other) || - (ru->function == NGFI_RRU_IF5) || - (ru->function == NGFI_RRU_IF4p5)) { - LOG_D(PHY, "Joining pthread_asynch_rxtx\n"); - pthread_join(proc->pthread_asynch_rxtx, NULL); - } - } - if (get_nprocs() >= 2) { if (ru->feprx) { pthread_mutex_lock(&proc->mutex_fep); @@ -1958,17 +1521,6 @@ void kill_NR_RU_proc(int inst) { LOG_D(PHY, "Joining ru_stats_thread\n"); pthread_join(ru->ru_stats_thread, NULL); } - - pthread_mutex_destroy(&proc->mutex_prach); - pthread_mutex_destroy(&proc->mutex_asynch_rxtx); - pthread_mutex_destroy(&proc->mutex_synch); - pthread_mutex_destroy(&proc->mutex_FH); - pthread_mutex_destroy(&proc->mutex_gNBs); - pthread_cond_destroy(&proc->cond_prach); - pthread_cond_destroy(&proc->cond_FH); - pthread_cond_destroy(&proc->cond_asynch_rxtx); - pthread_cond_destroy(&proc->cond_synch); - pthread_cond_destroy(&proc->cond_gNBs); } int check_capabilities(RU_t *ru,RRU_capabilities_t *cap) diff --git a/executables/nr-softmodem.c b/executables/nr-softmodem.c index 924c32b8a7..69fc3c554d 100644 --- a/executables/nr-softmodem.c +++ b/executables/nr-softmodem.c @@ -136,9 +136,6 @@ double rx_gain[MAX_NUM_CCs][4] = {{110,0,0,0},{20,0,0,0}}; double rx_gain_off = 0.0; -double sample_rate=30.72e6; -double bw = 10.0e6; - static int tx_max_power[MAX_NUM_CCs]; /* = {0,0}*/; @@ -476,93 +473,6 @@ void set_default_frame_parms(nfapi_nr_config_request_scf_t *config[MAX_NUM_CCs], } } -/* -void init_openair0(void) { - - int card; - int i; - - for (card=0; cardrf_config.dl_carrier_bandwidth.value == 100) { - if (frame_parms[0]->threequarter_fs) { - openair0_cfg[card].sample_rate=23.04e6; - openair0_cfg[card].samples_per_frame = 230400; - openair0_cfg[card].tx_bw = 10e6; - openair0_cfg[card].rx_bw = 10e6; - } else { - openair0_cfg[card].sample_rate=30.72e6; - openair0_cfg[card].samples_per_frame = 307200; - openair0_cfg[card].tx_bw = 10e6; - openair0_cfg[card].rx_bw = 10e6; - } - } else if(config[0]->rf_config.dl_carrier_bandwidth.value == 50) { - openair0_cfg[card].sample_rate=15.36e6; - openair0_cfg[card].samples_per_frame = 153600; - openair0_cfg[card].tx_bw = 5e6; - openair0_cfg[card].rx_bw = 5e6; - } else if (config[0]->rf_config.dl_carrier_bandwidth.value == 25) { - openair0_cfg[card].sample_rate=7.68e6; - openair0_cfg[card].samples_per_frame = 76800; - openair0_cfg[card].tx_bw = 2.5e6; - openair0_cfg[card].rx_bw = 2.5e6; - } else if (config[0]->rf_config.dl_carrier_bandwidth.value == 6) { - openair0_cfg[card].sample_rate=1.92e6; - openair0_cfg[card].samples_per_frame = 19200; - openair0_cfg[card].tx_bw = 1.5e6; - openair0_cfg[card].rx_bw = 1.5e6; - } - - - if (config[0]->subframe_config.duplex_mode.value==TDD) - openair0_cfg[card].duplex_mode = duplex_mode_TDD; - else //FDD - openair0_cfg[card].duplex_mode = duplex_mode_FDD; - - printf("HW: Configuring card %d, nb_antennas_tx/rx %d/%d\n",card, - RC.gNB[0]->gNB_config.rf_config.tx_antenna_ports.value, - RC.gNB[0]->gNB_config.rf_config.tx_antenna_ports.value ); - openair0_cfg[card].Mod_id = 0; - - openair0_cfg[card].num_rb_dl=config[0]->rf_config.dl_carrier_bandwidth.value; - - openair0_cfg[card].clock_source = clock_source; - - - openair0_cfg[card].tx_num_channels=min(2,RC.gNB[0]->gNB_config.rf_config.tx_antenna_ports.value ); - openair0_cfg[card].rx_num_channels=min(2,RC.gNB[0]->gNB_config.rf_config.tx_antenna_ports.value ); - - for (i=0; i<4; i++) { - - if (irx_total_gain_dB; - - - openair0_cfg[card].configFilename = get_softmodem_params()->rf_config_file; - printf("Card %d, channel %d, Setting tx_gain %f, rx_gain %f, tx_freq %f, rx_freq %f\n", - card,i, openair0_cfg[card].tx_gain[i], - openair0_cfg[card].rx_gain[i], - openair0_cfg[card].tx_freq[i], - openair0_cfg[card].rx_freq[i]); - } - } // for loop on cards -} -*/ - void wait_RUs(void) { LOG_I(PHY,"Waiting for RUs to be configured ... RC.ru_mask:%02lx\n", RC.ru_mask); // wait for all RUs to be configured over fronthaul diff --git a/executables/nr-ue.c b/executables/nr-ue.c index 6be23582b1..f175ab4980 100644 --- a/executables/nr-ue.c +++ b/executables/nr-ue.c @@ -237,43 +237,6 @@ static void UE_synch(void *arg) { openair0_cfg[UE->rf_map.card].rx_freq[0], openair0_cfg[UE->rf_map.card].tx_freq[0]); - // reconfigure for potentially different bandwidth - switch(UE->frame_parms.N_RB_DL) { - case 6: - openair0_cfg[UE->rf_map.card].sample_rate =1.92e6; - openair0_cfg[UE->rf_map.card].rx_bw =.96e6; - openair0_cfg[UE->rf_map.card].tx_bw =.96e6; - // openair0_cfg[0].rx_gain[0] -= 12; - break; - - case 25: - openair0_cfg[UE->rf_map.card].sample_rate =7.68e6; - openair0_cfg[UE->rf_map.card].rx_bw =2.5e6; - openair0_cfg[UE->rf_map.card].tx_bw =2.5e6; - // openair0_cfg[0].rx_gain[0] -= 6; - break; - - case 50: - openair0_cfg[UE->rf_map.card].sample_rate =15.36e6; - openair0_cfg[UE->rf_map.card].rx_bw =5.0e6; - openair0_cfg[UE->rf_map.card].tx_bw =5.0e6; - // openair0_cfg[0].rx_gain[0] -= 3; - break; - - case 100: - openair0_cfg[UE->rf_map.card].sample_rate=30.72e6; - openair0_cfg[UE->rf_map.card].rx_bw=10.0e6; - openair0_cfg[UE->rf_map.card].tx_bw=10.0e6; - // openair0_cfg[0].rx_gain[0] -= 0; - break; - - case 66: - openair0_cfg[UE->rf_map.card].sample_rate=122.88e6; - openair0_cfg[UE->rf_map.card].rx_bw=100.e6; - openair0_cfg[UE->rf_map.card].tx_bw=100.e6; - break; - } - if (UE->mode != loop_through_memory) { UE->rfdevice.trx_set_freq_func(&UE->rfdevice,&openair0_cfg[0],0); //UE->rfdevice.trx_set_gains_func(&openair0,&openair0_cfg[0]); @@ -703,16 +666,23 @@ void *UE_thread(void *arg) { int flags = 0; int slot_tx_usrp = slot_nr + DURATION_RX_TO_TX - RX_NB_TH; - uint8_t tdd_period = mac->phy_config.config_req.tdd_table.tdd_period_in_slots; - uint8_t num_UL_slots = mac->scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofUplinkSlots + - (mac->scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofUplinkSymbols!=0); - uint8_t first_tx_slot = tdd_period - num_UL_slots; - if (slot_tx_usrp%tdd_period==first_tx_slot) - flags=2; - else if (slot_tx_usrp%tdd_period==first_tx_slot+num_UL_slots-1) - flags = 3; - else if (slot_tx_usrp%tdd_period>first_tx_slot) + + if (openair0_cfg[0].duplex_mode == duplex_mode_TDD) { + + uint8_t tdd_period = mac->phy_config.config_req.tdd_table.tdd_period_in_slots; + int nrofUplinkSlots = mac->scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofUplinkSlots; + uint8_t num_UL_slots = nrofUplinkSlots + (nrofUplinkSlots != 0); + uint8_t first_tx_slot = tdd_period - num_UL_slots; + + if (slot_tx_usrp % tdd_period == first_tx_slot) + flags = 2; + else if (slot_tx_usrp % tdd_period == first_tx_slot + num_UL_slots - 1) + flags = 3; + else if (slot_tx_usrp % tdd_period > first_tx_slot) + flags = 1; + } else { flags = 1; + } if (flags || IS_SOFTMODEM_RFSIM) AssertFatal( writeBlockSize == diff --git a/executables/nr-uesoftmodem.c b/executables/nr-uesoftmodem.c index 5d651344d6..2854457eee 100644 --- a/executables/nr-uesoftmodem.c +++ b/executables/nr-uesoftmodem.c @@ -145,7 +145,6 @@ int chain_offset = 0; int card_offset = 0; uint64_t num_missed_slots = 0; // counter for the number of missed slots int transmission_mode = 1; -int numerology = 0; int usrp_tx_thread = 0; int oaisim_flag = 0; int emulate_rf = 0; @@ -316,92 +315,10 @@ void init_openair0(void) { for (card=0; cardthreequarter_fs; - numerology = frame_parms->numerology_index; - - if(frame_parms->N_RB_DL == 66) { - if (numerology==3) { - openair0_cfg[card].sample_rate=122.88e6; - openair0_cfg[card].samples_per_frame = 1228800; - } else { - LOG_E(PHY,"Unsupported numerology! FR2 supports only 120KHz SCS for now.\n"); - exit(-1); - } - }else if(frame_parms->N_RB_DL == 32) { - if (numerology==3) { - openair0_cfg[card].sample_rate=61.44e6; - openair0_cfg[card].samples_per_frame = 614400; - } else { - LOG_E(PHY,"Unsupported numerology! FR2 supports only 120KHz SCS for now.\n"); - exit(-1); - } - }else if(frame_parms->N_RB_DL == 217) { - if (numerology==1) { - if (frame_parms->threequarter_fs) { - openair0_cfg[card].sample_rate=92.16e6; - openair0_cfg[card].samples_per_frame = 921600; - } - else { - openair0_cfg[card].sample_rate=122.88e6; - openair0_cfg[card].samples_per_frame = 1228800; - } - } else { - LOG_E(PHY,"Unsupported numerology!\n"); - exit(-1); - } - } else if(frame_parms->N_RB_DL == 273) { - if (numerology==1) { - if (frame_parms->threequarter_fs) { - AssertFatal(0 == 1,"three quarter sampling not supported for N_RB 273\n"); - } - else { - openair0_cfg[card].sample_rate=122.88e6; - openair0_cfg[card].samples_per_frame = 1228800; - } - } else { - LOG_E(PHY,"Unsupported numerology!\n"); - exit(-1); - } - } else if(frame_parms->N_RB_DL == 106) { - if (numerology==0) { - if (frame_parms->threequarter_fs) { - openair0_cfg[card].sample_rate=23.04e6; - openair0_cfg[card].samples_per_frame = 230400; - } else { - openair0_cfg[card].sample_rate=30.72e6; - openair0_cfg[card].samples_per_frame = 307200; - } - } else if (numerology==1) { - if (frame_parms->threequarter_fs) { - openair0_cfg[card].sample_rate=46.08e6; - openair0_cfg[card].samples_per_frame = 460800; - } - else { - openair0_cfg[card].sample_rate=61.44e6; - openair0_cfg[card].samples_per_frame = 614400; - } - } else if (numerology==2) { - openair0_cfg[card].sample_rate=122.88e6; - openair0_cfg[card].samples_per_frame = 1228800; - } else { - LOG_E(PHY,"Unsupported numerology!\n"); - exit(-1); - } - } else if(frame_parms->N_RB_DL == 50) { - openair0_cfg[card].sample_rate=15.36e6; - openair0_cfg[card].samples_per_frame = 153600; - } else if (frame_parms->N_RB_DL == 25) { - openair0_cfg[card].sample_rate=7.68e6; - openair0_cfg[card].samples_per_frame = 76800; - } else if (frame_parms->N_RB_DL == 6) { - openair0_cfg[card].sample_rate=1.92e6; - openair0_cfg[card].samples_per_frame = 19200; - } - else { - LOG_E(PHY,"Unknown NB_RB %d!\n",frame_parms->N_RB_DL); - exit(-1); - } + openair0_cfg[card].configFilename = NULL; + openair0_cfg[card].threequarter_fs = frame_parms->threequarter_fs; + openair0_cfg[card].sample_rate = frame_parms->samples_per_subframe * 1e3; + openair0_cfg[card].samples_per_frame = frame_parms->samples_per_frame; if (frame_parms->frame_type==TDD) openair0_cfg[card].duplex_mode = duplex_mode_TDD; @@ -415,8 +332,9 @@ void init_openair0(void) { openair0_cfg[card].tx_num_channels = min(2, frame_parms->nb_antennas_tx); openair0_cfg[card].rx_num_channels = min(2, frame_parms->nb_antennas_rx); - LOG_I(PHY, "HW: Configuring card %d, tx/rx num_channels %d/%d, duplex_mode %s\n", + 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[openair0_cfg[card].duplex_mode]); @@ -531,7 +449,8 @@ int main( int argc, char **argv ) { 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->scc->downlinkConfigCommon->frequencyInfoDL->frequencyBandList.list.array[0]); - init_symbol_rotation(&UE[CC_id]->frame_parms, UE[CC_id]->frame_parms.dl_CarrierFreq); + + init_symbol_rotation(&UE[CC_id]->frame_parms); init_nr_ue_vars(UE[CC_id], 0, abstraction_flag); #ifdef FR2_TEST diff --git a/executables/softmodem-common.h b/executables/softmodem-common.h index 60a761c732..7a7be1de96 100644 --- a/executables/softmodem-common.h +++ b/executables/softmodem-common.h @@ -244,6 +244,13 @@ extern char *get_softmodem_function(uint64_t *sofmodemfunc_mask_ptr); extern void set_softmodem_sighandler(void); extern uint64_t downlink_frequency[MAX_NUM_CCs][4]; extern int32_t uplink_frequency_offset[MAX_NUM_CCs][4]; +extern uint16_t sl_ahead; +extern uint16_t sf_ahead; +extern volatile int oai_exit; + +void tx_func(void *param); +void rx_func(void *param); +void ru_tx_func(void *param); extern uint8_t nfapi_mode; #ifdef __cplusplus } diff --git a/nfapi/oai_integration/nfapi_pnf.c b/nfapi/oai_integration/nfapi_pnf.c index 92057186e2..e744fcbb24 100644 --- a/nfapi/oai_integration/nfapi_pnf.c +++ b/nfapi/oai_integration/nfapi_pnf.c @@ -2406,36 +2406,3 @@ int oai_nfapi_sr_indication(nfapi_sr_indication_t *ind) { //free(ind.rx_indication_body.rx_pdu_list); return retval; } - -//NR UPLINK INDICATION - -int oai_nfapi_nr_rx_data_indication(nfapi_nr_rx_data_indication_t *ind) { - ind->header.phy_id = 1; // DJP HACK TODO FIXME - need to pass this around!!!! - ind->header.message_id = NFAPI_NR_PHY_MSG_TYPE_RX_DATA_INDICATION; - return nfapi_pnf_p7_nr_rx_data_ind(p7_config_g, ind); -} - -int oai_nfapi_nr_crc_indication(nfapi_nr_crc_indication_t *ind) { - ind->header.phy_id = 1; // DJP HACK TODO FIXME - need to pass this around!!!! - ind->header.message_id = NFAPI_NR_PHY_MSG_TYPE_CRC_INDICATION; - return nfapi_pnf_p7_nr_crc_ind(p7_config_g, ind); -} - -int oai_nfapi_nr_srs_indication(nfapi_nr_srs_indication_t *ind) { - ind->header.phy_id = 1; // DJP HACK TODO FIXME - need to pass this around!!!! - ind->header.message_id = NFAPI_NR_PHY_MSG_TYPE_SRS_INDICATION; - return nfapi_pnf_p7_nr_srs_ind(p7_config_g, ind); -} - -int oai_nfapi_nr_uci_indication(nfapi_nr_uci_indication_t *ind) { - ind->header.phy_id = 1; // DJP HACK TODO FIXME - need to pass this around!!!! - ind->header.message_id = NFAPI_NR_PHY_MSG_TYPE_UCI_INDICATION; - return nfapi_pnf_p7_nr_uci_ind(p7_config_g, ind); -} - -int oai_nfapi_nr_rach_indication(nfapi_nr_rach_indication_t *ind) { - ind->header.phy_id = 1; // DJP 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); -} - 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 85f1efa3f4..bc5e7af45f 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 @@ -1516,11 +1516,10 @@ typedef struct typedef struct { - nfapi_p7_message_header_t header; uint16_t sfn; uint16_t slot; uint16_t number_of_pdus; - nfapi_nr_rx_data_pdu_t *pdu_list; //changed from pointer to struct - gokul + nfapi_nr_rx_data_pdu_t* pdu_list; } nfapi_nr_rx_data_indication_t; @@ -1543,7 +1542,6 @@ typedef struct typedef struct { - nfapi_p7_message_header_t header; uint16_t sfn; uint16_t slot; uint16_t number_crcs; @@ -1681,7 +1679,6 @@ typedef struct typedef struct { - nfapi_p7_message_header_t header; uint16_t sfn; uint16_t slot; uint16_t num_ucis; @@ -1718,7 +1715,6 @@ typedef struct typedef struct { - nfapi_p7_message_header_t header; uint16_t sfn; uint16_t slot; uint8_t number_of_pdus; @@ -1751,7 +1747,6 @@ typedef struct{ typedef struct { - nfapi_p7_message_header_t header; uint16_t sfn; uint16_t slot; uint8_t number_of_pdus; diff --git a/nfapi/open-nFAPI/nfapi/src/nfapi_p7.c b/nfapi/open-nFAPI/nfapi/src/nfapi_p7.c index a97e4ccaaf..5f8e6b52b4 100755 --- a/nfapi/open-nFAPI/nfapi/src/nfapi_p7.c +++ b/nfapi/open-nFAPI/nfapi/src/nfapi_p7.c @@ -307,7 +307,6 @@ static uint8_t pack_dl_tti_pdcch_pdu_rel15_value(void* tlv, uint8_t **ppWritePac static uint8_t pack_dl_tti_pdsch_pdu_rel15_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { - printf("packing pdsch pdu. \n"); nfapi_nr_dl_tti_pdsch_pdu_rel15_t* value = (nfapi_nr_dl_tti_pdsch_pdu_rel15_t*)tlv; // TODO: resolve the packaging of array (currently sending a single element) @@ -3354,308 +3353,6 @@ static uint8_t pack_nr_timing_info(void *msg, uint8_t **ppWritePackedMsg, uint8_ } -//NR UPLINK indication function packing - -//RX DATA INDICATION - -static uint8_t pack_nr_rx_data_indication_body(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_nr_rx_data_pdu_t* value = (nfapi_nr_rx_data_pdu_t*)tlv; - - if(!(push32(value->handle, ppWritePackedMsg, end) && - push16(value->rnti, ppWritePackedMsg, end) && - push8(value->harq_id, ppWritePackedMsg, end) && - push16(value->pdu_length, ppWritePackedMsg, end) && - push8(value->ul_cqi, ppWritePackedMsg, end) && - push16(value->timing_advance, ppWritePackedMsg, end) && - push16(value->rssi, ppWritePackedMsg, end) - )) - return 0; - - return 1; -} - - -static uint8_t pack_nr_rx_data_indication(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) -{ - nfapi_nr_rx_data_indication_t *pNfapiMsg = (nfapi_nr_rx_data_indication_t*)msg; - - if (!(push16(pNfapiMsg->sfn , ppWritePackedMsg, end) && - push16(pNfapiMsg->slot , ppWritePackedMsg, end) && - push16(pNfapiMsg->number_of_pdus, ppWritePackedMsg, end) - )) - return 0; - - for(int i=0; inumber_of_pdus;i++) - { - if(!pack_nr_rx_data_indication_body(pNfapiMsg->pdu_list,ppWritePackedMsg,end)) - return 0; - } - -return 1; -} - -//NR CRC INDICATION - -static uint8_t pack_nr_crc_indication_body(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_nr_crc_t* value = (nfapi_nr_crc_t*)tlv; - - if(!(push32(value->handle, ppWritePackedMsg, end) && - push16(value->rnti, ppWritePackedMsg, end) && - push8(value->harq_id, ppWritePackedMsg, end) && - push8(value->tb_crc_status, ppWritePackedMsg, end) && - push16(value->num_cb, ppWritePackedMsg, end) && - //pusharray8(value->cb_crc_status, (int)(value->num_cb / 8) + 1, (int)(value->num_cb / 8) + 1, ppWritePackedMsg, end) && //length is ceil(NumCb/8) - push8(value->ul_cqi, ppWritePackedMsg, end) && - push16(value->timing_advance, ppWritePackedMsg, end) && - push16(value->rssi, ppWritePackedMsg, end) - )) - return 0; - - return 1; -} - -static uint8_t pack_nr_crc_indication(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) -{ - nfapi_nr_crc_indication_t *pNfapiMsg = (nfapi_nr_crc_indication_t*)msg; - - if (!(push16(pNfapiMsg->sfn , ppWritePackedMsg, end) && - push16(pNfapiMsg->slot , ppWritePackedMsg, end) && - push16(pNfapiMsg->number_crcs, ppWritePackedMsg, end) - )) - return 0; - - for(int i=0; inumber_crcs;i++) - { - if(!pack_nr_crc_indication_body(pNfapiMsg->crc_list,ppWritePackedMsg,end)) - return 0; - } - -return 1; -} - -//SRS INDICATION - -static uint8_t pack_nr_srs_indication_body(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_nr_srs_indication_pdu_t* value = (nfapi_nr_srs_indication_pdu_t*)tlv; - - if(!(push32(value->handle, ppWritePackedMsg, end) && - push16(value->rnti, ppWritePackedMsg, end) && - push16(value->timing_advance, ppWritePackedMsg, end) && - push8(value->num_symbols, ppWritePackedMsg, end) && - push8(value->wide_band_snr, ppWritePackedMsg, end) && - push8(value->num_reported_symbols, ppWritePackedMsg, end) && - push8(value->reported_symbol_list->num_rbs, ppWritePackedMsg, end) - )) - return 0; - for(int i = 0; i < value->reported_symbol_list->num_rbs; i++) - { - if(!(push8(value->reported_symbol_list->rb_list->rb_snr, ppWritePackedMsg, end) - )) - return 0; - } - return 1; -} - -static uint8_t pack_nr_srs_indication(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) -{ - nfapi_nr_srs_indication_t *pNfapiMsg = (nfapi_nr_srs_indication_t*)msg; - - if (!(push16(pNfapiMsg->sfn , ppWritePackedMsg, end) && - push16(pNfapiMsg->slot , ppWritePackedMsg, end) && - push16(pNfapiMsg->number_of_pdus, ppWritePackedMsg, end) - )) - return 0; - - for(int i=0; inumber_of_pdus;i++) - { - if(!pack_nr_srs_indication_body(&(pNfapiMsg->pdu_list[i]),ppWritePackedMsg,end)) - return 0; - } - -return 1; -} - -//RACH INDICATION - -static uint8_t pack_nr_rach_indication_body(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_nr_prach_indication_pdu_t* value = (nfapi_nr_prach_indication_pdu_t*)tlv; - - if(!(push16(value->phy_cell_id, ppWritePackedMsg, end) && - push8(value->symbol_index, ppWritePackedMsg, end) && - push8(value->slot_index, ppWritePackedMsg, end) && - push8(value->freq_index, ppWritePackedMsg, end) && - push8(value->avg_rssi, ppWritePackedMsg, end) && - push8(value->avg_snr, ppWritePackedMsg, end) && - push8(value->num_preamble, ppWritePackedMsg, end) - )) - return 0; - for(int i = 0; i < value->num_preamble; i++) - { - if(!(push8(value->preamble_list->preamble_index, ppWritePackedMsg, end) && - push16(value->preamble_list->timing_advance, ppWritePackedMsg, end) && - push32(value->preamble_list->preamble_pwr, ppWritePackedMsg, end) - )) - return 0; - } - return 1; -} - -static uint8_t pack_nr_rach_indication(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) -{ - nfapi_nr_rach_indication_t *pNfapiMsg = (nfapi_nr_rach_indication_t*)msg; - - if (!(push16(pNfapiMsg->sfn , ppWritePackedMsg, end) && - push16(pNfapiMsg->slot , ppWritePackedMsg, end) && - push16(pNfapiMsg->number_of_pdus, ppWritePackedMsg, end) - )) - return 0; - - for(int i=0; inumber_of_pdus;i++) - { - if(!pack_nr_rach_indication_body(&(pNfapiMsg->pdu_list[i]),ppWritePackedMsg,end)) - return 0; - } - -return 1; -} - - -//UCI INDICATION - -static uint8_t pack_nr_uci_pucch_0_1(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { - nfapi_nr_uci_pucch_pdu_format_0_1_t* value = (nfapi_nr_uci_pucch_pdu_format_0_1_t*)tlv; - - if(!(push8(value->pduBitmap, ppWritePackedMsg, end) && - push32(value->handle, ppWritePackedMsg, end) && - push16(value->rnti, ppWritePackedMsg, end) && - push8(value->pucch_format, ppWritePackedMsg, end) && - push8(value->ul_cqi, ppWritePackedMsg, end) && - push16(value->timing_advance, ppWritePackedMsg, end) && - push16(value->rssi, ppWritePackedMsg, end) - )) - return 0; - if (value->pduBitmap & 0x01) { //SR - if(!(push8(value->sr->sr_indication, ppWritePackedMsg, end) && - push8(value->sr->sr_confidence_level, ppWritePackedMsg, end) - )) - return 0; - } - - if (((value->pduBitmap >> 1) & 0x01)) { //HARQ - if(!(push8(value->harq->num_harq, ppWritePackedMsg, end) && - push8(value->harq->harq_confidence_level, ppWritePackedMsg, end) - )) - return 0; - - for(int i=0; iharq->num_harq;i++) - { - if(!(push8(value->harq->harq_list[i].harq_value, ppWritePackedMsg, end) - )) - return 0; - } - } - - return 1; -} - -static uint8_t pack_nr_uci_pucch_2_3_4(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { - nfapi_nr_uci_pucch_pdu_format_2_3_4_t* value = (nfapi_nr_uci_pucch_pdu_format_2_3_4_t*) tlv; - - if(!(push8(value->pduBitmap, ppWritePackedMsg, end) && - push32(value->handle, ppWritePackedMsg, end) && - push16(value->rnti, ppWritePackedMsg, end) && - push8(value->pucch_format, ppWritePackedMsg, end) && - push8(value->ul_cqi, ppWritePackedMsg, end) && - push16(value->timing_advance, ppWritePackedMsg, end) && - push16(value->rssi, ppWritePackedMsg, end) - )) - return 0; - - if (value->pduBitmap & 0x01) { //SR - if(!(push8(value->sr.sr_bit_len, ppWritePackedMsg, end) && - pusharray8(value->sr.sr_payload, (int)(value->sr.sr_bit_len / 8) + 1, (int)(value->sr.sr_bit_len / 8) + 1, ppWritePackedMsg, end) - )) - return 0; - } - - if (((value->pduBitmap >> 1) & 0x01)) { //HARQ - if(!(push8(value->harq.harq_crc, ppWritePackedMsg, end) && - push8(value->harq.harq_bit_len, ppWritePackedMsg, end) && - pusharray8(value->harq.harq_payload, (int)(value->harq.harq_bit_len / 8) + 1, (int)(value->harq.harq_bit_len / 8) + 1, ppWritePackedMsg, end) - )) - return 0; - } - - if (((value->pduBitmap >> 2) & 0x01)) { //CSI-1 - if(!(push8(value->csi_part1.csi_part1_crc, ppWritePackedMsg, end) && - push8(value->csi_part1.csi_part1_bit_len, ppWritePackedMsg, end) && - pusharray8(value->csi_part1.csi_part1_payload, (int)(value->csi_part1.csi_part1_bit_len / 8) + 1, (int)(value->csi_part1.csi_part1_bit_len / 8) + 1, ppWritePackedMsg, end) - )) - return 0; - } - - if (((value->pduBitmap >> 3) & 0x01)) { //CSI-2 - if(!(push8(value->csi_part2.csi_part2_crc, ppWritePackedMsg, end) && - push8(value->csi_part2.csi_part2_bit_len, ppWritePackedMsg, end) && - pusharray8(value->csi_part2.csi_part2_payload, (int)(value->csi_part2.csi_part2_bit_len / 8) + 1, (int)(value->csi_part2.csi_part2_bit_len / 8) + 1, ppWritePackedMsg, end) - )) - return 0; - } - - return 1; -} - -static uint8_t pack_nr_uci_indication_body(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_nr_uci_t* value = (nfapi_nr_uci_t*)tlv; - - if(!(push16(value->pdu_type, ppWritePackedMsg, end) && - push16(value->pdu_size, ppWritePackedMsg, end) - )) - return 0; - - switch (value->pdu_type) { - case NFAPI_NR_UCI_PUSCH_PDU_TYPE: - printf("Unhandled NFAPI_NR_UCI_PUSCH_PDU_TYPE \n"); - break; - - case NFAPI_NR_UCI_FORMAT_0_1_PDU_TYPE: { - nfapi_nr_uci_pucch_pdu_format_0_1_t *uci_pdu = &value->pucch_pdu_format_0_1; - pack_nr_uci_pucch_0_1(uci_pdu, ppWritePackedMsg, end); - break; - } - case NFAPI_NR_UCI_FORMAT_2_3_4_PDU_TYPE: { - nfapi_nr_uci_pucch_pdu_format_2_3_4_t *uci_pdu = &value->pucch_pdu_format_2_3_4; - pack_nr_uci_pucch_2_3_4(uci_pdu, ppWritePackedMsg, end); - break; - } - } - - return 1; -} - -static uint8_t pack_nr_uci_indication(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) -{ - nfapi_nr_uci_indication_t *pNfapiMsg = (nfapi_nr_uci_indication_t*)msg; - - if (!(push16(pNfapiMsg->sfn , ppWritePackedMsg, end) && - push16(pNfapiMsg->slot , ppWritePackedMsg, end) && - push16(pNfapiMsg->num_ucis, ppWritePackedMsg, end) - )) - return 0; - - for(int i=0; inum_ucis;i++) - { - if(!pack_nr_uci_indication_body(&(pNfapiMsg->uci_list[i]),ppWritePackedMsg,end)) - return 0; - } - -return 1; -} // Main pack function - public @@ -3700,7 +3397,6 @@ int nfapi_nr_p7_message_pack(void *pMessageBuf, void *pPackedBuf, uint32_t packe { case NFAPI_NR_PHY_MSG_TYPE_DL_TTI_REQUEST: result = pack_dl_tti_request(pMessageHeader, &pWritePackedMessage, end, config); - printf("result of pack dl_tti_req is %d. \n",result); break; case NFAPI_NR_PHY_MSG_TYPE_UL_TTI_REQUEST: @@ -3721,24 +3417,49 @@ int nfapi_nr_p7_message_pack(void *pMessageBuf, void *pPackedBuf, uint32_t packe result =pack_ue_release_response(pMessageHeader, &pWritePackedMessage, end, config); break; - case NFAPI_NR_PHY_MSG_TYPE_RX_DATA_INDICATION: - result = pack_nr_rx_data_indication(pMessageHeader, &pWritePackedMessage, end, config); + case NFAPI_HARQ_INDICATION: + result = pack_harq_indication(pMessageHeader, &pWritePackedMessage, end, config); break; - case NFAPI_NR_PHY_MSG_TYPE_CRC_INDICATION: - result = pack_nr_crc_indication(pMessageHeader, &pWritePackedMessage, end, config); + case NFAPI_CRC_INDICATION: + result = pack_crc_indication(pMessageHeader, &pWritePackedMessage, end, config); break; - case NFAPI_NR_PHY_MSG_TYPE_UCI_INDICATION: - result = pack_nr_uci_indication(pMessageHeader, &pWritePackedMessage, end, config); + case NFAPI_RX_ULSCH_INDICATION: + //printf("RX ULSCH\n"); + result = pack_rx_ulsch_indication(pMessageHeader, &pWritePackedMessage, end, config); break; - case NFAPI_NR_PHY_MSG_TYPE_SRS_INDICATION: - result = pack_nr_rach_indication(pMessageHeader, &pWritePackedMessage, end, config); + case NFAPI_RACH_INDICATION: + result = pack_rach_indication(pMessageHeader, &pWritePackedMessage, end, config); break; - case NFAPI_NR_PHY_MSG_TYPE_RACH_INDICATION: - result = pack_nr_srs_indication(pMessageHeader, &pWritePackedMessage, end, config); + case NFAPI_SRS_INDICATION: + result = pack_srs_indication(pMessageHeader, &pWritePackedMessage, end, config); + break; + + case NFAPI_RX_SR_INDICATION: + result = pack_sr_indication(pMessageHeader, &pWritePackedMessage, end, config); + break; + + case NFAPI_RX_CQI_INDICATION: + result = pack_cqi_indication(pMessageHeader, &pWritePackedMessage, end, config); + break; + + case NFAPI_LBT_DL_CONFIG_REQUEST: + result = pack_lbt_dl_config_request(pMessageHeader, &pWritePackedMessage, end, config); + break; + + case NFAPI_LBT_DL_INDICATION: + result = pack_lbt_dl_indication(pMessageHeader, &pWritePackedMessage, end, config); + break; + + case NFAPI_NB_HARQ_INDICATION: + result = pack_nb_harq_indication(pMessageHeader, &pWritePackedMessage, end, config); + break; + + case NFAPI_NRACH_INDICATION: + result = pack_nrach_indication(pMessageHeader, &pWritePackedMessage, end, config); break; case NFAPI_NR_PHY_MSG_TYPE_DL_NODE_SYNC: @@ -3854,6 +3575,7 @@ int nfapi_p7_message_pack(void *pMessageBuf, void *pPackedBuf, uint32_t packedBu switch (pMessageHeader->message_id) { case NFAPI_DL_CONFIG_REQUEST: + //NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() NFAPI_DL_CONFIG_REQUEST\n", __FUNCTION__); result = pack_dl_config_request(pMessageHeader, &pWritePackedMessage, end, config); break; @@ -3861,6 +3583,7 @@ int nfapi_p7_message_pack(void *pMessageBuf, void *pPackedBuf, uint32_t packedBu result = pack_ul_config_request(pMessageHeader, &pWritePackedMessage, end, config); break; case NFAPI_TX_REQUEST: + //NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() NFAPI_TX_REQUEST\n", __FUNCTION__); result = pack_tx_request(pMessageHeader, &pWritePackedMessage, end, config); break; case NFAPI_HI_DCI0_REQUEST: @@ -3884,6 +3607,7 @@ int nfapi_p7_message_pack(void *pMessageBuf, void *pPackedBuf, uint32_t packedBu break; case NFAPI_RX_ULSCH_INDICATION: + //printf("RX ULSCH\n"); result = pack_rx_ulsch_indication(pMessageHeader, &pWritePackedMessage, end, config); break; @@ -6348,334 +6072,6 @@ static uint8_t unpack_tx_request(uint8_t **ppReadPackedMsg, uint8_t *end, void * return 1; } - -//UNPACK NR UPLINK INDICATION FUNCTIONS - -//RX DATA INDICATION - -static uint8_t unpack_nr_rx_data_indication_body(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_nr_rx_data_pdu_t* value = (nfapi_nr_rx_data_pdu_t*)tlv; - - if(!(pull32(ppReadPackedMsg, &value->handle, end) && - pull16(ppReadPackedMsg, &value->rnti, end) && - pull8(ppReadPackedMsg, &value->harq_id, end) && - pull16(ppReadPackedMsg, &value->pdu_length, end) && - pull8(ppReadPackedMsg, &value->ul_cqi, end) && - pull16(ppReadPackedMsg, &value->timing_advance, end) && - pull16(ppReadPackedMsg, &value->rssi, end) - )) - return 0; - return 1; -} - - -static uint8_t unpack_nr_rx_data_indication(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config) -{ - // uint8_t *ptr = *ppReadPackedMsg; - // printf("\n Read P7 message rx data indication unpack: "); - // while(ptr < end){ - // printf(" %d ", *ptr); - // ptr++; - // } - // printf("\n"); - nfapi_nr_rx_data_indication_t *pNfapiMsg = (nfapi_nr_rx_data_indication_t*)msg; - - printf("\n"); - if (!(pull16(ppReadPackedMsg, &pNfapiMsg->sfn , end) && - pull16(ppReadPackedMsg, &pNfapiMsg->slot , end) && - pull16(ppReadPackedMsg, &pNfapiMsg->number_of_pdus, end) - )) - return 0; - - for(int i=0; inumber_of_pdus;i++) - { - if(!unpack_nr_rx_data_indication_body(&pNfapiMsg->pdu_list, ppReadPackedMsg, end)) - return 0; - } - -return 1; -} - -//NR CRC INDICATION - -static uint8_t unpack_nr_crc_indication_body(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_nr_crc_t* value = (nfapi_nr_crc_t*)tlv; - - if(!(pull32(ppReadPackedMsg, &value->handle, end) && - pull16(ppReadPackedMsg, &value->rnti, end) && - pull8(ppReadPackedMsg, &value->harq_id, end) && - pull8(ppReadPackedMsg, &value->tb_crc_status, end) && - pull16(ppReadPackedMsg, &value->num_cb, end) && - //pullarray8(ppReadPackedMsg, value->cb_crc_status, (int)(value->num_cb / 8) + 1, (int)(value->num_cb / 8) + 1, end) && //length is ceil(NumCb/8) - pull8(ppReadPackedMsg, &value->ul_cqi, end) && - pull16(ppReadPackedMsg, &value->timing_advance, end) && - pull16(ppReadPackedMsg, &value->rssi, end) - )) - return 0; - - return 1; -} - -static uint8_t unpack_nr_crc_indication(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config) -{ - uint8_t *ptr = *ppReadPackedMsg; - // printf("\n Read P7 message indication unpack: "); - // while(ptr < end){ - // printf(" %d ", *ptr); - // ptr++; - // } - // printf("\n"); - nfapi_nr_crc_indication_t *pNfapiMsg = (nfapi_nr_crc_indication_t*)msg; - - if (!(pull16(ppReadPackedMsg, &pNfapiMsg->sfn , end) && - pull16(ppReadPackedMsg, &pNfapiMsg->slot , end) && - pull16(ppReadPackedMsg, &pNfapiMsg->number_crcs, end) - )) - return 0; - - for(int i=0; inumber_crcs;i++) - { - if(!unpack_nr_crc_indication_body(&pNfapiMsg->crc_list,ppReadPackedMsg,end)) - return 0; - } - -return 1; -} - -//SRS INDICATION - -static uint8_t unpack_nr_srs_indication_body(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_nr_srs_indication_pdu_t* value = (nfapi_nr_srs_indication_pdu_t*)tlv; - - if(!(pull32(ppReadPackedMsg, &value->handle, end) && - pull16(ppReadPackedMsg, &value->rnti, end) && - pull16(ppReadPackedMsg, &value->timing_advance, end) && - pull8(ppReadPackedMsg, &value->num_symbols, end) && - pull8(ppReadPackedMsg, &value->wide_band_snr, end) && - pull8(ppReadPackedMsg, &value->num_reported_symbols, end) && - pull16(ppReadPackedMsg, &value->reported_symbol_list->num_rbs, end) - )) - return 0; - for(int i = 0; i < value->reported_symbol_list->num_rbs; i++) - { - if(!(pull8(ppReadPackedMsg, &value->reported_symbol_list->rb_list->rb_snr, end) - )) - return 0; - } - return 1; -} - -static uint8_t unpack_nr_srs_indication(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config) -{ - nfapi_nr_srs_indication_t *pNfapiMsg = (nfapi_nr_srs_indication_t*)msg; - - if (!(pull16(ppReadPackedMsg,&pNfapiMsg->sfn , end) && - pull16(ppReadPackedMsg,&pNfapiMsg->slot , end) && - pull8(ppReadPackedMsg,&pNfapiMsg->number_of_pdus, end) - )) - return 0; - - for(int i=0; inumber_of_pdus;i++) - { - if(!unpack_nr_srs_indication_body(&pNfapiMsg->pdu_list,ppReadPackedMsg,end)) - return 0; - } - -return 1; -} - -//NR RACH - -static uint8_t unpack_nr_rach_indication_body(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_nr_prach_indication_pdu_t* value = (nfapi_nr_prach_indication_pdu_t*)tlv; - - if(!(pull16(ppReadPackedMsg, &value->phy_cell_id, end) && - pull8(ppReadPackedMsg, &value->symbol_index, end) && - pull8(ppReadPackedMsg, &value->slot_index, end) && - pull8(ppReadPackedMsg, &value->freq_index, end) && - pull8(ppReadPackedMsg, &value->avg_rssi, end) && - pull8(ppReadPackedMsg, &value->avg_snr, end) && - pull8(ppReadPackedMsg, &value->num_preamble, end) - )) - return 0; - for(int i = 0; i < value->num_preamble; i++) - { - if(!(pull8(ppReadPackedMsg, &value->preamble_list->preamble_index, end) && - pull16(ppReadPackedMsg, &value->preamble_list->timing_advance, end) && - pull32(ppReadPackedMsg, &value->preamble_list->preamble_pwr, end) - )) - return 0; - } - return 1; -} - -static uint8_t unpack_nr_rach_indication(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config) { - - nfapi_nr_rach_indication_t *pNfapiMsg = (nfapi_nr_rach_indication_t*)msg; - if (!(pull16(ppReadPackedMsg, &pNfapiMsg->sfn , end) && - pull16(ppReadPackedMsg, &pNfapiMsg->slot , end) && - pull8(ppReadPackedMsg, &pNfapiMsg->number_of_pdus, end) - )) - return 0; - - for(int i=0; i< pNfapiMsg->number_of_pdus;i++) - { - if(!unpack_nr_rach_indication_body(&pNfapiMsg->pdu_list,ppReadPackedMsg,end)) - return 0; - } - -return 1; -} - -//NR UCI - -static uint8_t unpack_nr_uci_pucch_0_1(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { - nfapi_nr_uci_pucch_pdu_format_0_1_t* value = (nfapi_nr_uci_pucch_pdu_format_0_1_t*)tlv; - - uint8_t *ptr = *ppReadPackedMsg; - printf("\n Read P7 message uci_0_1 indication unpack: "); - while(ptr < end){ - printf(" %d ", *ptr); - ptr++; - } - printf("\n"); - - if(!(pull8(ppReadPackedMsg, &value->pduBitmap, end) && - pull32(ppReadPackedMsg, &value->handle, end) && - pull16(ppReadPackedMsg, &value->rnti, end) && - pull8(ppReadPackedMsg, &value->pucch_format, end) && - pull8(ppReadPackedMsg, &value->ul_cqi, end) && - pull16(ppReadPackedMsg, &value->timing_advance, end) && - pull16(ppReadPackedMsg, &value->rssi, end) - )) - return 0; - if (value->pduBitmap & 0x01) { //SR - if(!(pull8(ppReadPackedMsg, &value->sr->sr_indication, end) && - pull8(ppReadPackedMsg, &value->sr->sr_confidence_level, end) - )) - return 0; - } - - // if (((value->pduBitmap >> 1) & 0x01)) { //HARQ - // uint8_t* temp; //&value->harq->num_harq &value->harq->harq_confidence_level &value->harq->harq_list[0].harq_value - // temp = (uint8_t*) malloc(sizeof(uint8_t)); - // //printf("value->harq->num_harq = %d \n", value->harq->num_harq); - // // if(!(pull8(ppReadPackedMsg, temp, end) && - // // pull8(ppReadPackedMsg, temp, end) - // // )) - // // return 0; - - // // for(int i=0; i<1;i++) - // // { - // // if(!(pull8(ppReadPackedMsg, temp, end) //review - gokul - // // )) - // // return 0; - // // } - // } - - return 1; -} - - -static uint8_t unpack_nr_uci_pucch_2_3_4(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { - nfapi_nr_uci_pucch_pdu_format_2_3_4_t* value = (nfapi_nr_uci_pucch_pdu_format_2_3_4_t*) tlv; - - if(!(pull8(ppReadPackedMsg, &value->pduBitmap, end) && - pull32(ppReadPackedMsg, &value->handle, end) && - pull16(ppReadPackedMsg, &value->rnti, end) && - pull8(ppReadPackedMsg, &value->pucch_format, end) && - pull8(ppReadPackedMsg, &value->ul_cqi, end) && - pull16(ppReadPackedMsg, &value->timing_advance, end) && - pull16(ppReadPackedMsg, &value->rssi, end) - )) - return 0; - if (value->pduBitmap & 0x01) { //SR - if(!(pull16(ppReadPackedMsg, &value->sr.sr_bit_len, end) && - pullarray8(ppReadPackedMsg, value->sr.sr_payload, (int)(value->sr.sr_bit_len / 8) + 1, (int)(value->sr.sr_bit_len / 8) + 1, end) - )) - return 0; - } - - if (((value->pduBitmap >> 1) & 0x01)) { //HARQ - if(!(pull8(ppReadPackedMsg, &value->harq.harq_crc, end) && - pull16(ppReadPackedMsg, &value->harq.harq_bit_len, end) && - pullarray8(ppReadPackedMsg, value->harq.harq_payload, (int)(value->harq.harq_bit_len / 8) + 1, (int)(value->harq.harq_bit_len / 8) + 1, end) - )) - return 0; - } - - if (((value->pduBitmap >> 2) & 0x01)) { //CSI-1 - if(!(pull8(ppReadPackedMsg, &value->csi_part1.csi_part1_crc, end) && - pull16(ppReadPackedMsg, &value->csi_part1.csi_part1_bit_len, end) && - pullarray8(ppReadPackedMsg, value->csi_part1.csi_part1_payload, (int)(value->csi_part1.csi_part1_bit_len / 8) + 1, (int)(value->csi_part1.csi_part1_bit_len / 8) + 1, end) - )) - return 0; - } - - if (((value->pduBitmap >> 3) & 0x01)) { //CSI-2 - if(!(pull8(ppReadPackedMsg, &value->csi_part2.csi_part2_crc, end) && - pull16(ppReadPackedMsg, &value->csi_part2.csi_part2_bit_len, end) && - pullarray8(ppReadPackedMsg, value->csi_part2.csi_part2_payload, (int)(value->csi_part2.csi_part2_bit_len / 8) + 1, (int)(value->csi_part2.csi_part2_bit_len / 8) + 1, end) - )) - return 0; - } - - return 1; -} - -static uint8_t unpack_nr_uci_indication_body(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_nr_uci_t* value = (nfapi_nr_uci_t*)tlv; - - if(!(pull16(ppReadPackedMsg, &value->pdu_type, end) && - pull16(ppReadPackedMsg, &value->pdu_size, end) - )) - return 0; - - switch (value->pdu_type) { - case NFAPI_NR_UCI_PUSCH_PDU_TYPE: - printf("Unhandled NFAPI_NR_UCI_PUSCH_PDU_TYPE \n"); - break; - - case NFAPI_NR_UCI_FORMAT_0_1_PDU_TYPE: { - nfapi_nr_uci_pucch_pdu_format_0_1_t* uci_pdu = &value->pucch_pdu_format_0_1; - unpack_nr_uci_pucch_0_1(&uci_pdu, ppReadPackedMsg, end); - break; - } - case NFAPI_NR_UCI_FORMAT_2_3_4_PDU_TYPE: { - nfapi_nr_uci_pucch_pdu_format_2_3_4_t *uci_pdu = &value->pucch_pdu_format_2_3_4; - unpack_nr_uci_pucch_2_3_4(&uci_pdu, ppReadPackedMsg, end); - break; - } - } - - return 1; -} - -static uint8_t unpack_nr_uci_indication(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config) -{ - nfapi_nr_uci_indication_t *pNfapiMsg = (nfapi_nr_uci_indication_t*)msg; - - if (!(pull16(ppReadPackedMsg, &pNfapiMsg->sfn , end) && - pull16(ppReadPackedMsg, &pNfapiMsg->slot , end) && - pull16(ppReadPackedMsg, &pNfapiMsg->num_ucis, end) - )) - return 0; - - for(int i=0; inum_ucis;i++) - { - if(!unpack_nr_uci_indication_body(&pNfapiMsg->uci_list,ppReadPackedMsg,end)) - return 0; - } - -return 1; -} - - static uint8_t unpack_ue_release_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config) { uint8_t proceed = 1; @@ -8301,32 +7697,62 @@ static int check_nr_unpack_length(nfapi_message_id_e msgId, uint32_t unpackedBuf if (unpackedBufLen >= sizeof(nfapi_nr_tx_data_request_t)) retLen = sizeof(nfapi_nr_tx_data_request_t); break; - - case NFAPI_NR_PHY_MSG_TYPE_RX_DATA_INDICATION: - if (unpackedBufLen >= sizeof(nfapi_nr_rx_data_indication_t)) - retLen = sizeof(nfapi_nr_rx_data_indication_t); - break; - - case NFAPI_NR_PHY_MSG_TYPE_CRC_INDICATION: - if (unpackedBufLen >= sizeof(nfapi_nr_crc_indication_t)) - retLen = sizeof(nfapi_nr_crc_indication_t); + + case NFAPI_HARQ_INDICATION: + if (unpackedBufLen >= sizeof(nfapi_harq_indication_t)) + retLen = sizeof(nfapi_harq_indication_t); break; - case NFAPI_NR_PHY_MSG_TYPE_RACH_INDICATION: - if (unpackedBufLen >= sizeof(nfapi_nr_rach_indication_t)) - retLen = sizeof(nfapi_nr_rach_indication_t); + case NFAPI_CRC_INDICATION: + if (unpackedBufLen >= sizeof(nfapi_crc_indication_t)) + retLen = sizeof(nfapi_crc_indication_t); break; - - case NFAPI_NR_PHY_MSG_TYPE_UCI_INDICATION: - if (unpackedBufLen >= sizeof(nfapi_nr_uci_indication_t)) - retLen = sizeof(nfapi_nr_uci_indication_t); + + case NFAPI_RX_ULSCH_INDICATION: + if (unpackedBufLen >= sizeof(nfapi_rx_indication_t)) + retLen = sizeof(nfapi_rx_indication_t); break; - - case NFAPI_NR_PHY_MSG_TYPE_SRS_INDICATION: - if (unpackedBufLen >= sizeof(nfapi_nr_srs_indication_t)) - retLen = sizeof(nfapi_nr_srs_indication_t); + + case NFAPI_RACH_INDICATION: + if (unpackedBufLen >= sizeof(nfapi_rach_indication_t)) + retLen = sizeof(nfapi_rach_indication_t); break; - + + case NFAPI_SRS_INDICATION: + if (unpackedBufLen >= sizeof(nfapi_srs_indication_t)) + retLen = sizeof(nfapi_srs_indication_t); + break; + + case NFAPI_RX_SR_INDICATION: + if (unpackedBufLen >= sizeof(nfapi_sr_indication_t)) + retLen = sizeof(nfapi_sr_indication_t); + break; + + case NFAPI_RX_CQI_INDICATION: + if (unpackedBufLen >= sizeof(nfapi_cqi_indication_t)) + retLen = sizeof(nfapi_cqi_indication_t); + break; + + case NFAPI_LBT_DL_CONFIG_REQUEST: + if (unpackedBufLen >= sizeof(nfapi_lbt_dl_config_request_t)) + retLen = sizeof(nfapi_lbt_dl_config_request_t); + break; + + case NFAPI_LBT_DL_INDICATION: + if (unpackedBufLen >= sizeof(nfapi_lbt_dl_indication_t)) + retLen = sizeof(nfapi_lbt_dl_indication_t); + break; + + case NFAPI_NB_HARQ_INDICATION: + if (unpackedBufLen >= sizeof(nfapi_nb_harq_indication_t)) + retLen = sizeof(nfapi_nb_harq_indication_t); + break; + + case NFAPI_NRACH_INDICATION: + if (unpackedBufLen >= sizeof(nfapi_nrach_indication_t)) + retLen = sizeof(nfapi_nrach_indication_t); + break; + case NFAPI_NR_PHY_MSG_TYPE_DL_NODE_SYNC: if (unpackedBufLen >= sizeof(nfapi_nr_dl_node_sync_t)) retLen = sizeof(nfapi_nr_dl_node_sync_t); @@ -8636,15 +8062,15 @@ int nfapi_nr_p7_message_unpack(void *pMessageBuf, uint32_t messageBufLen, void * NFAPI_TRACE(NFAPI_TRACE_ERROR, "P7 unpack supplied message buffer is too small %d, %d\n", messageBufLen, unpackedBufLen); return -1; } - - // uint8_t *ptr = pMessageBuf; - // printf("\n Read P7 message unpack: "); - // while(ptr < end){ - // printf(" %d ", *ptr); - // ptr++; - // } - // printf("\n"); - + /* + uint8_t *ptr = pMessageBuf; + printf("\n Read P7 message unpack: "); + while(ptr < end){ + printf(" %d ", *ptr); + ptr++; + } + printf("\n"); +*/ // clean the supplied buffer for - tag value blanking (void)memset(pUnpackedBuf, 0, unpackedBufLen); @@ -8710,41 +8136,83 @@ int nfapi_nr_p7_message_unpack(void *pMessageBuf, uint32_t messageBufLen, void * return -1; break; - case NFAPI_NR_PHY_MSG_TYPE_RX_DATA_INDICATION: - if (check_nr_unpack_length(NFAPI_NR_PHY_MSG_TYPE_RX_DATA_INDICATION, unpackedBufLen)) - result = unpack_nr_rx_data_indication(&pReadPackedMessage, end, pMessageHeader, config); + case NFAPI_HARQ_INDICATION: + if (check_nr_unpack_length(NFAPI_HARQ_INDICATION, unpackedBufLen)) + result = unpack_harq_indication(&pReadPackedMessage, end, pMessageHeader, config); else return -1; break; - case NFAPI_NR_PHY_MSG_TYPE_CRC_INDICATION: - if (check_nr_unpack_length(NFAPI_NR_PHY_MSG_TYPE_CRC_INDICATION, unpackedBufLen)) - result = unpack_nr_crc_indication(&pReadPackedMessage,end , pMessageHeader, config); + case NFAPI_CRC_INDICATION: + if (check_nr_unpack_length(NFAPI_CRC_INDICATION, unpackedBufLen)) + result = unpack_crc_indication(&pReadPackedMessage,end , pMessageHeader, config); else return -1; break; - case NFAPI_NR_PHY_MSG_TYPE_UCI_INDICATION: - if (check_nr_unpack_length(NFAPI_NR_PHY_MSG_TYPE_UCI_INDICATION, unpackedBufLen)) - result = unpack_nr_uci_indication(&pReadPackedMessage, end, pMessageHeader, config); + case NFAPI_RX_ULSCH_INDICATION: + if (check_nr_unpack_length(NFAPI_RX_ULSCH_INDICATION, unpackedBufLen)) + result = unpack_rx_indication(&pReadPackedMessage, end, pMessageHeader, config); else return -1; break; - case NFAPI_NR_PHY_MSG_TYPE_SRS_INDICATION: - if (check_nr_unpack_length(NFAPI_NR_PHY_MSG_TYPE_SRS_INDICATION, unpackedBufLen)) - result = unpack_nr_srs_indication(&pReadPackedMessage, end, pMessageHeader, config); + case NFAPI_RACH_INDICATION: + if (check_nr_unpack_length(NFAPI_RACH_INDICATION, unpackedBufLen)) + result = unpack_rach_indication(&pReadPackedMessage, end, pMessageHeader, config); else return -1; break; - case NFAPI_NR_PHY_MSG_TYPE_RACH_INDICATION: - if (check_nr_unpack_length(NFAPI_NR_PHY_MSG_TYPE_RACH_INDICATION, unpackedBufLen)) - result = unpack_nr_rach_indication(&pReadPackedMessage, end, pMessageHeader, config); + case NFAPI_SRS_INDICATION: + if (check_nr_unpack_length(NFAPI_SRS_INDICATION, unpackedBufLen)) + result = unpack_srs_indication(&pReadPackedMessage, end, pMessageHeader, config); else return -1; break; + case NFAPI_RX_SR_INDICATION: + if (check_nr_unpack_length(NFAPI_RX_SR_INDICATION, unpackedBufLen)) + result = unpack_sr_indication(&pReadPackedMessage, end, pMessageHeader, config); + else + return -1; + break; + + case NFAPI_RX_CQI_INDICATION: + if (check_nr_unpack_length(NFAPI_RX_CQI_INDICATION, unpackedBufLen)) + result = unpack_cqi_indication(&pReadPackedMessage, end, pMessageHeader, config); + else + return -1; + break; + + case NFAPI_LBT_DL_CONFIG_REQUEST: + if (check_nr_unpack_length(NFAPI_LBT_DL_CONFIG_REQUEST, unpackedBufLen)) + result = unpack_lbt_dl_config_request(&pReadPackedMessage, end, pMessageHeader, config); + else + return -1; + break; + + case NFAPI_LBT_DL_INDICATION: + if (check_nr_unpack_length(NFAPI_LBT_DL_INDICATION, unpackedBufLen)) + result = unpack_lbt_dl_indication(&pReadPackedMessage, end, pMessageHeader, config); + else + return -1; + break; + + case NFAPI_NB_HARQ_INDICATION: + if (check_nr_unpack_length(NFAPI_NB_HARQ_INDICATION, unpackedBufLen)) + result = unpack_nb_harq_indication(&pReadPackedMessage, end, pMessageHeader, config); + else + return -1; + break; + + case NFAPI_NRACH_INDICATION: + if (check_nr_unpack_length(NFAPI_NRACH_INDICATION, unpackedBufLen)) + result = unpack_nrach_indication(&pReadPackedMessage, end, pMessageHeader, config); + else + return -1; + break; + case NFAPI_NR_PHY_MSG_TYPE_DL_NODE_SYNC: if (check_nr_unpack_length(NFAPI_NR_PHY_MSG_TYPE_DL_NODE_SYNC, unpackedBufLen)) result = unpack_nr_dl_node_sync(&pReadPackedMessage, end, pMessageHeader, config); diff --git a/nfapi/open-nFAPI/pnf/src/pnf_p7.c b/nfapi/open-nFAPI/pnf/src/pnf_p7.c index 14b4846846..3511ed2fb9 100644 --- a/nfapi/open-nFAPI/pnf/src/pnf_p7.c +++ b/nfapi/open-nFAPI/pnf/src/pnf_p7.c @@ -1572,7 +1572,7 @@ uint8_t is_nr_p7_request_in_window(uint16_t sfn,uint16_t slot, const char* name, { NFAPI_TRACE(NFAPI_TRACE_NOTE, "[%d] %s is out of window %d (delta:%d) [max:%d]\n", current_sfn_slot_dec, name, recv_sfn_slot_dec, (current_sfn_slot_dec - recv_sfn_slot_dec), timing_window); - + //NFAPI_TRACE(NFAPI_TRACE_NOTE, "[%d] %s is out of window [max:%d]\n", current_sfn_slot_dec, name, recv_sfn_slot_dec, (current_sfn_slot_dec - recv_sfn_slot_dec), timing_window); }//Need to add more cases diff --git a/nfapi/open-nFAPI/pnf/src/pnf_p7_interface.c b/nfapi/open-nFAPI/pnf/src/pnf_p7_interface.c index 88aa1391cb..efcb60ce96 100644 --- a/nfapi/open-nFAPI/pnf/src/pnf_p7_interface.c +++ b/nfapi/open-nFAPI/pnf/src/pnf_p7_interface.c @@ -175,7 +175,17 @@ int nfapi_pnf_p7_rach_ind(nfapi_pnf_p7_config_t* config, nfapi_rach_indication_t pnf_p7_t* _this = (pnf_p7_t*)(config); return pnf_p7_pack_and_send_p7_message(_this, (nfapi_p7_message_header_t*)ind, sizeof(nfapi_rach_indication_t)); } +int nfapi_pnf_p7_srs_ind(nfapi_pnf_p7_config_t* config, nfapi_srs_indication_t* ind) +{ + 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); + return pnf_p7_pack_and_send_p7_message(_this, (nfapi_p7_message_header_t*)ind, sizeof(nfapi_srs_indication_t)); +} int nfapi_pnf_p7_sr_ind(nfapi_pnf_p7_config_t* config, nfapi_sr_indication_t* ind) { if(config == NULL || ind == NULL) @@ -255,65 +265,3 @@ int nfapi_pnf_ue_release_resp(nfapi_pnf_p7_config_t* config, nfapi_ue_release_re return pnf_p7_pack_and_send_p7_message(_this, &(resp->header), sizeof(nfapi_ue_release_response_t)); } - -//NR UPLINK INDICATION - -int nfapi_pnf_p7_nr_rx_data_ind(nfapi_pnf_p7_config_t* config, nfapi_nr_rx_data_indication_t* ind) -{ - 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); - return pnf_nr_p7_pack_and_send_p7_message(_this, (nfapi_p7_message_header_t*)ind, sizeof(nfapi_nr_rx_data_indication_t)); -} - -int nfapi_pnf_p7_nr_crc_ind(nfapi_pnf_p7_config_t* config, nfapi_nr_crc_indication_t* ind) -{ - 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); - return pnf_nr_p7_pack_and_send_p7_message(_this, (nfapi_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) -{ - 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); - return pnf_nr_p7_pack_and_send_p7_message(_this, (nfapi_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) -{ - 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); - return pnf_nr_p7_pack_and_send_p7_message(_this, (nfapi_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) -{ - 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); - return pnf_nr_p7_pack_and_send_p7_message(_this, (nfapi_p7_message_header_t*)ind, sizeof(nfapi_nr_rach_indication_t)); -} diff --git a/nfapi/open-nFAPI/vnf/inc/vnf_p7.h b/nfapi/open-nFAPI/vnf/inc/vnf_p7.h index ad1c5e7944..248faf8369 100644 --- a/nfapi/open-nFAPI/vnf/inc/vnf_p7.h +++ b/nfapi/open-nFAPI/vnf/inc/vnf_p7.h @@ -24,8 +24,6 @@ #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)) - - typedef struct { uint8_t* buffer; uint16_t length; diff --git a/nfapi/open-nFAPI/vnf/src/vnf_p7.c b/nfapi/open-nFAPI/vnf/src/vnf_p7.c index 453f0f3769..39f7899d77 100644 --- a/nfapi/open-nFAPI/vnf/src/vnf_p7.c +++ b/nfapi/open-nFAPI/vnf/src/vnf_p7.c @@ -461,7 +461,6 @@ int vnf_send_p7_msg(vnf_p7_t* vnf_p7, nfapi_vnf_p7_connection_info_t* p7_info, u { NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() sendto_result %d %d\n", __FUNCTION__, sendto_result, errno); } - return 0; } @@ -677,7 +676,6 @@ int vnf_nr_build_send_dl_node_sync(vnf_p7_t* vnf_p7, nfapi_vnf_p7_connection_inf //dl_node_sync.t1 = calculate_t1(p7_info->sfn_sf, vnf_p7->sf_start_time_hr); dl_node_sync.t1 = calculate_nr_t1(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); } @@ -1453,102 +1451,8 @@ void vnf_handle_ul_node_sync(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vnf_p7) phy->previous_t1 = ind.t1; phy->previous_t2 = ind.t2; } -} -//NR HANDLES FOR UPLINK MESSAGES -void vnf_handle_nr_rx_data_indication(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vnf_p7) -{ - // ensure it's valid - if (pRecvMsg == NULL || vnf_p7 == NULL) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__); - } - 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) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: Failed to unpack message\n", __FUNCTION__); - } - - } -} - -void vnf_handle_nr_crc_indication(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vnf_p7) -{ - // ensure it's valid - if (pRecvMsg == NULL || vnf_p7 == NULL) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__); - } - else - { - nfapi_nr_crc_indication_t ind; - - if(nfapi_nr_p7_message_unpack(pRecvMsg, recvMsgLen, &ind, sizeof(ind), &vnf_p7->_public.codec_config) < 0) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: Failed to unpack message\n", __FUNCTION__); - } - - } -} - -void vnf_handle_nr_srs_indication(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vnf_p7) -{ - // ensure it's valid - if (pRecvMsg == NULL || vnf_p7 == NULL) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__); - } - else - { - nfapi_nr_srs_indication_t ind; - - if(nfapi_nr_p7_message_unpack(pRecvMsg, recvMsgLen, &ind, sizeof(ind), &vnf_p7->_public.codec_config) < 0) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: Failed to unpack message\n", __FUNCTION__); - } - - } -} - -void vnf_handle_nr_uci_indication(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vnf_p7) -{ - // ensure it's valid - if (pRecvMsg == NULL || vnf_p7 == NULL) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__); - } - else - { - nfapi_nr_uci_indication_t ind; - - if(nfapi_nr_p7_message_unpack(pRecvMsg, recvMsgLen, &ind, sizeof(ind), &vnf_p7->_public.codec_config) < 0) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: Failed to unpack message\n", __FUNCTION__); - } - } -} - -void vnf_handle_nr_rach_indication(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vnf_p7) -{ - // ensure it's valid - if (pRecvMsg == NULL || vnf_p7 == NULL) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__); - } - else - { - nfapi_nr_rach_indication_t ind; - - if(nfapi_nr_p7_message_unpack(pRecvMsg, recvMsgLen, &ind, sizeof(ind), &vnf_p7->_public.codec_config) < 0) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: Failed to unpack message\n", __FUNCTION__); - } - - } } void vnf_nr_handle_ul_node_sync(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vnf_p7) @@ -2131,26 +2035,46 @@ void vnf_nr_dispatch_p7_message(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vnf_p7 vnf_nr_handle_timing_info(pRecvMsg, recvMsgLen, vnf_p7); break; - case NFAPI_NR_PHY_MSG_TYPE_RX_DATA_INDICATION: - vnf_handle_nr_rx_data_indication(pRecvMsg, recvMsgLen, vnf_p7); + case NFAPI_HARQ_INDICATION: + vnf_handle_harq_indication(pRecvMsg, recvMsgLen, vnf_p7); break; - case NFAPI_NR_PHY_MSG_TYPE_CRC_INDICATION: - vnf_handle_nr_crc_indication(pRecvMsg, recvMsgLen, vnf_p7); + case NFAPI_CRC_INDICATION: + vnf_handle_crc_indication(pRecvMsg, recvMsgLen, vnf_p7); break; - case NFAPI_NR_PHY_MSG_TYPE_UCI_INDICATION: - vnf_handle_nr_uci_indication(pRecvMsg, recvMsgLen, vnf_p7); + case NFAPI_RX_ULSCH_INDICATION: + vnf_handle_rx_ulsch_indication(pRecvMsg, recvMsgLen, vnf_p7); break; - case NFAPI_NR_PHY_MSG_TYPE_SRS_INDICATION: - vnf_handle_nr_rach_indication(pRecvMsg, recvMsgLen, vnf_p7); + case NFAPI_RACH_INDICATION: + vnf_handle_rach_indication(pRecvMsg, recvMsgLen, vnf_p7); break; - case NFAPI_NR_PHY_MSG_TYPE_RACH_INDICATION: - vnf_handle_nr_srs_indication(pRecvMsg, recvMsgLen, vnf_p7); + case NFAPI_SRS_INDICATION: + vnf_handle_srs_indication(pRecvMsg, recvMsgLen, vnf_p7); break; + case NFAPI_RX_SR_INDICATION: + vnf_handle_rx_sr_indication(pRecvMsg, recvMsgLen, vnf_p7); + break; + + case NFAPI_RX_CQI_INDICATION: + vnf_handle_rx_cqi_indication(pRecvMsg, recvMsgLen, vnf_p7); + break; + + case NFAPI_LBT_DL_INDICATION: + vnf_handle_lbt_dl_indication(pRecvMsg, recvMsgLen, vnf_p7); + break; + + case NFAPI_NB_HARQ_INDICATION: + vnf_handle_nb_harq_indication(pRecvMsg, recvMsgLen, vnf_p7); + break; + + case NFAPI_NRACH_INDICATION: + vnf_handle_nrach_indication(pRecvMsg, recvMsgLen, vnf_p7); + break; + case NFAPI_UE_RELEASE_RESPONSE: vnf_handle_ue_release_resp(pRecvMsg, recvMsgLen, vnf_p7); break; diff --git a/nfapi/open-nFAPI/vnf/src/vnf_p7_interface.c b/nfapi/open-nFAPI/vnf/src/vnf_p7_interface.c index 3fa1f035fd..aba91d0d28 100644 --- a/nfapi/open-nFAPI/vnf/src/vnf_p7_interface.c +++ b/nfapi/open-nFAPI/vnf/src/vnf_p7_interface.c @@ -26,8 +26,12 @@ #include "vnf_p7.h" +#include "common/ran_context.h" + +#include "openair1/PHY/defs_gNB.h" #define FAPI2_IP_DSCP 0 +extern RAN_CONTEXT_t RC; nfapi_vnf_p7_config_t* nfapi_vnf_p7_config_create() { @@ -93,6 +97,7 @@ struct timespec timespec_sub(struct timespec lhs, struct timespec rhs) // send indications to mac int nfapi_nr_vnf_p7_start(nfapi_vnf_p7_config_t* config) { + uint16_t vnf_frame; uint8_t vnf_slot; if(config == 0) return -1; @@ -145,7 +150,7 @@ int nfapi_nr_vnf_p7_start(nfapi_vnf_p7_config_t* config) //struct timespec original_pselect_timeout; struct timespec pselect_timeout; - pselect_timeout.tv_sec = 0; + pselect_timeout.tv_sec = 0; pselect_timeout.tv_nsec = 500000; // ns in a 0.5 ms //pselect_timeout.tv_nsec = 500000; @@ -257,7 +262,8 @@ int nfapi_nr_vnf_p7_start(nfapi_vnf_p7_config_t* config) //long wraps = pselect_timeout.tv_nsec % 1e9; - + // pselect_timeout.tv_sec = 100; // 0 + // pselect_timeout.tv_nsec = 0;//500000; // ns in a 0.5 ms selectRetval = pselect(maxSock+1, &rfds, NULL, NULL, &pselect_timeout, NULL); // selectRetval = pselect(120, &rfds, NULL, NULL, &pselect_timeout, NULL); @@ -388,6 +394,8 @@ NFAPI_TRACE(NFAPI_TRACE_ERROR, "INVAL: pselect_timeout:%d.%ld adj[dur:%d adj:%d] selectRetval = 0; } + nfapi_vnf_p7_connection_info_t* curr = vnf_p7->p7_connections; + uint8_t ul_p7_count = 0; if(selectRetval == 0) { //vnf_p7->sf_start_time_hr = vnf_get_current_time_hr(); @@ -395,7 +403,7 @@ NFAPI_TRACE(NFAPI_TRACE_ERROR, "INVAL: pselect_timeout:%d.%ld adj[dur:%d adj:%d] struct timespec current_time; clock_gettime(CLOCK_MONOTONIC, ¤t_time); // pselect timed out - nfapi_vnf_p7_connection_info_t* curr = vnf_p7->p7_connections; + while(curr != 0) { if (curr->slot == 19) @@ -410,17 +418,49 @@ struct timespec current_time; { curr->slot++; } + //printf("Frame = %d, slot = %d in VNF main loop. n",curr->sfn,curr->slot); + vnf_frame = curr->sfn; vnf_slot = curr->slot; + + struct timespec curr_time; + clock_gettime(CLOCK_MONOTONIC, &curr_time); + //printf("SFN=%d, slot=%d, Curr_time=%d.%d \n",vnf_frame,vnf_slot,curr_time.tv_sec,curr_time.tv_nsec); + vnf_nr_sync(vnf_p7, curr); curr = curr->next; } send_mac_slot_indications(vnf_p7); + + + + // // Call the scheduler + // struct PHY_VARS_gNB_s *gNB = RC.gNB[0]; + // pthread_mutex_lock(&gNB->UL_INFO_mutex); + // gNB->UL_INFO.frame = vnf_frame; + // gNB->UL_INFO.slot = vnf_slot; + + // gNB->UL_INFO.module_id = gNB->Mod_id; + // gNB->UL_INFO.CC_id = gNB->CC_id; + // gNB->if_inst->NR_UL_indication(&gNB->UL_INFO); + // pthread_mutex_unlock(&gNB->UL_INFO_mutex); } else if(selectRetval > 0) { // have a p7 message if(FD_ISSET(vnf_p7->socket, &rfds)) - { + { + vnf_nr_p7_read_dispatch_message(vnf_p7); + + // Call the scheduler + struct PHY_VARS_gNB_s *gNB = RC.gNB[0]; + pthread_mutex_lock(&gNB->UL_INFO_mutex); + gNB->UL_INFO.frame = vnf_frame; + gNB->UL_INFO.slot = vnf_slot; + + gNB->UL_INFO.module_id = gNB->Mod_id; + gNB->UL_INFO.CC_id = gNB->CC_id; + gNB->if_inst->NR_UL_indication(&gNB->UL_INFO); + pthread_mutex_unlock(&gNB->UL_INFO_mutex); } } else diff --git a/openair1/PHY/INIT/nr_init.c b/openair1/PHY/INIT/nr_init.c index d00bc90315..0e6b253c2b 100644 --- a/openair1/PHY/INIT/nr_init.c +++ b/openair1/PHY/INIT/nr_init.c @@ -20,6 +20,7 @@ */ #include "executables/nr-softmodem-common.h" +#include "common/utils/nr/nr_common.h" #include "PHY/defs_gNB.h" #include "PHY/phy_extern.h" #include "PHY/NR_REFSIG/nr_refsig.h" @@ -45,10 +46,42 @@ #include "PHY/NR_REFSIG/ul_ref_seq_nr.h" -/* -extern uint32_t from_nrarfcn(int nr_bandP,uint32_t dl_nrarfcn); -extern openair0_config_t openair0_cfg[MAX_CARDS]; -*/ +static +uint16_t get_band(uint64_t downlink_frequency, int32_t delta_duplex) +{ + const uint64_t dl_freq_khz = downlink_frequency / 1000; + const int32_t delta_duplex_khz = delta_duplex / 1000; + + uint64_t center_freq_diff_khz = 999999999999999999; // 2^64 + uint16_t current_band = 0; + + for (int ind = 0; ind < nr_bandtable_size; ind++) { + + LOG_D(PHY, "Scanning band %d, dl_min %"PRIu64", ul_min %"PRIu64"\n", nr_bandtable[ind].band, nr_bandtable[ind].dl_min, nr_bandtable[ind].ul_min); + + if (dl_freq_khz < nr_bandtable[ind].dl_min || dl_freq_khz > nr_bandtable[ind].dl_max) + continue; + + int32_t current_offset_khz = nr_bandtable[ind].ul_min - nr_bandtable[ind].dl_min; + + if (current_offset_khz != delta_duplex_khz) + continue; + + uint64_t center_frequency_khz = (nr_bandtable[ind].dl_max + nr_bandtable[ind].dl_min) / 2; + + if (abs(dl_freq_khz - center_frequency_khz) < center_freq_diff_khz){ + current_band = nr_bandtable[ind].band; + center_freq_diff_khz = abs(dl_freq_khz - center_frequency_khz); + } + } + + LOG_I(PHY, "DL frequency %"PRIu64": band %d, UL frequency %"PRIu64"\n", + downlink_frequency, current_band, downlink_frequency+delta_duplex); + + AssertFatal(current_band != 0, "Can't find EUTRA band for frequency %"PRIu64" and duplex_spacing %u\n", downlink_frequency, delta_duplex); + + return current_band; +} int l1_north_init_gNB() { @@ -431,8 +464,8 @@ void nr_phy_config_request_sim(PHY_VARS_gNB *gNB, gNB->mac_enabled = 1; if (mu==1) { - fp->dl_CarrierFreq = 3500000000;//from_nrarfcn(gNB_config->nfapi_config.rf_bands.rf_band[0],gNB_config->nfapi_config.nrarfcn.value); - fp->ul_CarrierFreq = 3500000000;//fp->dl_CarrierFreq - (get_uldl_offset(gNB_config->nfapi_config.rf_bands.rf_band[0])*100000); + fp->dl_CarrierFreq = 3600000000;//from_nrarfcn(gNB_config->nfapi_config.rf_bands.rf_band[0],gNB_config->nfapi_config.nrarfcn.value); + fp->ul_CarrierFreq = 3600000000;//fp->dl_CarrierFreq - (get_uldl_offset(gNB_config->nfapi_config.rf_bands.rf_band[0])*100000); fp->nr_band = 78; // fp->threequarter_fs= 0; } else if (mu==3) { @@ -455,7 +488,6 @@ void nr_phy_config_request(NR_PHY_Config_t *phy_config) { uint8_t short_sequence, num_sequences, rootSequenceIndex, fd_occasion; 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; - int32_t dlul_offset = 0; memcpy((void*)gNB_config,phy_config->cfg,sizeof(*phy_config->cfg)); RC.gNB[Mod_id]->mac_enabled = 1; @@ -466,16 +498,9 @@ void nr_phy_config_request(NR_PHY_Config_t *phy_config) { uint64_t ul_bw_khz = (12*gNB_config->carrier_config.ul_grid_size[gNB_config->ssb_config.scs_common.value].value)*(15<ssb_config.scs_common.value); fp->ul_CarrierFreq = ((ul_bw_khz>>1) + gNB_config->carrier_config.uplink_frequency.value)*1000 ; - //fp->nr_band = *RC.nrmac[Mod_id]->common_channels[0].ServingCellConfigCommon->downlinkConfigCommon->frequencyInfoDL->frequencyBandList.list.array[0]; - lte_frame_type_t frame_type = 0; // FDD - - get_band(fp->dl_CarrierFreq,&fp->nr_band,&dlul_offset,&frame_type); //RC.nrmac[Mod_id] cannot be accessed in NFAPI + int32_t dlul_offset = fp->ul_CarrierFreq - fp->dl_CarrierFreq; + fp->nr_band = get_band(fp->dl_CarrierFreq, dlul_offset); - get_delta_duplex(fp->nr_band, gNB_config->ssb_config.scs_common.value, &dlul_offset); - dlul_offset *= 1000; - - AssertFatal(fp->ul_CarrierFreq == (fp->dl_CarrierFreq + dlul_offset), "Disagreement in uplink frequency for band %d: ul_CarrierFreq = %lu Hz vs expected %lu Hz\n", fp->nr_band, fp->ul_CarrierFreq, fp->dl_CarrierFreq + dlul_offset); - LOG_I(PHY, "DL frequency %lu Hz, UL frequency %lu Hz: band %d, uldl offset %d Hz\n", fp->dl_CarrierFreq, fp->ul_CarrierFreq, fp->nr_band, dlul_offset); fp->threequarter_fs = openair0_cfg[0].threequarter_fs; @@ -504,7 +529,7 @@ void nr_phy_config_request(NR_PHY_Config_t *phy_config) { // } RC.gNB[Mod_id]->configured = 1; - init_symbol_rotation(fp,fp->dl_CarrierFreq); + init_symbol_rotation(fp); LOG_I(PHY,"gNB %d configured\n",Mod_id); } diff --git a/openair1/PHY/INIT/nr_init_ue.c b/openair1/PHY/INIT/nr_init_ue.c index 8bcc58160f..3132fb9960 100644 --- a/openair1/PHY/INIT/nr_init_ue.c +++ b/openair1/PHY/INIT/nr_init_ue.c @@ -507,50 +507,36 @@ void init_N_TA_offset(PHY_VARS_NR_UE *ue){ if (fp->frame_type == FDD) { ue->N_TA_offset = 0; } else { - int N_RB = fp->N_RB_DL; int N_TA_offset = fp->ul_CarrierFreq < 6e9 ? 400 : 431; // reference samples for 25600Tc @ 30.72 Ms/s for FR1, same @ 61.44 Ms/s for FR2 - double factor = 1; + + double factor = 1.0; switch (fp->numerology_index) { case 0: //15 kHz scs AssertFatal(N_TA_offset == 400, "scs_common 15kHz only for FR1\n"); - if (N_RB <= 25) factor = .25; // 7.68 Ms/s - else if (N_RB <=50) factor = .5; // 15.36 Ms/s - else if (N_RB <=75) factor = 1.0; // 30.72 Ms/s - else if (N_RB <=100) factor = 1.0; // 30.72 Ms/s - else AssertFatal(1==0, "Too many PRBS for mu=0\n"); + factor = fp->samples_per_subframe / 30720.0; break; case 1: //30 kHz sc AssertFatal(N_TA_offset == 400, "scs_common 30kHz only for FR1\n"); - if (N_RB <= 106) factor = 2.0; // 61.44 Ms/s - else if (N_RB <= 275) factor = 4.0; // 122.88 Ms/s + factor = fp->samples_per_subframe / 30720.0; break; case 2: //60 kHz scs AssertFatal(1==0, "scs_common should not be 60 kHz\n"); break; case 3: //120 kHz scs AssertFatal(N_TA_offset == 431, "scs_common 120kHz only for FR2\n"); + factor = fp->samples_per_subframe / 61440.0; break; case 4: //240 kHz scs - AssertFatal(1==0, "scs_common should not be 60 kHz\n"); - if (N_RB <= 32) factor = 1.0; // 61.44 Ms/s - else if (N_RB <= 66) factor = 2.0; // 122.88 Ms/s - else AssertFatal(1==0, "N_RB %d is too big for curretn FR2 implementation\n", N_RB); + AssertFatal(N_TA_offset == 431, "scs_common 240kHz only for FR2\n"); + factor = fp->samples_per_subframe / 61440.0; break; - - if (N_RB == 100) - ue->N_TA_offset = 624; - else if (N_RB == 50) - ue->N_TA_offset = 624/2; - else if (N_RB == 25) - ue->N_TA_offset = 624/4; + default: + AssertFatal(1==0, "Invalid scs_common!\n"); } - if (fp->threequarter_fs == 1) - factor = factor*.75; - ue->N_TA_offset = (int)(N_TA_offset * factor); - LOG_I(PHY,"UE %d Setting N_TA_offset to %d samples (factor %f, UL Freq %lu, N_RB %d)\n", ue->Mod_id, ue->N_TA_offset, factor, fp->ul_CarrierFreq, N_RB); + LOG_I(PHY,"UE %d Setting N_TA_offset to %d samples (factor %f, UL Freq %lu, N_RB %d, mu %d)\n", ue->Mod_id, ue->N_TA_offset, factor, fp->ul_CarrierFreq, fp->N_RB_DL, fp->numerology_index); } } diff --git a/openair1/PHY/INIT/nr_parms.c b/openair1/PHY/INIT/nr_parms.c index ba4147e5cd..bacc671adc 100644 --- a/openair1/PHY/INIT/nr_parms.c +++ b/openair1/PHY/INIT/nr_parms.c @@ -75,9 +75,8 @@ int nr_get_ssb_start_symbol(NR_DL_FRAME_PARMS *fp) return symbol; } -void set_scs_parameters (NR_DL_FRAME_PARMS *fp, int mu, uint16_t bw) +void set_scs_parameters (NR_DL_FRAME_PARMS *fp, int mu, int N_RB_DL) { - switch(mu) { case NR_MU_0: //15kHz scs @@ -99,108 +98,17 @@ void set_scs_parameters (NR_DL_FRAME_PARMS *fp, int mu, uint16_t bw) else AssertFatal(1==0,"NR Operating Band n%d not available for SS block SCS with mu=%d\n", fp->nr_band, mu); } - - switch(bw){ - case 5: - case 15: - case 20: - case 25: - case 30: - case 40: //40 MHz - if (fp->threequarter_fs) { - fp->ofdm_symbol_size = 1536; - fp->first_carrier_offset = 900; //1536 - ( (106*12) / 2 ) - fp->nb_prefix_samples0 = 132; - fp->nb_prefix_samples = 108; - } - else { - fp->ofdm_symbol_size = 2048; - fp->first_carrier_offset = 1412; //2048 - ( (106*12) / 2 ) - fp->nb_prefix_samples0 = 176; - fp->nb_prefix_samples = 144; - } - break; - - case 50: - case 60: - case 70: - - case 80: //80 MHz - if (fp->threequarter_fs) { - fp->ofdm_symbol_size = 3072; - fp->first_carrier_offset = 1770; //3072 - ( (217*12) / 2 ) - fp->nb_prefix_samples0 = 264; - fp->nb_prefix_samples = 216; - } - else { - fp->ofdm_symbol_size = 4096; - fp->first_carrier_offset = 2794; //4096 - ( (217*12) / 2 ) - fp->nb_prefix_samples0 = 352; - fp->nb_prefix_samples = 288; - } - break; - - case 90: - AssertFatal(fp->threequarter_fs==0,"3/4 sampling impossible for %d MHz band and MU %d\n",bw,mu); - fp->ofdm_symbol_size = 4096; - fp->first_carrier_offset = 2626; //4096 - ( (245*12) / 2 ) - fp->nb_prefix_samples0 = 352; - fp->nb_prefix_samples = 288; - break; - case 100: - AssertFatal(fp->threequarter_fs==0,"3/4 sampling impossible for %d MHz band and MU %d\n",bw,mu); - fp->ofdm_symbol_size = 4096; - fp->first_carrier_offset = 2458; //4096 - ( (273*12) / 2 ) - fp->nb_prefix_samples0 = 352; - fp->nb_prefix_samples = 288; - break; - default: - AssertFatal(1==0,"%d MHz band undefined for mu %d, frame parms = %p\n", bw, mu, fp); - } break; case NR_MU_2: //60kHz scs fp->subcarrier_spacing = nr_subcarrier_spacing[NR_MU_2]; fp->slots_per_subframe = nr_slots_per_subframe[NR_MU_2]; - - switch(bw){ //FR1 bands only - case 10: - case 15: - case 20: - case 25: - case 30: - case 40: - case 50: - case 60: - case 70: - case 80: - case 90: - case 100: - default: - AssertFatal(1==0,"%d MHz band undefined for mu %d, frame parms = %p\n", bw, mu, fp); - } break; case NR_MU_3: fp->subcarrier_spacing = nr_subcarrier_spacing[NR_MU_3]; fp->slots_per_subframe = nr_slots_per_subframe[NR_MU_3]; fp->ssb_type = nr_ssb_type_D; - switch(bw){ - case 100: - fp->ofdm_symbol_size = 1024; - fp->first_carrier_offset = 628; //1024 - ( (66*12) / 2 ) - fp->nb_prefix_samples0 = 136; - fp->nb_prefix_samples = 72; - break; - case 50: - fp->ofdm_symbol_size = 512; - fp->first_carrier_offset = 320; //1024 - ( (66*12) / 2 ) - fp->nb_prefix_samples0 = 68; - fp->nb_prefix_samples = 36; - break; - default: - AssertFatal(1==0,"%d MHz band undefined for mu %d, frame parms = %p\n", bw, mu, fp); - } break; case NR_MU_4: @@ -209,9 +117,21 @@ void set_scs_parameters (NR_DL_FRAME_PARMS *fp, int mu, uint16_t bw) fp->ssb_type = nr_ssb_type_E; break; - default: - AssertFatal(1==0,"Invalid numerology index %d", mu); + default: + AssertFatal(1==0,"Invalid numerology index %d", mu); } + + if(fp->threequarter_fs) + fp->ofdm_symbol_size = 3 * 128; + else + fp->ofdm_symbol_size = 4 * 128; + + while(fp->ofdm_symbol_size < N_RB_DL * 12) + fp->ofdm_symbol_size <<= 1; + + fp->first_carrier_offset = fp->ofdm_symbol_size - (N_RB_DL * 12 / 2); + fp->nb_prefix_samples = fp->ofdm_symbol_size / 128 * 9; + fp->nb_prefix_samples0 = fp->ofdm_symbol_size / 128 * (9 + (1 << mu)); } uint32_t get_samples_per_slot(int slot, NR_DL_FRAME_PARMS* fp) @@ -280,7 +200,7 @@ int nr_init_frame_parms(nfapi_nr_config_request_scf_t* cfg, fp->half_frame_bit = 0; // half frame bit initialized to 0 here fp->numerology_index = mu; - set_scs_parameters(fp, mu, cfg->carrier_config.dl_bandwidth.value); + set_scs_parameters(fp, mu, fp->N_RB_DL); fp->slots_per_frame = 10* fp->slots_per_subframe; @@ -352,9 +272,8 @@ int nr_init_frame_parms_ue(NR_DL_FRAME_PARMS *fp, fp->N_RB_UL = config->carrier_config.ul_grid_size[fp->numerology_index]; fp->N_RB_DL = config->carrier_config.dl_grid_size[fp->numerology_index]; - int32_t uplink_frequency_offset = 0; - get_delta_duplex(fp->nr_band, fp->numerology_index, &uplink_frequency_offset); - get_frame_type(fp->nr_band, fp->numerology_index, &fp->frame_type); + fp->frame_type = get_frame_type(fp->nr_band, fp->numerology_index); + int32_t uplink_frequency_offset = get_delta_duplex(fp->nr_band, fp->numerology_index); uplink_frequency_offset *= 1000; LOG_I(PHY, "Initializing frame parms: DL frequency %lu Hz, UL frequency %lu Hz: band %d, uldl offset %d Hz\n", fp->dl_CarrierFreq, fp->ul_CarrierFreq, fp->nr_band, uplink_frequency_offset); @@ -374,7 +293,7 @@ int nr_init_frame_parms_ue(NR_DL_FRAME_PARMS *fp, fp->Ncp = Ncp; - set_scs_parameters(fp,fp->numerology_index,config->carrier_config.dl_bandwidth); + set_scs_parameters(fp, fp->numerology_index, fp->N_RB_DL); fp->slots_per_frame = 10* fp->slots_per_subframe; fp->symbols_per_slot = ((Ncp == NORMAL)? 14 : 12); // to redefine for different slot formats diff --git a/openair1/PHY/MODULATION/modulation_UE.h b/openair1/PHY/MODULATION/modulation_UE.h index 72a1334fe9..20fdaa7ad8 100644 --- a/openair1/PHY/MODULATION/modulation_UE.h +++ b/openair1/PHY/MODULATION/modulation_UE.h @@ -51,16 +51,13 @@ int slot_fep(PHY_VARS_UE *phy_vars_ue, int nr_slot_fep(PHY_VARS_NR_UE *phy_vars_ue, UE_nr_rxtx_proc_t *proc, unsigned char l, - unsigned char Ns, - int sample_offset, - int no_prefix); + unsigned char Ns); int nr_slot_fep_init_sync(PHY_VARS_NR_UE *ue, UE_nr_rxtx_proc_t *proc, unsigned char symbol, unsigned char Ns, - int sample_offset, - int no_prefix); + int sample_offset); int slot_fep_mbsfn(PHY_VARS_UE *phy_vars_ue, unsigned char l, diff --git a/openair1/PHY/MODULATION/nr_modulation.c b/openair1/PHY/MODULATION/nr_modulation.c index ed9a859fb6..f12dcfc01b 100644 --- a/openair1/PHY/MODULATION/nr_modulation.c +++ b/openair1/PHY/MODULATION/nr_modulation.c @@ -591,35 +591,63 @@ void nr_dft(int32_t *z, int32_t *d, uint32_t Msc_PUSCH) } -void init_symbol_rotation(NR_DL_FRAME_PARMS *fp,uint64_t CarrierFreq) { +void init_symbol_rotation(NR_DL_FRAME_PARMS *fp) { + + uint64_t dl_CarrierFreq = fp->dl_CarrierFreq; + uint64_t ul_CarrierFreq = fp->ul_CarrierFreq; + double f[2] = {(double)dl_CarrierFreq, (double)ul_CarrierFreq}; const int nsymb = fp->symbols_per_slot * fp->slots_per_frame/10; const double Tc=(1/480e3/4096); const double Nu=2048*64*(1/(float)(1<numerology_index)); - const double f0= (double)CarrierFreq; const double Ncp0=16*64 + (144*64*(1/(float)(1<numerology_index))); const double Ncp1=(144*64*(1/(float)(1<numerology_index))); - double tl=0,poff,exp_re,exp_im; - double Ncp,Ncpm1=Ncp0; - poff = 2*M_PI*((Ncp0*Tc))*f0; - exp_re = cos(poff); - exp_im = sin(-poff); - fp->symbol_rotation[0]=(int16_t)floor(exp_re*32767); - fp->symbol_rotation[1]=(int16_t)floor(exp_im*32767); - LOG_I(PHY,"Doing symbol rotation calculation for gNB TX/RX, f0 %f Hz, Nsymb %d\n",f0,nsymb); - LOG_I(PHY,"Symbol rotation %d/%d => (%d,%d)\n",0,nsymb,fp->symbol_rotation[0],fp->symbol_rotation[1]); - for (int l=1;lnumerology_index))) Ncp=Ncp0; - else Ncp=Ncp1; - tl += (Nu+Ncpm1)*Tc; - poff = 2*M_PI*(tl + (Ncp*Tc))*f0; - exp_re = cos(poff); - exp_im = sin(-poff); - fp->symbol_rotation[l<<1]=(int16_t)floor(exp_re*32767); - fp->symbol_rotation[1+(l<<1)]=(int16_t)floor(exp_im*32767); - LOG_I(PHY,"Symbol rotation %d/%d => tl %f (%d,%d) (%f)\n",l,nsymb,tl,fp->symbol_rotation[l<<1],fp->symbol_rotation[1+(l<<1)], - (poff/2/M_PI)-floor(poff/2/M_PI)); - Ncpm1=Ncp; + for (uint8_t ll = 0; ll < 2; ll++){ + + double f0 = f[ll]; + double Ncpm1 = Ncp0; + int16_t *symbol_rotation = fp->symbol_rotation[ll]; + + double tl = 0; + double poff = 2 * M_PI * ((Ncp0 * Tc)) * f0; + double exp_re = cos(poff); + double exp_im = sin(-poff); + symbol_rotation[0] = (int16_t)floor(exp_re * 32767); + symbol_rotation[1] = (int16_t)floor(exp_im * 32767); + LOG_I(PHY, "Doing symbol rotation calculation for gNB TX/RX, f0 %f Hz, Nsymb %d\n", f0, nsymb); + LOG_I(PHY, "Symbol rotation %d/%d => (%d,%d)\n", + 0, + nsymb, + symbol_rotation[0], + symbol_rotation[1]); + + for (int l = 1; l < nsymb; l++) { + + double Ncp; + if (l == (7 * (1 << fp->numerology_index))) { + Ncp = Ncp0; + } else { + Ncp = Ncp1; + } + + tl += (Nu + Ncpm1) * Tc; + poff = 2 * M_PI * (tl + (Ncp * Tc)) * f0; + exp_re = cos(poff); + exp_im = sin(-poff); + symbol_rotation[l<<1] = (int16_t)floor(exp_re * 32767); + symbol_rotation[1 + (l<<1)] = (int16_t)floor(exp_im * 32767); + + LOG_I(PHY, "Symbol rotation %d/%d => tl %f (%d,%d) (%f)\n", + l, + nsymb, + tl, + symbol_rotation[l<<1], + symbol_rotation[1 + (l<<1)], + (poff / 2 / M_PI) - floor(poff / 2 / M_PI)); + + Ncpm1 = Ncp; + + } } } diff --git a/openair1/PHY/MODULATION/nr_modulation.h b/openair1/PHY/MODULATION/nr_modulation.h index 3d2be905ac..841073a1af 100644 --- a/openair1/PHY/MODULATION/nr_modulation.h +++ b/openair1/PHY/MODULATION/nr_modulation.h @@ -74,7 +74,6 @@ void nr_ue_layer_mapping(NR_UE_ULSCH_t **ulsch_ue, \param symbol symbol within slot (0..12/14) \param Ns Slot number (0..19) \param sample_offset offset within rxdata (points to beginning of subframe) -\param no_prefix if 1 prefix is removed by HW */ int nr_slot_fep_ul(NR_DL_FRAME_PARMS *frame_parms, @@ -82,8 +81,7 @@ int nr_slot_fep_ul(NR_DL_FRAME_PARMS *frame_parms, int32_t *rxdataF, unsigned char symbol, unsigned char Ns, - int sample_offset, - int no_prefix); + int sample_offset); /*! \brief This function implements the dft transform precoding in PUSCH @@ -110,7 +108,7 @@ void apply_nr_rotation(NR_DL_FRAME_PARMS *fp, int nsymb, int length); -void init_symbol_rotation(NR_DL_FRAME_PARMS *fp,uint64_t CarrierFreq); +void init_symbol_rotation(NR_DL_FRAME_PARMS *fp); void apply_nr_rotation_ul(NR_DL_FRAME_PARMS *frame_parms, int32_t *rxdataF, diff --git a/openair1/PHY/MODULATION/ofdm_mod.c b/openair1/PHY/MODULATION/ofdm_mod.c index 2d86b46742..8cf9f05b9b 100644 --- a/openair1/PHY/MODULATION/ofdm_mod.c +++ b/openair1/PHY/MODULATION/ofdm_mod.c @@ -306,15 +306,23 @@ void apply_nr_rotation(NR_DL_FRAME_PARMS *fp, int length) { int symb_offset = (slot%fp->slots_per_subframe)*fp->symbols_per_slot; + int16_t *symbol_rotation = fp->symbol_rotation[0]; + for (int sidx=0;sidxsymbol_rotation[2*(sidx+first_symbol+symb_offset)],fp->symbol_rotation[1+2*(sidx+first_symbol+symb_offset)]); - rotate_cpx_vector(trxdata+(sidx*length*2), - &fp->symbol_rotation[2*(sidx+first_symbol+symb_offset)], - trxdata+(sidx*length*2), - length, - 15); + first_symbol + sidx, + slot, + sidx + first_symbol + symb_offset, + length, + symbol_rotation[2 * (sidx + first_symbol + symb_offset)], + symbol_rotation[1 + 2 * (sidx + first_symbol + symb_offset)]); + + rotate_cpx_vector(trxdata + (sidx * length * 2), + &symbol_rotation[2 * (sidx + first_symbol + symb_offset)], + trxdata + (sidx * length * 2), + length, + 15); } } diff --git a/openair1/PHY/MODULATION/slot_fep_nr.c b/openair1/PHY/MODULATION/slot_fep_nr.c index 60b28d4ad1..0be635ba0b 100644 --- a/openair1/PHY/MODULATION/slot_fep_nr.c +++ b/openair1/PHY/MODULATION/slot_fep_nr.c @@ -29,364 +29,121 @@ //#define DEBUG_FEP -#define SOFFSET 0 - /*#ifdef LOG_I #undef LOG_I #define LOG_I(A,B...) printf(A) #endif*/ +dft_size_idx_t get_dft_size_idx(uint16_t ofdm_symbol_size) +{ + switch (ofdm_symbol_size) { + case 128: + return DFT_128; + + case 256: + return DFT_256; + + case 512: + return DFT_512; + + case 1024: + return DFT_1024; + + case 1536: + return DFT_1536; + + case 2048: + return DFT_2048; + + case 3072: + return DFT_3072; + + case 4096: + return DFT_4096; + + case 6144: + return DFT_6144; + + case 8192: + return DFT_8192; + + default: + printf("unsupported ofdm symbol size \n"); + assert(0); + } + + return DFT_SIZE_IDXTABLESIZE; +} + int nr_slot_fep(PHY_VARS_NR_UE *ue, UE_nr_rxtx_proc_t *proc, unsigned char symbol, - unsigned char Ns, - int sample_offset, - int no_prefix) + unsigned char Ns) { NR_DL_FRAME_PARMS *frame_parms = &ue->frame_parms; - NR_UE_COMMON *common_vars = &ue->common_vars; - unsigned char aa; + NR_UE_COMMON *common_vars = &ue->common_vars; + + AssertFatal(symbol < frame_parms->symbols_per_slot, "slot_fep: symbol must be between 0 and %d\n", frame_parms->symbols_per_slot-1); + AssertFatal(Ns < frame_parms->slots_per_frame, "slot_fep: Ns must be between 0 and %d\n", frame_parms->slots_per_frame-1); + unsigned int nb_prefix_samples; unsigned int nb_prefix_samples0; - unsigned int abs_symbol; if (ue->is_synchronized) { - nb_prefix_samples = (no_prefix ? 0 : frame_parms->nb_prefix_samples); - nb_prefix_samples0 = (no_prefix ? 0 : frame_parms->nb_prefix_samples0); - } - else { - nb_prefix_samples = (no_prefix ? 0 : frame_parms->nb_prefix_samples); - nb_prefix_samples0 = (no_prefix ? 0 : frame_parms->nb_prefix_samples); - } - //unsigned int subframe_offset;//,subframe_offset_F; - unsigned int slot_offset; - //int i; - unsigned int frame_length_samples = frame_parms->samples_per_subframe * 10; - unsigned int rx_offset; - - - dft_size_idx_t dftsize; - int tmp_dft_in[8192] __attribute__ ((aligned (32))); // This is for misalignment issues for 6 and 15 PRBs - - switch (frame_parms->ofdm_symbol_size) { - case 128: - dftsize = DFT_128; - break; - - case 256: - dftsize = DFT_256; - break; - - case 512: - dftsize = DFT_512; - break; - - case 1024: - dftsize = DFT_1024; - break; - - case 1536: - dftsize = DFT_1536; - break; - - case 2048: - dftsize = DFT_2048; - break; - - case 3072: - dftsize = DFT_3072; - break; - - case 4096: - dftsize = DFT_4096; - break; - - case 8192: - dftsize = DFT_8192; - break; - - default: - printf("unsupported ofdm symbol size \n"); - assert(0); - } - - if (no_prefix) { - slot_offset = frame_parms->ofdm_symbol_size * (frame_parms->symbols_per_slot) * (Ns); + nb_prefix_samples = frame_parms->nb_prefix_samples; + nb_prefix_samples0 = frame_parms->nb_prefix_samples0; } else { - slot_offset = frame_parms->get_samples_slot_timestamp(Ns,frame_parms,0); + nb_prefix_samples = frame_parms->nb_prefix_samples; + nb_prefix_samples0 = frame_parms->nb_prefix_samples; } - /*if (l<0 || l>=7-frame_parms->Ncp) { - printf("slot_fep: l must be between 0 and %d\n",7-frame_parms->Ncp); - return(-1); - }*/ + dft_size_idx_t dftsize = get_dft_size_idx(frame_parms->ofdm_symbol_size); + // This is for misalignment issues + int32_t tmp_dft_in[8192] __attribute__ ((aligned (32))); - if (Ns<0 || Ns>(frame_parms->slots_per_frame-1)) { - printf("slot_fep: Ns must be between 0 and %d\n",frame_parms->slots_per_frame-1); - return(-1); - } + unsigned int rx_offset = frame_parms->get_samples_slot_timestamp(Ns,frame_parms,0); + unsigned int abs_symbol = Ns * frame_parms->symbols_per_slot + symbol; + for (int idx_symb = Ns*frame_parms->symbols_per_slot; idx_symb <= abs_symbol; idx_symb++) + rx_offset += (idx_symb%(0x7<numerology_index)) ? nb_prefix_samples : nb_prefix_samples0; + rx_offset += frame_parms->ofdm_symbol_size * symbol; - for (aa=0; aanb_antennas_rx; aa++) { - memset(&common_vars->common_vars_rx_data_per_thread[proc->thread_id].rxdataF[aa][frame_parms->ofdm_symbol_size*symbol],0,frame_parms->ofdm_symbol_size*sizeof(int)); - - rx_offset = sample_offset + slot_offset - SOFFSET; - // Align with 256 bit - // rx_offset = rx_offset&0xfffffff8; + // use OFDM symbol from within 1/8th of the CP to avoid ISI + rx_offset -= nb_prefix_samples / 8; #ifdef DEBUG_FEP - // if (ue->frame <100) - /*LOG_I(PHY,*/printf("slot_fep: slot %d, symbol %d, nb_prefix_samples %u, nb_prefix_samples0 %u, slot_offset %u, sample_offset %d,rx_offset %u, frame_length_samples %u\n", - Ns, symbol, nb_prefix_samples, nb_prefix_samples0, slot_offset, sample_offset, rx_offset, frame_length_samples); + // if (ue->frame <100) + printf("slot_fep: slot %d, symbol %d, nb_prefix_samples %u, nb_prefix_samples0 %u, rx_offset %u\n", + Ns, symbol, nb_prefix_samples, nb_prefix_samples0, rx_offset); #endif - abs_symbol = Ns * frame_parms->symbols_per_slot + symbol; - - for (int idx_symb = Ns*frame_parms->symbols_per_slot; idx_symb < abs_symbol; idx_symb++) - rx_offset += (idx_symb%(0x7<numerology_index)) ? nb_prefix_samples : nb_prefix_samples0; + for (unsigned char aa=0; aanb_antennas_rx; aa++) { + memset(&common_vars->common_vars_rx_data_per_thread[proc->thread_id].rxdataF[aa][frame_parms->ofdm_symbol_size*symbol],0,frame_parms->ofdm_symbol_size*sizeof(int32_t)); - rx_offset += frame_parms->ofdm_symbol_size * symbol; - - if (abs_symbol%(0x7<numerology_index)) { - - rx_offset += nb_prefix_samples; - if (rx_offset > (frame_length_samples - frame_parms->ofdm_symbol_size)) - memcpy((short*) &common_vars->rxdata[aa][frame_length_samples], - (short*) &common_vars->rxdata[aa][0], - frame_parms->ofdm_symbol_size*sizeof(int)); - - if ((rx_offset&7)!=0) { // if input to dft is not 256-bit aligned, issue for size 6,15 and 25 PRBs - memcpy((void *)tmp_dft_in, - (void *) &common_vars->rxdata[aa][rx_offset % frame_length_samples], - frame_parms->ofdm_symbol_size*sizeof(int)); - dft(dftsize,(int16_t *)tmp_dft_in, - (int16_t *)&common_vars->common_vars_rx_data_per_thread[proc->thread_id].rxdataF[aa][frame_parms->ofdm_symbol_size*symbol],1); - } else { // use dft input from RX buffer directly -#if UE_TIMING_TRACE - start_meas(&ue->rx_dft_stats); -#endif - - dft(dftsize,(int16_t *) &common_vars->rxdata[aa][(rx_offset) % frame_length_samples], - (int16_t *)&common_vars->common_vars_rx_data_per_thread[proc->thread_id].rxdataF[aa][frame_parms->ofdm_symbol_size*symbol],1); -#if UE_TIMING_TRACE - stop_meas(&ue->rx_dft_stats); -#endif - } - } else { - - rx_offset += nb_prefix_samples0; - if (rx_offset > (frame_length_samples - frame_parms->ofdm_symbol_size)) - memcpy((void *) &common_vars->rxdata[aa][frame_length_samples], - (void *) &common_vars->rxdata[aa][0], - frame_parms->ofdm_symbol_size*sizeof(int)); -#if UE_TIMING_TRACE - start_meas(&ue->rx_dft_stats); -#endif - - if ((rx_offset&7)!=0) { // if input to dft is not 128-bit aligned, issue for size 6 and 15 PRBs - memcpy((void *)tmp_dft_in, - (void *) &common_vars->rxdata[aa][(rx_offset) % frame_length_samples], - frame_parms->ofdm_symbol_size*sizeof(int)); - dft(dftsize,(int16_t *)tmp_dft_in, - (int16_t *)&common_vars->common_vars_rx_data_per_thread[proc->thread_id].rxdataF[aa][frame_parms->ofdm_symbol_size*symbol],1); - } else { // use dft input from RX buffer directly - - dft(dftsize,(int16_t *) &common_vars->rxdata[aa][(rx_offset) % frame_length_samples], - (int16_t *)&common_vars->common_vars_rx_data_per_thread[proc->thread_id].rxdataF[aa][frame_parms->ofdm_symbol_size*symbol],1); - } -#if UE_TIMING_TRACE - stop_meas(&ue->rx_dft_stats); -#endif + int16_t *rxdata_ptr = (int16_t *)&common_vars->rxdata[aa][rx_offset]; + // if input to dft is not 256-bit aligned + if ((rx_offset & 7) != 0) { + memcpy((void *)&tmp_dft_in[0], + (void *)&common_vars->rxdata[aa][rx_offset], + frame_parms->ofdm_symbol_size * sizeof(int32_t)); + rxdata_ptr = (int16_t *)tmp_dft_in; } -#ifdef DEBUG_FEP - // if (ue->frame <100) - printf("slot_fep: symbol %d rx_offset %u\n", symbol, rx_offset); -#endif - - int symb_offset = (Ns%frame_parms->slots_per_subframe)*frame_parms->symbols_per_slot; - int32_t rot2 = ((uint32_t*)frame_parms->symbol_rotation)[symbol+symb_offset]; - ((int16_t*)&rot2)[1]=-((int16_t*)&rot2)[1]; - rotate_cpx_vector((int16_t *)&common_vars->common_vars_rx_data_per_thread[proc->thread_id].rxdataF[aa][frame_parms->ofdm_symbol_size*symbol], - (int16_t*)&rot2, - (int16_t *)&common_vars->common_vars_rx_data_per_thread[proc->thread_id].rxdataF[aa][frame_parms->ofdm_symbol_size*symbol], - frame_parms->ofdm_symbol_size, - 15); - - } - - -#ifdef DEBUG_FEP - printf("slot_fep: done\n"); -#endif - return(0); -} - -int nr_slot_fep_init_sync(PHY_VARS_NR_UE *ue, - UE_nr_rxtx_proc_t *proc, - unsigned char symbol, - unsigned char Ns, - int sample_offset, - int no_prefix) -{ - NR_DL_FRAME_PARMS *frame_parms = &ue->frame_parms; - NR_UE_COMMON *common_vars = &ue->common_vars; - unsigned char aa; - unsigned int nb_prefix_samples; - unsigned int nb_prefix_samples0; - unsigned int abs_symbol; - if (ue->is_synchronized) { - nb_prefix_samples = (no_prefix ? 0 : frame_parms->nb_prefix_samples); - nb_prefix_samples0 = (no_prefix ? 0 : frame_parms->nb_prefix_samples0); - } - else { - nb_prefix_samples = (no_prefix ? 0 : frame_parms->nb_prefix_samples); - nb_prefix_samples0 = (no_prefix ? 0 : frame_parms->nb_prefix_samples); - } - //unsigned int subframe_offset;//,subframe_offset_F; - unsigned int slot_offset; - //int i; - unsigned int frame_length_samples = frame_parms->samples_per_subframe * 10; - unsigned int rx_offset; - - - dft_size_idx_t dftsize; - int tmp_dft_in[8192] __attribute__ ((aligned (32))); // This is for misalignment issues for 6 and 15 PRBs - - switch (frame_parms->ofdm_symbol_size) { - case 128: - dftsize = DFT_128; - break; - - case 256: - dftsize = DFT_256; - break; - - case 512: - dftsize = DFT_512; - break; - - case 1024: - dftsize = DFT_1024; - break; - - case 1536: - dftsize = DFT_1536; - break; - - case 2048: - dftsize = DFT_2048; - break; - - case 3072: - dftsize = DFT_3072; - break; - - case 4096: - dftsize = DFT_4096; - break; - - case 8192: - dftsize = DFT_8192; - break; - - default: - printf("unsupported ofdm symbol size \n"); - assert(0); - } - - if (no_prefix) { - slot_offset = frame_parms->ofdm_symbol_size * (frame_parms->symbols_per_slot) * (Ns); - } else { - slot_offset = frame_parms->get_samples_slot_timestamp(Ns,frame_parms,0); - } - - /*if (l<0 || l>=7-frame_parms->Ncp) { - printf("slot_fep: l must be between 0 and %d\n",7-frame_parms->Ncp); - return(-1); - }*/ - - if (Ns<0 || Ns>(frame_parms->slots_per_frame-1)) { - printf("slot_fep: Ns must be between 0 and %d\n",frame_parms->slots_per_frame-1); - return(-1); - } - - for (aa=0; aanb_antennas_rx; aa++) { - memset(&common_vars->common_vars_rx_data_per_thread[proc->thread_id].rxdataF[aa][frame_parms->ofdm_symbol_size*symbol],0,frame_parms->ofdm_symbol_size*sizeof(int)); - - rx_offset = sample_offset + slot_offset - SOFFSET; - // Align with 256 bit - // rx_offset = rx_offset&0xfffffff8; - -#ifdef DEBUG_FEP - // if (ue->frame <100) - /*LOG_I(PHY,*/printf("slot_fep: slot %d, symbol %d, nb_prefix_samples %u, nb_prefix_samples0 %u, slot_offset %u, sample_offset %d,rx_offset %u, frame_length_samples %u\n", - Ns, symbol, nb_prefix_samples, nb_prefix_samples0, slot_offset, sample_offset, rx_offset, frame_length_samples); -#endif - - abs_symbol = Ns * frame_parms->symbols_per_slot + symbol; - - for (int idx_symb = Ns*frame_parms->symbols_per_slot; idx_symb < abs_symbol; idx_symb++) - rx_offset += (abs_symbol%(0x7<numerology_index)) ? nb_prefix_samples : nb_prefix_samples0; - - rx_offset += frame_parms->ofdm_symbol_size * symbol; - - if (abs_symbol%(0x7<numerology_index)) { - - rx_offset += nb_prefix_samples; - if (rx_offset > (frame_length_samples - frame_parms->ofdm_symbol_size)) - memcpy((short*) &common_vars->rxdata[aa][frame_length_samples], - (short*) &common_vars->rxdata[aa][0], - frame_parms->ofdm_symbol_size*sizeof(int)); - - if ((rx_offset&7)!=0) { // if input to dft is not 256-bit aligned, issue for size 6,15 and 25 PRBs - memcpy((void *)tmp_dft_in, - (void *) &common_vars->rxdata[aa][rx_offset], - frame_parms->ofdm_symbol_size*sizeof(int)); - dft(dftsize,(int16_t *)tmp_dft_in, - (int16_t *)&common_vars->common_vars_rx_data_per_thread[proc->thread_id].rxdataF[aa][frame_parms->ofdm_symbol_size*symbol],1); - } else { // use dft input from RX buffer directly #if UE_TIMING_TRACE - start_meas(&ue->rx_dft_stats); + start_meas(&ue->rx_dft_stats); #endif + dft(dftsize, + rxdata_ptr, + (int16_t *)&common_vars->common_vars_rx_data_per_thread[proc->thread_id].rxdataF[aa][frame_parms->ofdm_symbol_size*symbol], + 1); - dft(dftsize,(int16_t *) &common_vars->rxdata[aa][rx_offset], - (int16_t *)&common_vars->common_vars_rx_data_per_thread[proc->thread_id].rxdataF[aa][frame_parms->ofdm_symbol_size*symbol],1); #if UE_TIMING_TRACE - stop_meas(&ue->rx_dft_stats); + stop_meas(&ue->rx_dft_stats); #endif - } - } else { - - rx_offset += nb_prefix_samples0; - if (rx_offset > (frame_length_samples - frame_parms->ofdm_symbol_size)) - memcpy((void *) &common_vars->rxdata[aa][frame_length_samples], - (void *) &common_vars->rxdata[aa][0], - frame_parms->ofdm_symbol_size*sizeof(int)); -#if UE_TIMING_TRACE - start_meas(&ue->rx_dft_stats); -#endif - - if ((rx_offset&7)!=0) { // if input to dft is not 128-bit aligned, issue for size 6 and 15 PRBs - memcpy((void *)tmp_dft_in, - (void *) &common_vars->rxdata[aa][rx_offset], - frame_parms->ofdm_symbol_size*sizeof(int)); - dft(dftsize,(int16_t *)tmp_dft_in, - (int16_t *)&common_vars->common_vars_rx_data_per_thread[proc->thread_id].rxdataF[aa][frame_parms->ofdm_symbol_size*symbol],1); - } else { // use dft input from RX buffer directly - dft(dftsize,(int16_t *) &common_vars->rxdata[aa][rx_offset], - (int16_t *)&common_vars->common_vars_rx_data_per_thread[proc->thread_id].rxdataF[aa][frame_parms->ofdm_symbol_size*symbol],1); - } -#if UE_TIMING_TRACE - stop_meas(&ue->rx_dft_stats); -#endif - - - } int symb_offset = (Ns%frame_parms->slots_per_subframe)*frame_parms->symbols_per_slot; - int32_t rot2 = ((uint32_t*)frame_parms->symbol_rotation)[symbol+symb_offset]; + int32_t rot2 = ((uint32_t*)frame_parms->symbol_rotation[0])[symbol+symb_offset]; ((int16_t*)&rot2)[1]=-((int16_t*)&rot2)[1]; #ifdef DEBUG_FEP @@ -400,14 +157,121 @@ int nr_slot_fep_init_sync(PHY_VARS_NR_UE *ue, (int16_t *)&common_vars->common_vars_rx_data_per_thread[proc->thread_id].rxdataF[aa][frame_parms->ofdm_symbol_size*symbol], frame_parms->ofdm_symbol_size, 15); - } - #ifdef DEBUG_FEP printf("slot_fep: done\n"); #endif - return(0); + + return 0; +} + +int nr_slot_fep_init_sync(PHY_VARS_NR_UE *ue, + UE_nr_rxtx_proc_t *proc, + unsigned char symbol, + unsigned char Ns, + int sample_offset) +{ + NR_DL_FRAME_PARMS *frame_parms = &ue->frame_parms; + NR_UE_COMMON *common_vars = &ue->common_vars; + + AssertFatal(symbol < frame_parms->symbols_per_slot, "slot_fep: symbol must be between 0 and %d\n", frame_parms->symbols_per_slot-1); + AssertFatal(Ns < frame_parms->slots_per_frame, "slot_fep: Ns must be between 0 and %d\n", frame_parms->slots_per_frame-1); + + unsigned int nb_prefix_samples; + unsigned int nb_prefix_samples0; + if (ue->is_synchronized) { + nb_prefix_samples = frame_parms->nb_prefix_samples; + nb_prefix_samples0 = frame_parms->nb_prefix_samples0; + } + else { + nb_prefix_samples = frame_parms->nb_prefix_samples; + nb_prefix_samples0 = frame_parms->nb_prefix_samples; + } + unsigned int frame_length_samples = frame_parms->samples_per_frame; + + dft_size_idx_t dftsize = get_dft_size_idx(frame_parms->ofdm_symbol_size); + // This is for misalignment issues + int32_t tmp_dft_in[8192] __attribute__ ((aligned (32))); + + unsigned int slot_offset = frame_parms->get_samples_slot_timestamp(Ns,frame_parms,0); + unsigned int rx_offset = sample_offset + slot_offset; + unsigned int abs_symbol = Ns * frame_parms->symbols_per_slot + symbol; + for (int idx_symb = Ns*frame_parms->symbols_per_slot; idx_symb <= abs_symbol; idx_symb++) + rx_offset += (abs_symbol%(0x7<numerology_index)) ? nb_prefix_samples : nb_prefix_samples0; + rx_offset += frame_parms->ofdm_symbol_size * symbol; + +#ifdef DEBUG_FEP + // if (ue->frame <100) + printf("slot_fep: slot %d, symbol %d, nb_prefix_samples %u, nb_prefix_samples0 %u, slot_offset %u, sample_offset %d,rx_offset %u, frame_length_samples %u\n", + Ns, symbol, nb_prefix_samples, nb_prefix_samples0, slot_offset, sample_offset, rx_offset, frame_length_samples); +#endif + + for (unsigned char aa=0; aanb_antennas_rx; aa++) { + memset(&common_vars->common_vars_rx_data_per_thread[proc->thread_id].rxdataF[aa][frame_parms->ofdm_symbol_size*symbol],0,frame_parms->ofdm_symbol_size*sizeof(int32_t)); + + int16_t *rxdata_ptr; + + if (frame_length_samples - rx_offset < frame_parms->ofdm_symbol_size) { + + memcpy((void *)&tmp_dft_in[0], + (void *)&common_vars->rxdata[aa][rx_offset], + (frame_length_samples - rx_offset) * sizeof(int32_t)); + memcpy((void *)&tmp_dft_in[frame_length_samples - rx_offset], + (void *)&common_vars->rxdata[aa][0], + (frame_parms->ofdm_symbol_size - (frame_length_samples - rx_offset)) * sizeof(int32_t)); + rxdata_ptr = (int16_t *)&tmp_dft_in[0]; + + } else if ((rx_offset & 7) != 0) { + + // if input to dft is not 256-bit aligned + memcpy((void *)&tmp_dft_in[0], + (void *)&common_vars->rxdata[aa][rx_offset], + frame_parms->ofdm_symbol_size * sizeof(int32_t)); + rxdata_ptr = (int16_t *)&tmp_dft_in[0]; + + } else { + + // use dft input from RX buffer directly + rxdata_ptr = (int16_t *)&common_vars->rxdata[aa][rx_offset]; + + } + +#if UE_TIMING_TRACE + start_meas(&ue->rx_dft_stats); +#endif + + dft(dftsize, + rxdata_ptr, + (int16_t *)&common_vars->common_vars_rx_data_per_thread[proc->thread_id].rxdataF[aa][frame_parms->ofdm_symbol_size*symbol], + 1); + +#if UE_TIMING_TRACE + stop_meas(&ue->rx_dft_stats); +#endif + + int symb_offset = (Ns%frame_parms->slots_per_subframe)*frame_parms->symbols_per_slot; + int32_t rot2 = ((uint32_t*)frame_parms->symbol_rotation[0])[symbol + symb_offset]; + ((int16_t*)&rot2)[1]=-((int16_t*)&rot2)[1]; + +#ifdef DEBUG_FEP + // if (ue->frame <100) + printf("slot_fep: slot %d, symbol %d rx_offset %u, rotation symbol %d %d.%d\n", Ns,symbol, rx_offset, + symbol+symb_offset,((int16_t*)&rot2)[0],((int16_t*)&rot2)[1]); +#endif + + rotate_cpx_vector((int16_t *)&common_vars->common_vars_rx_data_per_thread[proc->thread_id].rxdataF[aa][frame_parms->ofdm_symbol_size*symbol], + (int16_t*)&rot2, + (int16_t *)&common_vars->common_vars_rx_data_per_thread[proc->thread_id].rxdataF[aa][frame_parms->ofdm_symbol_size*symbol], + frame_parms->ofdm_symbol_size, + 15); + } + +#ifdef DEBUG_FEP + printf("slot_fep: done\n"); +#endif + + return 0; } @@ -416,89 +280,60 @@ int nr_slot_fep_ul(NR_DL_FRAME_PARMS *frame_parms, int32_t *rxdataF, unsigned char symbol, unsigned char Ns, - int sample_offset, - int no_prefix) + int sample_offset) { - int32_t slot_offset, rxdata_offset; - - unsigned int nb_prefix_samples = (no_prefix ? 0 : frame_parms->nb_prefix_samples); - unsigned int nb_prefix_samples0 = (no_prefix ? 0 : frame_parms->nb_prefix_samples0); + unsigned int nb_prefix_samples = frame_parms->nb_prefix_samples; + unsigned int nb_prefix_samples0 = frame_parms->nb_prefix_samples0; - int tmp_dft_in[8192] __attribute__ ((aligned (32))); + dft_size_idx_t dftsize = get_dft_size_idx(frame_parms->ofdm_symbol_size); + // This is for misalignment issues + int32_t tmp_dft_in[8192] __attribute__ ((aligned (32))); - dft_size_idx_t dftsize; + unsigned int slot_offset = frame_parms->get_samples_slot_timestamp(Ns,frame_parms,0); - switch (frame_parms->ofdm_symbol_size) { - case 128: - dftsize = DFT_128; - break; + // offset of first OFDM symbol + int32_t rxdata_offset = slot_offset + nb_prefix_samples0; + // offset of n-th OFDM symbol + rxdata_offset += symbol * (frame_parms->ofdm_symbol_size + nb_prefix_samples); + // use OFDM symbol from within 1/8th of the CP to avoid ISI + rxdata_offset -= nb_prefix_samples / 8; - case 256: - dftsize = DFT_256; - break; + int16_t *rxdata_ptr; - case 512: - dftsize = DFT_512; - break; + if(sample_offset > rxdata_offset) { - case 1024: - dftsize = DFT_1024; - break; + memcpy((void *)&tmp_dft_in[0], + (void *)&rxdata[frame_parms->samples_per_frame - sample_offset + rxdata_offset], + (sample_offset - rxdata_offset) * sizeof(int32_t)); + memcpy((void *)&tmp_dft_in[sample_offset - rxdata_offset], + (void *)&rxdata[0], + (frame_parms->ofdm_symbol_size - sample_offset + rxdata_offset) * sizeof(int32_t)); + rxdata_ptr = (int16_t *)&tmp_dft_in[0]; - case 1536: - dftsize = DFT_1536; - break; + } else if (((rxdata_offset - sample_offset) & 7) != 0) { - case 2048: - dftsize = DFT_2048; - break; + // if input to dft is not 256-bit aligned + memcpy((void *)&tmp_dft_in[0], + (void *)&rxdata[rxdata_offset - sample_offset], + (frame_parms->ofdm_symbol_size) * sizeof(int32_t)); + rxdata_ptr = (int16_t *)&tmp_dft_in[0]; - case 4096: - dftsize = DFT_4096; - break; + } else { - case 8192: - dftsize = DFT_8192; - break; + // use dft input from RX buffer directly + rxdata_ptr = (int16_t *)&rxdata[rxdata_offset - sample_offset]; - default: - dftsize = DFT_512; - break; } - - slot_offset = frame_parms->get_samples_slot_timestamp(Ns,frame_parms,0); - if(symbol == 0) - rxdata_offset = slot_offset + nb_prefix_samples0 - SOFFSET; - else - rxdata_offset = slot_offset + nb_prefix_samples0 + (symbol * (frame_parms->ofdm_symbol_size + nb_prefix_samples)) - SOFFSET; - - if(sample_offset>rxdata_offset) { - memcpy1((void *)tmp_dft_in, - (void *) &rxdata[frame_parms->samples_per_frame-sample_offset+rxdata_offset], - (sample_offset-rxdata_offset)*sizeof(int)); - - memcpy1((void *)&tmp_dft_in[sample_offset-rxdata_offset], - (void *) &rxdata[0], - (frame_parms->ofdm_symbol_size-sample_offset+rxdata_offset)*sizeof(int)); - - dft(dftsize,(int16_t *)&tmp_dft_in, - (int16_t *)&rxdataF[symbol * frame_parms->ofdm_symbol_size], 1); - } - else { - //dft(dftsize,(int16_t *)&rxdata[rxdata_offset-sample_offset], - // (int16_t *)&rxdataF[symbol * frame_parms->ofdm_symbol_size], 1); - memcpy((void *)tmp_dft_in, - (void *) &rxdata[rxdata_offset-sample_offset], - (frame_parms->ofdm_symbol_size)*sizeof(int)); - dft(dftsize,(int16_t *)&tmp_dft_in, - (int16_t *)&rxdataF[symbol * frame_parms->ofdm_symbol_size], 1); - } + dft(dftsize, + rxdata_ptr, + (int16_t *)&rxdataF[symbol * frame_parms->ofdm_symbol_size], + 1); // clear DC carrier from OFDM symbols rxdataF[symbol * frame_parms->ofdm_symbol_size] = 0; - return(0); + return 0; } void apply_nr_rotation_ul(NR_DL_FRAME_PARMS *frame_parms, @@ -513,7 +348,7 @@ void apply_nr_rotation_ul(NR_DL_FRAME_PARMS *frame_parms, for (int symbol=0;symbolsymbol_rotation)[symbol+symb_offset]; + uint32_t rot2 = ((uint32_t*)frame_parms->symbol_rotation[1])[symbol + symb_offset]; ((int16_t*)&rot2)[1]=-((int16_t*)&rot2)[1]; LOG_D(PHY,"slot %d, symb_offset %d rotating by %d.%d\n",slot,symb_offset,((int16_t*)&rot2)[0],((int16_t*)&rot2)[1]); rotate_cpx_vector((int16_t *)&rxdataF[frame_parms->ofdm_symbol_size*symbol], diff --git a/openair1/PHY/NR_ESTIMATION/nr_measurements_gNB.c b/openair1/PHY/NR_ESTIMATION/nr_measurements_gNB.c index ec55eabf31..a54aec7bc2 100644 --- a/openair1/PHY/NR_ESTIMATION/nr_measurements_gNB.c +++ b/openair1/PHY/NR_ESTIMATION/nr_measurements_gNB.c @@ -37,22 +37,20 @@ int nr_est_timing_advance_pusch(PHY_VARS_gNB* gNB, int UE_id) { - int temp, i, aa, max_pos = 0, max_val = 0; - short Re, Im; - uint8_t cyclic_shift = 0; + int i, aa, max_pos = 0, max_val = 0; NR_DL_FRAME_PARMS *frame_parms = &gNB->frame_parms; NR_gNB_PUSCH *gNB_pusch_vars = gNB->pusch_vars[UE_id]; int32_t **ul_ch_estimates_time = gNB_pusch_vars->ul_ch_estimates_time; - int sync_pos = (frame_parms->ofdm_symbol_size - cyclic_shift*frame_parms->ofdm_symbol_size/12) % (frame_parms->ofdm_symbol_size); + int sync_pos = frame_parms->nb_prefix_samples / 8; for (i = 0; i < frame_parms->ofdm_symbol_size; i++) { - temp = 0; + int temp = 0; for (aa = 0; aa < frame_parms->nb_antennas_rx; aa++) { - Re = ((int16_t*)ul_ch_estimates_time[aa])[(i<<1)]; - Im = ((int16_t*)ul_ch_estimates_time[aa])[1+(i<<1)]; + short Re = ((int16_t*)ul_ch_estimates_time[aa])[(i<<1)]; + short Im = ((int16_t*)ul_ch_estimates_time[aa])[1+(i<<1)]; temp += (Re*Re/2) + (Im*Im/2); } diff --git a/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c b/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c index 38b35dcf6d..10ac23bef0 100644 --- a/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c +++ b/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c @@ -61,8 +61,6 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB, debug_ch_est = fopen("debug_ch_est.txt","w"); #endif - //uint16_t Nid_cell = (eNB_offset == 0) ? gNB->frame_parms.Nid_cell : gNB->measurements.adj_cell_id[eNB_offset-1]; - uint8_t nushift; int **ul_ch_estimates = gNB->pusch_vars[ul_id]->ul_ch_estimates; int **rxdataF = gNB->common_vars.rxdataF; @@ -79,12 +77,17 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB, uint16_t nb_rb_pusch = pusch_pdu->rb_size; -/* #ifdef DEBUG_CH - printf("PUSCH Channel Estimation : ch_offset %d, symbol_offset %d OFDM size %d, Ncp=%d, l=%d, Ns=%d, k=%d symbol %d\n", ,ch_offset,symbol_offset,gNB->frame_parms.ofdm_symbol_size, - gNB->frame_parms.Ncp,l,Ns,k, symbol); + LOG_D(PHY, "In %s: ch_offset %d, symbol_offset %d OFDM size %d, Ns = %d, k = %d symbol %d\n", + __FUNCTION__, + ch_offset, + symbol_offset, + gNB->frame_parms.ofdm_symbol_size, + Ns, + k, + symbol); #endif -*/ + switch (nushift) { case 0: fl = filt8_l0; @@ -124,9 +127,9 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB, //------------------generate DMRS------------------// - if (pusch_pdu->transform_precoding == transform_precoder_disabled) + if (pusch_pdu->transform_precoding == transform_precoder_disabled) { nr_pusch_dmrs_rx(gNB, Ns, gNB->nr_gold_pusch_dmrs[pusch_pdu->scid][Ns][symbol], &pilot[0], 1000, 0, nb_rb_pusch, pusch_pdu->rb_start*NR_NB_SC_PER_RB, pusch_pdu->dmrs_config_type); - + } else { // if transform precoding or SC-FDMA is enabled in Uplink // NR_SC_FDMA supports type1 DMRS so only 6 DMRS REs per RB possible @@ -151,11 +154,15 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB, //------------------------------------------------// - #ifdef DEBUG_PUSCH - for (int i=0;i<(6*nb_rb_pusch);i++) - printf("%d+j*(%d)\n",((int16_t*)pilot)[2*i],((int16_t*)pilot)[1+(2*i)]); + for (int i = 0; i < (6 * nb_rb_pusch); i++) { + LOG_I(PHY, "In %s: %d + j*(%d)\n", + __FUNCTION__, + ((int16_t*)pilot)[2 * i], + ((int16_t*)pilot)[1 + (2 * i)]); + } #endif + for (aarx=0; aarxframe_parms.nb_antennas_rx; aarx++) { re_offset = k; /* Initializing the Resource element offset for each Rx antenna */ @@ -167,11 +174,11 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB, memset(ul_ch,0,4*(gNB->frame_parms.ofdm_symbol_size)); #ifdef DEBUG_PUSCH - printf("symbol_offset %d, nushift %d\n",symbol_offset,nushift); - printf("ch est pilot addr %p RB_DL %d\n",&pilot[0], gNB->frame_parms.N_RB_UL); - printf("bwp_start_subcarrier %d, k %d, first_carrier %d, nb_rb_pusch %d\n",bwp_start_subcarrier,k,gNB->frame_parms.first_carrier_offset,nb_rb_pusch); - printf("rxF addr %p p %d\n", rxF,p); - printf("ul_ch addr %p nushift %d\n",ul_ch,nushift); + LOG_I(PHY, "In %s symbol_offset %d, nushift %d\n", __FUNCTION__, symbol_offset, nushift); + LOG_I(PHY, "In %s ch est pilot addr %p, N_RB_UL %d\n", __FUNCTION__, &pilot[0], gNB->frame_parms.N_RB_UL); + LOG_I(PHY, "In %s bwp_start_subcarrier %d, k %d, first_carrier %d, nb_rb_pusch %d\n", __FUNCTION__, bwp_start_subcarrier, k, gNB->frame_parms.first_carrier_offset, nb_rb_pusch); + LOG_I(PHY, "In %s rxF addr %p p %d\n", __FUNCTION__, rxF, p); + LOG_I(PHY, "In %s ul_ch addr %p nushift %d\n", __FUNCTION__, ul_ch, nushift); #endif //if ((gNB->frame_parms.N_RB_UL&1)==0) { @@ -182,9 +189,18 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB, ch[1] = (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15); #ifdef DEBUG_PUSCH - printf("ch 0 %d\n",((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])); - printf("pilot 0 : rxF - > (%d,%d) (%d) ch -> (%d,%d) (%d), pil -> (%d,%d) \n",rxF[0],rxF[1],dBc(rxF[0],rxF[1]),ch[0],ch[1],dBc(ch[0],ch[1]),pil[0],pil[1]); - printf("data 0 : rxF - > (%d,%d) (%d)\n",rxF[2],rxF[3],dBc(rxF[2],rxF[3])); + LOG_I(PHY, "In %s ch 0 %d\n", __FUNCTION__, ((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])); + LOG_I(PHY, "In %s pilot 0 : rxF - > (%d,%d) (%d) ch -> (%d,%d) (%d), pil -> (%d,%d) \n", + __FUNCTION__, + rxF[0], + rxF[1], + dBc(rxF[0],rxF[1]), + ch[0], + ch[1], + dBc(ch[0],ch[1]), + pil[0], + pil[1]); + LOG_I(PHY, "In %s data 0 : rxF - > (%d,%d) (%d)\n", __FUNCTION__, rxF[2], rxF[3], dBc(rxF[2],rxF[3])); #endif multadd_real_vector_complex_scalar(fl, @@ -201,9 +217,23 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB, ch[1] = (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15); #ifdef DEBUG_PUSCH - printf("pilot 1 : rxF - > (%d,%d) (%d) ch -> (%d,%d) (%d), pil -> (%d,%d) \n",rxF[0],rxF[1],dBc(rxF[0],rxF[1]),ch[0],ch[1],dBc(ch[0],ch[1]),pil[0],pil[1]); - printf("data 1 : rxF - > (%d,%d) (%d)\n",rxF[2],rxF[3],dBc(rxF[2],rxF[3])); + LOG_I(PHY, "In %s pilot 1 : rxF - > (%d,%d) (%d) ch -> (%d,%d) (%d), pil -> (%d,%d) \n", + __FUNCTION__, + rxF[0], + rxF[1], + dBc(rxF[0],rxF[1]), + ch[0], + ch[1], + dBc(ch[0],ch[1]), + pil[0], + pil[1]); + LOG_I(PHY, "In %s data 1 : rxF - > (%d,%d) (%d)\n", + __FUNCTION__, + rxF[2], + rxF[3], + dBc(rxF[2],rxF[3])); #endif + multadd_real_vector_complex_scalar(fml, ch, ul_ch, @@ -217,9 +247,23 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB, ch[1] = (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15); #ifdef DEBUG_PUSCH - printf("pilot 2 : rxF - > (%d,%d) (%d) ch -> (%d,%d) (%d), pil -> (%d,%d) \n",rxF[0],rxF[1],dBc(rxF[0],rxF[1]),ch[0],ch[1],dBc(ch[0],ch[1]),pil[0],pil[1]); - printf("data 2 : rxF - > (%d,%d) (%d)\n",rxF[2],rxF[3],dBc(rxF[2],rxF[3])); + LOG_I(PHY, "In %s pilot 2 : rxF - > (%d,%d) (%d) ch -> (%d,%d) (%d), pil -> (%d,%d) \n", + __FUNCTION__, + rxF[0], + rxF[1], + dBc(rxF[0],rxF[1]), + ch[0], + ch[1], + dBc(ch[0],ch[1]), + pil[0], + pil[1]); + LOG_I(PHY, "In %s data 2 : rxF - > (%d,%d) (%d)\n", + __FUNCTION__, + rxF[2], + rxF[3], + dBc(rxF[2],rxF[3])); #endif + multadd_real_vector_complex_scalar(fmm, ch, ul_ch, diff --git a/openair1/PHY/NR_REFSIG/nr_dmrs_rx.c b/openair1/PHY/NR_REFSIG/nr_dmrs_rx.c index 5d62f9dbb9..5a4b1adbb8 100644 --- a/openair1/PHY/NR_REFSIG/nr_dmrs_rx.c +++ b/openair1/PHY/NR_REFSIG/nr_dmrs_rx.c @@ -40,9 +40,9 @@ #include "PHY/defs_gNB.h" /*Table 7.4.1.1.2-1/2 from 38.211 */ -int wf1[8][2] = {{1,1},{1,-1},{1,1},{1,-1},{1,1},{1,-1},{1,1},{1,1}}; +int wf1[8][2] = {{1,1},{1,-1},{1,1},{1,-1},{1,1},{1,-1},{1,1},{1,-1}}; int wt1[8][2] = {{1,1},{1,1},{1,1},{1,1},{1,-1},{1,-1},{1,-1},{1,-1}}; -int wf2[12][2] = {{1,1},{1,-1},{1,1},{1,-1},{1,1},{1,-1},{1,1},{1,1},{1,1},{1,-1},{1,1},{1,1}}; +int wf2[12][2] = {{1,1},{1,-1},{1,1},{1,-1},{1,1},{1,-1},{1,1},{1,-1},{1,1},{1,-1},{1,1},{1,-1}}; int wt2[12][2] = {{1,1},{1,1},{1,1},{1,1},{1,1},{1,1},{1,-1},{1,-1},{1,-1},{1,-1},{1,-1},{1,-1}}; // complex conjugate of mod table diff --git a/openair1/PHY/NR_TRANSPORT/nr_dlsch.c b/openair1/PHY/NR_TRANSPORT/nr_dlsch.c index 1cce5e1174..66fc987f6d 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_dlsch.c +++ b/openair1/PHY/NR_TRANSPORT/nr_dlsch.c @@ -147,19 +147,18 @@ uint8_t nr_generate_pdsch(PHY_VARS_gNB *gNB, uint16_t n_dmrs; if (rel15->dmrsConfigType==NFAPI_NR_DMRS_TYPE1) { nb_re_dmrs = 6*rel15->numDmrsCdmGrpsNoData; - n_dmrs = ((rel15->rbSize+rel15->rbStart)*6)<<1; } else { nb_re_dmrs = 4*rel15->numDmrsCdmGrpsNoData; - n_dmrs = ((rel15->rbSize+rel15->rbStart)*4)<<1; } + n_dmrs = (rel15->rbSize+rel15->rbStart)*nb_re_dmrs; uint16_t dmrs_symbol_map = rel15->dlDmrsSymbPos;//single DMRS: 010000100 Double DMRS 110001100 uint8_t dmrs_len = get_num_dmrs(rel15->dlDmrsSymbPos); uint16_t nb_re = ((12*rel15->NrOfSymbols)-nb_re_dmrs*dmrs_len-xOverhead)*rel15->rbSize*rel15->nrOfLayers; uint8_t Qm = rel15->qamModOrder[0]; uint32_t encoded_length = nb_re*Qm; - int16_t mod_dmrs[14][n_dmrs] __attribute__ ((aligned(16))); + int16_t mod_dmrs[14][n_dmrs<<1] __attribute__ ((aligned(16))); /* PTRS */ uint16_t beta_ptrs = 1; @@ -271,10 +270,10 @@ uint8_t nr_generate_pdsch(PHY_VARS_gNB *gNB, /// DMRS QPSK modulation for (int l=rel15->StartSymbolIndex; lStartSymbolIndex+rel15->NrOfSymbols; l++) { if (rel15->dlDmrsSymbPos & (1 << l)) { - nr_modulation(pdsch_dmrs[l][0], n_dmrs, DMRS_MOD_ORDER, mod_dmrs[l]); // currently only codeword 0 is modulated. Qm = 2 as DMRS is QPSK modulated + nr_modulation(pdsch_dmrs[l][0], n_dmrs*2, DMRS_MOD_ORDER, mod_dmrs[l]); // currently only codeword 0 is modulated. Qm = 2 as DMRS is QPSK modulated #ifdef DEBUG_DLSCH - printf("DMRS modulation (symbol %d, %d symbols, type %d):\n", l, n_dmrs>>1, dmrs_Type); + printf("DMRS modulation (symbol %d, %d symbols, type %d):\n", l, n_dmrs, dmrs_Type); for (int i=0; i>4; i++) { for (int j=0; j<8; j++) { printf("%d %d\t", mod_dmrs[l][((i<<3)+j)<<1], mod_dmrs[l][(((i<<3)+j)<<1)+1]); diff --git a/openair1/PHY/NR_TRANSPORT/nr_prach.c b/openair1/PHY/NR_TRANSPORT/nr_prach.c index b5a3c061e9..64b14091d6 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_prach.c +++ b/openair1/PHY/NR_TRANSPORT/nr_prach.c @@ -301,205 +301,300 @@ void rx_nr_prach_ru(RU_t *ru, // do DFT if (mu==1) { - if (fp->N_RB_UL <= 100) - AssertFatal(1==0,"N_RB_UL %d not support for NR PRACH yet\n",fp->N_RB_UL); - else if (fp->N_RB_UL < 137) { - if (fp->threequarter_fs==0) { - //40 MHz @ 61.44 Ms/s - //50 MHz @ 61.44 Ms/s - prach2 = prach[aa] + (Ncp<<2); // Ncp is for 30.72 Ms/s, so multiply by 2 for I/Q, and 2 to bring to 61.44 Ms/s - if (prach_sequence_length == 0) { - if (prachFormat == 0 || prachFormat == 1 || prachFormat == 2) { - dftlen=49152; - dft(DFT_49152,prach2,rxsigF[aa],1); + switch(fp->samples_per_subframe) { + case 15360: + // 10, 15 MHz @ 15.36 Ms/s + prach2 = prach[aa] + (1*Ncp); // Ncp is for 30.72 Ms/s, so divide by 2 to bring to 15.36 Ms/s and multiply by 2 for I/Q + if (prach_sequence_length == 0) { + if (prachFormat == 0 || prachFormat == 1 || prachFormat == 2) { + dftlen=12288; + dft(DFT_12288,prach2,rxsigF[aa],1); + } + if (prachFormat == 1 || prachFormat == 2) { + dft(DFT_12288,prach2+24576,rxsigF[aa]+24576,1); + reps++; + } + if (prachFormat == 2) { + dft(DFT_12288,prach2+(24576*2),rxsigF[aa]+(24576*2),1); + dft(DFT_12288,prach2+(24576*3),rxsigF[aa]+(24576*3),1); + reps+=2; + } + if (prachFormat == 3) { + dftlen=3072; + for (int i=0;i<4;i++) dft(DFT_3072,prach2+(i*3072*2),rxsigF[aa]+(i*3072*2),1); + reps=4; + } + } else { // 839 sequence + if (prachStartSymbol == 0) prach2+=16; // 8 samples @ 15.36 Ms/s in first symbol of each half subframe (15/30 kHz only) + + dftlen=512; + dft(DFT_512,prach2,rxsigF[aa],1); + if (prachFormat != 9/*C0*/) { + dft(DFT_512,prach2+1024,rxsigF[aa]+1024,1); + reps++; + } + if (prachFormat == 5/*A2*/ || prachFormat == 6/*A3*/|| prachFormat == 8/*B4*/ || prachFormat == 10/*C2*/) { + dft(DFT_512,prach2+1024*2,rxsigF[aa]+1024*2,1); + dft(DFT_512,prach2+1024*3,rxsigF[aa]+1024*3,1); + reps+=2; + } + if (prachFormat == 6/*A3*/ || prachFormat == 8/*B4*/) { + dft(DFT_512,prach2+1024*4,rxsigF[aa]+1024*4,1); + dft(DFT_512,prach2+1024*5,rxsigF[aa]+1024*5,1); + reps+=2; + } + if (prachFormat == 8/*B4*/) { + for (int i=6;i<12;i++) dft(DFT_512,prach2+(1024*i),rxsigF[aa]+(1024*i),1); + reps+=6; + } } - if (prachFormat == 1 || prachFormat == 2) { - dft(DFT_49152,prach2+98304,rxsigF[aa]+98304,1); - reps++; - } - if (prachFormat == 2) { - dft(DFT_49152,prach2+(98304*2),rxsigF[aa]+(98304*2),1); - dft(DFT_49152,prach2+(98304*3),rxsigF[aa]+(98304*3),1); - reps+=2; - } - if (prachFormat == 3) { - dftlen=12288; - for (int i=0;i<4;i++) dft(DFT_12288,prach2+(i*12288*2),rxsigF[aa]+(i*12288*2),1); - reps=4; - } - }// 839 sequence - else { - if (prachStartSymbol == 0) - prach2+=64; // 32 samples @ 61.44 Ms/s in first symbol of each half subframe (15/30 kHz only) + break; - dftlen=2048; - dft(DFT_2048,prach2,rxsigF[aa],1); - if (prachFormat != 9/*C0*/) { - dft(DFT_2048,prach2+4096,rxsigF[aa]+4096,1); - reps++; - } - if (prachFormat == 5/*A2*/ || prachFormat == 6/*A3*/|| prachFormat == 8/*B4*/ || prachFormat == 10/*C2*/) { - dft(DFT_2048,prach2+4096*2,rxsigF[aa]+4096*2,1); - dft(DFT_2048,prach2+4096*3,rxsigF[aa]+4096*3,1); - reps+=2; - } - if (prachFormat == 6/*A3*/ || prachFormat == 8/*B4*/) { - dft(DFT_2048,prach2+4096*4,rxsigF[aa]+4096*4,1); - dft(DFT_2048,prach2+4096*5,rxsigF[aa]+4096*5,1); - reps+=2; - } - if (prachFormat == 8/*B4*/) { - for (int i=6;i<12;i++) dft(DFT_2048,prach2+(4096*i),rxsigF[aa]+(4096*i),1); - reps+=6; - } - } - } else { // threequarter sampling - // 40 MHz @ 46.08 Ms/s - prach2 = prach[aa] + (3*Ncp); // 46.08 is 1.5 * 30.72, times 2 for I/Q - if (prach_sequence_length == 0) { - AssertFatal(fp->N_RB_UL <= 107,"cannot do 108..136 PRBs with 3/4 sampling\n"); - if (prachFormat == 0 || prachFormat == 1 || prachFormat == 2) { - dftlen=36864; - dft(DFT_36864,prach2,rxsigF[aa],1); - reps++; - } - if (prachFormat == 1 || prachFormat == 2) { - dft(DFT_36864,prach2+73728,rxsigF[aa]+73728,1); - reps++; - } - if (prachFormat == 2) { - dft(DFT_36864,prach2+(73728*2),rxsigF[aa]+(73728*2),1); - dft(DFT_36864,prach2+(73728*3),rxsigF[aa]+(73728*3),1); - reps+=2; - } - if (prachFormat == 3) { - dftlen=9216; - for (int i=0;i<4;i++) dft(DFT_9216,prach2+(i*9216*2),rxsigF[aa]+(i*9216*2),1); - reps=4; - } - } else { - if (prachStartSymbol == 0) prach2+=48; // 24 samples @ 46.08 Ms/s in first symbol of each half subframe (15/30 kHz only) - dftlen=1536; - dft(DFT_1536,prach2,rxsigF[aa],1); - if (prachFormat != 9/*C0*/) { - dft(DFT_1536,prach2+3072,rxsigF[aa]+3072,1); - reps++; - } - - if (prachFormat == 5/*A2*/ || prachFormat == 6/*A3*/|| prachFormat == 8/*B4*/ || prachFormat == 10/*C2*/) { - dft(DFT_1536,prach2+3072*2,rxsigF[aa]+3072*2,1); - dft(DFT_1536,prach2+3072*3,rxsigF[aa]+3072*3,1); - reps+=2; - } - if (prachFormat == 6/*A3*/ || prachFormat == 8/*B4*/) { - dft(DFT_1536,prach2+3072*4,rxsigF[aa]+3072*4,1); - dft(DFT_1536,prach2+3072*5,rxsigF[aa]+3072*5,1); - reps+=2; - } - if (prachFormat == 8/*B4*/) { - for (int i=6;i<12;i++) dft(DFT_1536,prach2+(3072*i),rxsigF[aa]+(3072*i),1); - reps+=6; - } - } // short format - } // 3/4 sampling - } // <=50 MHz BW - else if (fp->N_RB_UL <= 273) { - if (fp->threequarter_fs==0) { - prach2 = prach[aa] + (Ncp<<3); - //80,90,100 MHz @ 122.88 Ms/s + case 30720: + // 20, 25, 30 MHz @ 30.72 Ms/s + prach2 = prach[aa] + (2*Ncp); // Ncp is for 30.72 Ms/s, so just multiply by 2 for I/Q + if (prach_sequence_length == 0) { + if (prachFormat == 0 || prachFormat == 1 || prachFormat == 2) { + dftlen=24576; + dft(DFT_24576,prach2,rxsigF[aa],1); + } + if (prachFormat == 1 || prachFormat == 2) { + dft(DFT_24576,prach2+49152,rxsigF[aa]+49152,1); + reps++; + } + if (prachFormat == 2) { + dft(DFT_24576,prach2+(49152*2),rxsigF[aa]+(49152*2),1); + dft(DFT_24576,prach2+(49152*3),rxsigF[aa]+(49152*3),1); + reps+=2; + } + if (prachFormat == 3) { + dftlen=6144; + for (int i=0;i<4;i++) dft(DFT_6144,prach2+(i*6144*2),rxsigF[aa]+(i*6144*2),1); + reps=4; + } + } else { // 839 sequence + if (prachStartSymbol == 0) prach2+=32; // 16 samples @ 30.72 Ms/s in first symbol of each half subframe (15/30 kHz only) - if (prach_sequence_length == 0) { - if (prachFormat == 0 || prachFormat == 1 || prachFormat == 2) { - dftlen=98304; - dft(DFT_98304,prach2,rxsigF[aa],1); + dftlen=1024; + dft(DFT_1024,prach2,rxsigF[aa],1); + if (prachFormat != 9/*C0*/) { + dft(DFT_1024,prach2+2048,rxsigF[aa]+2048,1); + reps++; + } + if (prachFormat == 5/*A2*/ || prachFormat == 6/*A3*/|| prachFormat == 8/*B4*/ || prachFormat == 10/*C2*/) { + dft(DFT_1024,prach2+2048*2,rxsigF[aa]+2048*2,1); + dft(DFT_1024,prach2+2048*3,rxsigF[aa]+2048*3,1); + reps+=2; + } + if (prachFormat == 6/*A3*/ || prachFormat == 8/*B4*/) { + dft(DFT_1024,prach2+2048*4,rxsigF[aa]+2048*4,1); + dft(DFT_1024,prach2+2048*5,rxsigF[aa]+2048*5,1); + reps+=2; + } + if (prachFormat == 8/*B4*/) { + for (int i=6;i<12;i++) dft(DFT_1024,prach2+(2048*i),rxsigF[aa]+(2048*i),1); + reps+=6; + } } - if (prachFormat == 1 || prachFormat == 2) { - dft(DFT_98304,prach2+196608,rxsigF[aa]+196608,1); - reps++; - } - if (prachFormat == 2) { - dft(DFT_98304,prach2+(196608*2),rxsigF[aa]+(196608*2),1); - dft(DFT_98304,prach2+(196608*3),rxsigF[aa]+(196608*3),1); - reps+=2; - } - if (prachFormat == 3) { - dftlen=24576; - for (int i=0;i<4;i++) dft(DFT_24576,prach2+(i*2*24576),rxsigF[aa]+(i*2*24576),1); - reps=4; - } - } - else { - if (prachStartSymbol == 0) prach2+=128; // 64 samples @ 122.88 Ms/s in first symbol of each half subframe (15/30 kHz only) + break; - dftlen=4096; - dft(DFT_4096,prach2,rxsigF[aa],1); - if (prachFormat != 9/*C0*/) { - dft(DFT_4096,prach2+8192,rxsigF[aa]+8192,1); - reps++; - } - - if (prachFormat == 5/*A2*/ || prachFormat == 6/*A3*/|| prachFormat == 8/*B4*/ || prachFormat == 10/*C2*/) { - dft(DFT_4096,prach2+8192*2,rxsigF[aa]+8192*2,1); - dft(DFT_4096,prach2+8192*3,rxsigF[aa]+8192*3,1); - reps+=2; - } - if (prachFormat == 6/*A3*/ || prachFormat == 8/*B4*/) { - dft(DFT_4096,prach2+8192*4,rxsigF[aa]+8192*4,1); - dft(DFT_4096,prach2+8192*5,rxsigF[aa]+8192*5,1); - reps+=2; - } - if (prachFormat == 8/*B4*/) { - for (int i=6;i<12;i++) dft(DFT_4096,prach2+(8192*i),rxsigF[aa]+(8192*i),1); - reps+=6; - } - } - } else { - AssertFatal(fp->N_RB_UL <= 217,"cannot do more than 217 PRBs with 3/4 sampling\n"); - prach2 = prach[aa] + (6*Ncp); - // 80 MHz @ 92.16 Ms/s - if (prach_sequence_length == 0) { - if (prachFormat == 0 || prachFormat == 1 || prachFormat == 2) { - dftlen=73728; - dft(DFT_73728,prach2,rxsigF[aa],1); - reps++; - } - if (prachFormat == 1 || prachFormat == 2) { - dft(DFT_73728,prach2+(2*73728),rxsigF[aa]+(2*73728),1); - reps++; - } - if (prachFormat == 3) { - dftlen=18432; - for (int i=0;i<4;i++) dft(DFT_18432,prach2+(i*2*18432),rxsigF[aa]+(i*2*18432),1); - reps=4; - } - } else { - if (prachStartSymbol == 0) prach2+=96; // 64 samples @ 122.88 Ms/s in first symbol of each half subframe (15/30 kHz only) + case 61440: + // 40, 50, 60 MHz @ 61.44 Ms/s + prach2 = prach[aa] + (4*Ncp); // Ncp is for 30.72 Ms/s, so multiply by 2 for I/Q, and 2 to bring to 61.44 Ms/s + if (prach_sequence_length == 0) { + if (prachFormat == 0 || prachFormat == 1 || prachFormat == 2) { + dftlen=49152; + dft(DFT_49152,prach2,rxsigF[aa],1); + } + if (prachFormat == 1 || prachFormat == 2) { + dft(DFT_49152,prach2+98304,rxsigF[aa]+98304,1); + reps++; + } + if (prachFormat == 2) { + dft(DFT_49152,prach2+(98304*2),rxsigF[aa]+(98304*2),1); + dft(DFT_49152,prach2+(98304*3),rxsigF[aa]+(98304*3),1); + reps+=2; + } + if (prachFormat == 3) { + dftlen=12288; + for (int i=0;i<4;i++) dft(DFT_12288,prach2+(i*12288*2),rxsigF[aa]+(i*12288*2),1); + reps=4; + } + } else { // 839 sequence + if (prachStartSymbol == 0) prach2+=64; // 32 samples @ 61.44 Ms/s in first symbol of each half subframe (15/30 kHz only) - dftlen=3072; - dft(DFT_3072,prach2,rxsigF[aa],1); - if (prachFormat != 9/*C0*/) { - dft(DFT_3072,prach2+6144,rxsigF[aa]+6144,1); - reps++; - } - - if (prachFormat == 5/*A2*/ || prachFormat == 6/*A3*/|| prachFormat == 8/*B4*/ || prachFormat == 10/*C2*/) { - dft(DFT_3072,prach2+6144*2,rxsigF[aa]+6144*2,1); - dft(DFT_3072,prach2+6144*3,rxsigF[aa]+6144*3,1); - reps+=2; - } - if (prachFormat == 6/*A3*/ || prachFormat == 8/*B4*/) { - dft(DFT_3072,prach2+6144*4,rxsigF[aa]+6144*4,1); - dft(DFT_3072,prach2+6144*5,rxsigF[aa]+6144*5,1); - reps+=2; - } - if (prachFormat == 8/*B4*/) { - for (int i=6;i<12;i++) dft(DFT_3072,prach2+(6144*i),rxsigF[aa]+(6144*i),1); - reps+=6; - } - } + dftlen=2048; + dft(DFT_2048,prach2,rxsigF[aa],1); + if (prachFormat != 9/*C0*/) { + dft(DFT_2048,prach2+4096,rxsigF[aa]+4096,1); + reps++; + } + if (prachFormat == 5/*A2*/ || prachFormat == 6/*A3*/|| prachFormat == 8/*B4*/ || prachFormat == 10/*C2*/) { + dft(DFT_2048,prach2+4096*2,rxsigF[aa]+4096*2,1); + dft(DFT_2048,prach2+4096*3,rxsigF[aa]+4096*3,1); + reps+=2; + } + if (prachFormat == 6/*A3*/ || prachFormat == 8/*B4*/) { + dft(DFT_2048,prach2+4096*4,rxsigF[aa]+4096*4,1); + dft(DFT_2048,prach2+4096*5,rxsigF[aa]+4096*5,1); + reps+=2; + } + if (prachFormat == 8/*B4*/) { + for (int i=6;i<12;i++) dft(DFT_2048,prach2+(4096*i),rxsigF[aa]+(4096*i),1); + reps+=6; + } + } + break; + + case 46080: + // 40 MHz @ 46.08 Ms/s + prach2 = prach[aa] + (3*Ncp); // 46.08 is 1.5 * 30.72, times 2 for I/Q + if (prach_sequence_length == 0) { + if (prachFormat == 0 || prachFormat == 1 || prachFormat == 2) { + dftlen=36864; + dft(DFT_36864,prach2,rxsigF[aa],1); + } + if (prachFormat == 1 || prachFormat == 2) { + dft(DFT_36864,prach2+73728,rxsigF[aa]+73728,1); + reps++; + } + if (prachFormat == 2) { + dft(DFT_36864,prach2+(73728*2),rxsigF[aa]+(73728*2),1); + dft(DFT_36864,prach2+(73728*3),rxsigF[aa]+(73728*3),1); + reps+=2; + } + if (prachFormat == 3) { + dftlen=9216; + for (int i=0;i<4;i++) dft(DFT_9216,prach2+(i*9216*2),rxsigF[aa]+(i*9216*2),1); + reps=4; + } + } else { // 839 sequence + if (prachStartSymbol == 0) prach2+=48; // 24 samples @ 46.08 Ms/s in first symbol of each half subframe (15/30 kHz only) + + dftlen=1536; + dft(DFT_1536,prach2,rxsigF[aa],1); + if (prachFormat != 9/*C0*/) { + dft(DFT_1536,prach2+3072,rxsigF[aa]+3072,1); + reps++; + } + if (prachFormat == 5/*A2*/ || prachFormat == 6/*A3*/|| prachFormat == 8/*B4*/ || prachFormat == 10/*C2*/) { + dft(DFT_1536,prach2+3072*2,rxsigF[aa]+3072*2,1); + dft(DFT_1536,prach2+3072*3,rxsigF[aa]+3072*3,1); + reps+=2; + } + if (prachFormat == 6/*A3*/ || prachFormat == 8/*B4*/) { + dft(DFT_1536,prach2+3072*4,rxsigF[aa]+3072*4,1); + dft(DFT_1536,prach2+3072*5,rxsigF[aa]+3072*5,1); + reps+=2; + } + if (prachFormat == 8/*B4*/) { + for (int i=6;i<12;i++) dft(DFT_1536,prach2+(3072*i),rxsigF[aa]+(3072*i),1); + reps+=6; + } + } + break; + + case 122880: + // 70, 80, 90, 100 MHz @ 122.88 Ms/s + prach2 = prach[aa] + (8*Ncp); + if (prach_sequence_length == 0) { + if (prachFormat == 0 || prachFormat == 1 || prachFormat == 2) { + dftlen=98304; + dft(DFT_98304,prach2,rxsigF[aa],1); + } + if (prachFormat == 1 || prachFormat == 2) { + dft(DFT_98304,prach2+196608,rxsigF[aa]+196608,1); + reps++; + } + if (prachFormat == 2) { + dft(DFT_98304,prach2+(196608*2),rxsigF[aa]+(196608*2),1); + dft(DFT_98304,prach2+(196608*3),rxsigF[aa]+(196608*3),1); + reps+=2; + } + if (prachFormat == 3) { + dftlen=24576; + for (int i=0;i<4;i++) dft(DFT_24576,prach2+(i*2*24576),rxsigF[aa]+(i*2*24576),1); + reps=4; + } + } else { // 839 sequence + if (prachStartSymbol == 0) prach2+=128; // 64 samples @ 122.88 Ms/s in first symbol of each half subframe (15/30 kHz only) + + dftlen=4096; + dft(DFT_4096,prach2,rxsigF[aa],1); + if (prachFormat != 9/*C0*/) { + dft(DFT_4096,prach2+8192,rxsigF[aa]+8192,1); + reps++; + } + + if (prachFormat == 5/*A2*/ || prachFormat == 6/*A3*/|| prachFormat == 8/*B4*/ || prachFormat == 10/*C2*/) { + dft(DFT_4096,prach2+8192*2,rxsigF[aa]+8192*2,1); + dft(DFT_4096,prach2+8192*3,rxsigF[aa]+8192*3,1); + reps+=2; + } + if (prachFormat == 6/*A3*/ || prachFormat == 8/*B4*/) { + dft(DFT_4096,prach2+8192*4,rxsigF[aa]+8192*4,1); + dft(DFT_4096,prach2+8192*5,rxsigF[aa]+8192*5,1); + reps+=2; + } + if (prachFormat == 8/*B4*/) { + for (int i=6;i<12;i++) dft(DFT_4096,prach2+(8192*i),rxsigF[aa]+(8192*i),1); + reps+=6; + } + } + break; + + case 92160: + // 80, 90 MHz @ 92.16 Ms/s + prach2 = prach[aa] + (6*Ncp); + if (prach_sequence_length == 0) { + if (prachFormat == 0 || prachFormat == 1 || prachFormat == 2) { + dftlen=73728; + dft(DFT_73728,prach2,rxsigF[aa],1); + } + if (prachFormat == 1 || prachFormat == 2) { + dft(DFT_73728,prach2+147456,rxsigF[aa]+147456,1); + reps++; + } + if (prachFormat == 2) { + dft(DFT_73728,prach2+(147456*2),rxsigF[aa]+(147456*2),1); + dft(DFT_73728,prach2+(147456*3),rxsigF[aa]+(147456*3),1); + reps+=2; + } + if (prachFormat == 3) { + dftlen=18432; + for (int i=0;i<4;i++) dft(DFT_18432,prach2+(i*2*18432),rxsigF[aa]+(i*2*18432),1); + reps=4; + } + } else { + if (prachStartSymbol == 0) prach2+=96; // 64 samples @ 122.88 Ms/s in first symbol of each half subframe (15/30 kHz only) + + dftlen=3072; + dft(DFT_3072,prach2,rxsigF[aa],1); + if (prachFormat != 9/*C0*/) { + dft(DFT_3072,prach2+6144,rxsigF[aa]+6144,1); + reps++; + } + + if (prachFormat == 5/*A2*/ || prachFormat == 6/*A3*/|| prachFormat == 8/*B4*/ || prachFormat == 10/*C2*/) { + dft(DFT_3072,prach2+6144*2,rxsigF[aa]+6144*2,1); + dft(DFT_3072,prach2+6144*3,rxsigF[aa]+6144*3,1); + reps+=2; + } + if (prachFormat == 6/*A3*/ || prachFormat == 8/*B4*/) { + dft(DFT_3072,prach2+6144*4,rxsigF[aa]+6144*4,1); + dft(DFT_3072,prach2+6144*5,rxsigF[aa]+6144*5,1); + reps+=2; + } + if (prachFormat == 8/*B4*/) { + for (int i=6;i<12;i++) dft(DFT_3072,prach2+(6144*i),rxsigF[aa]+(6144*i),1); + reps+=6; + } + } + break; + default: + AssertFatal(1==0,"sample_rate %f MHz not support for NR PRACH yet\n", fp->samples_per_subframe / 1000.0); } } - } else if (mu==3) { if (fp->threequarter_fs) { AssertFatal(1==0,"3/4 sampling not supported for numerology %d\n",mu); diff --git a/openair1/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c b/openair1/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c index 42d6cfad7a..dd8627f0e0 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c +++ b/openair1/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c @@ -345,6 +345,7 @@ void nr_ulsch_extract_rbs_single(int32_t **rxdataF, n = 0; k_prime = 0; + rxF_ext_index = ul_ch0_ext_index = ul_ch0_index = 0; /* In RX Antenna(aarx) loop, Reset the index */ if (is_dmrs_symbol == 0) { // diff --git a/openair1/PHY/NR_TRANSPORT/pucch_rx.c b/openair1/PHY/NR_TRANSPORT/pucch_rx.c index 3d2f27476a..239ae1d6d7 100644 --- a/openair1/PHY/NR_TRANSPORT/pucch_rx.c +++ b/openair1/PHY/NR_TRANSPORT/pucch_rx.c @@ -1611,7 +1611,7 @@ void nr_decode_pucch2(PHY_VARS_gNB *gNB, re_offset = (12*pucch_pdu->prb_start) + (12*pucch_pdu->bwp_start) + frame_parms->first_carrier_offset; // estimate CQI for MAC (from antenna port 0 only) int SNRtimes10 = dB_fixed_times10(signal_energy_nodc(&rxdataF[0][(l2*frame_parms->ofdm_symbol_size)+re_offset],12*pucch_pdu->prb_size)) - (10*gNB->measurements.n0_power_tot_dB); - int cqi; + int cqi,bit_left; if (SNRtimes10 < -640) cqi=0; else if (SNRtimes10 > 635) cqi=255; else cqi=(640+SNRtimes10)/5; @@ -1635,7 +1635,8 @@ void nr_decode_pucch2(PHY_VARS_gNB *gNB, uci_pdu->harq.harq_payload[i] = decodedPayload[0] & 255; decodedPayload[0]>>=8; } - uci_pdu->harq.harq_payload[i] = decodedPayload[0] & ((1<<(pucch_pdu->bit_len_harq&7))-1); + bit_left = pucch_pdu->bit_len_harq-((harq_bytes-1)<<3); + uci_pdu->harq.harq_payload[i] = decodedPayload[0] & ((1<>= pucch_pdu->bit_len_harq; } @@ -1649,6 +1650,7 @@ void nr_decode_pucch2(PHY_VARS_gNB *gNB, // csi if (pucch_pdu->bit_len_csi_part1>0) { uci_pdu->pduBitmap|=4; + uci_pdu->csi_part1.csi_part1_bit_len=pucch_pdu->bit_len_csi_part1; int csi_part1_bytes=pucch_pdu->bit_len_csi_part1>>3; if ((pucch_pdu->bit_len_csi_part1&7) > 0) csi_part1_bytes++; uci_pdu->csi_part1.csi_part1_payload = (uint8_t*)malloc(csi_part1_bytes); @@ -1658,7 +1660,8 @@ void nr_decode_pucch2(PHY_VARS_gNB *gNB, uci_pdu->csi_part1.csi_part1_payload[i] = decodedPayload[0] & 255; decodedPayload[0]>>=8; } - uci_pdu->csi_part1.csi_part1_payload[i] = decodedPayload[0] & ((1<<(pucch_pdu->bit_len_csi_part1&7))-1); + bit_left = pucch_pdu->bit_len_csi_part1-((csi_part1_bytes-1)<<3); + uci_pdu->csi_part1.csi_part1_payload[i] = decodedPayload[0] & ((1<>= pucch_pdu->bit_len_csi_part1; } diff --git a/openair1/PHY/NR_UE_TRANSPORT/dci_nr.c b/openair1/PHY/NR_UE_TRANSPORT/dci_nr.c index bfec64820b..8176514eb4 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/dci_nr.c +++ b/openair1/PHY/NR_UE_TRANSPORT/dci_nr.c @@ -158,7 +158,6 @@ void nr_pdcch_demapping_deinterleaving(uint32_t *llr, if ((reg % reg_bundle_size_L) == 0) r++; } - // Get cce_list indices by reg_idx in ascending order int f_bundle_j_list_id = 0; int f_bundle_j_list_ord[NR_MAX_PDCCH_AGG_LEVEL] = {}; @@ -175,7 +174,6 @@ void nr_pdcch_demapping_deinterleaving(uint32_t *llr, } } - for(int reg=0; reg<((coreset_nbr_rb*coreset_time_dur)); reg++) { f_reg = (f_bundle_j_list_ord[reg/6]*reg_bundle_size_L)+(reg%reg_bundle_size_L); @@ -404,11 +402,12 @@ void nr_pdcch_extract_rbs_single(int32_t **rxdataF, c_rb = 0; for (int rb=0;rb>3] & (1<<(7-(c_rb_by6&7)))) == 0) { - c_rb+=6; - c_rb_by6 = c_rb/6; - } + c_rb+=6; + c_rb_by6 = c_rb/6; + } LOG_DDD("c_rb=%d\n",c_rb); rxF=NULL; diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_llr_computation.c b/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_llr_computation.c index 68a206e7c7..853a3f61cf 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_llr_computation.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_llr_computation.c @@ -38,6 +38,31 @@ //#define DEBUG_LLR_SIC +void PrintIntrinsics(char *s, char *dtype, void *x) { + if (strcmp(dtype,"int") == 0) { + int *tempb = (int *)x; + printf("%s: [%d, %d, %d, %d]\n", s, tempb[0], tempb[1], tempb[2], tempb[3]); + } + if (strcmp(dtype,"short") == 0) { + short *tempb = (short *)x; + printf("%s: [%d, %d, %d, %d, %d, %d, %d, %d]\n", s, tempb[0], tempb[1], tempb[2], tempb[3], + tempb[4], tempb[5], tempb[6], tempb[7]); + } + if (strcmp(dtype,"char") == 0) { + char *tempb = (char *)x; + printf("%s: [%d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d]\n", s, + tempb[0], tempb[1], tempb[2], tempb[3], tempb[4], tempb[5], tempb[6], tempb[7], + tempb[8], tempb[9],tempb[10],tempb[11],tempb[12],tempb[13],tempb[14],tempb[15]); + } + if (strcmp(dtype,"float") == 0) { + float *tempb = (float *)x; + printf("%s: [%f, %f, %f, %f]\n", s, tempb[0], tempb[1], tempb[2], tempb[3]); + } + if (strcmp(dtype,"double") == 0) { + double *tempb = (double *)x; + printf("%s: [%f, %f]\n", s, tempb[0], tempb[1]); + } +} int16_t nr_zeros[8] __attribute__ ((aligned(16))) = {0,0,0,0,0,0,0,0}; int16_t nr_ones[8] __attribute__ ((aligned(16))) = {0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff}; @@ -734,20 +759,45 @@ void nr_dlsch_16qam_llr(NR_DL_FRAME_PARMS *frame_parms, for (i=0; isamples_per_frame+ue->ssb_offset, - 0); + is*fp->samples_per_frame+ue->ssb_offset); #ifdef DEBUG_INITIAL_SYNCH LOG_I(PHY,"Calling sss detection (normal CP)\n"); diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_prach.c b/openair1/PHY/NR_UE_TRANSPORT/nr_prach.c index 3ab88dac0a..0ba02c6bac 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_prach.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_prach.c @@ -244,86 +244,82 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, uint8_t slot){ *********************************************************/ if (mu==1) { - if (fp->N_RB_UL <= 100) - AssertFatal(1 == 0, "N_RB_UL %d not support for NR PRACH yet\n", fp->N_RB_UL); - else if (fp->N_RB_UL < 137) { - if (fp->threequarter_fs == 0) { - //40 MHz @ 61.44 Ms/s - //50 MHz @ 61.44 Ms/s + switch(fp->samples_per_subframe) { + case 15360: + // 10, 15 MHz @ 15.36 Ms/s if (prach_sequence_length == 0) { if (prach_fmt_id == 0 || prach_fmt_id == 1 || prach_fmt_id == 2) - dftlen = 49152; + dftlen = 12288; if (prach_fmt_id == 3) - dftlen = 12288; - } // 839 sequence - else { - switch (mu){ - case 1: - dftlen = 2048; - break; - default: - AssertFatal(1 == 0, "Shouldn't get here\n"); - break; - } + dftlen = 3072; + } else { // 839 sequence + dftlen = 512; } - } else { // threequarter sampling - // 40 MHz @ 46.08 Ms/s + break; + + case 30720: + // 20, 25, 30 MHz @ 30.72 Ms/s + if (prach_sequence_length == 0) { + if (prach_fmt_id == 0 || prach_fmt_id == 1 || prach_fmt_id == 2) + dftlen = 24576; + if (prach_fmt_id == 3) + dftlen = 6144; + } else { // 839 sequence + dftlen = 1024; + } + break; + + case 46080: + // 40 MHz @ 46.08 Ms/s if (prach_sequence_length == 0) { - AssertFatal(fp->N_RB_UL <= 107, "cannot do 108..136 PRBs with 3/4 sampling\n"); if (prach_fmt_id == 0 || prach_fmt_id == 1 || prach_fmt_id == 2) dftlen = 36864; if (prach_fmt_id == 3) dftlen = 9216; - } else { - switch (mu){ - case 1: - dftlen = 1536; - break; - default: - AssertFatal(1 == 0, "Shouldn't get here\n"); - break; - } - } // short format - } // 3/4 sampling - } // <=50 MHz BW - else if (fp->N_RB_UL <= 273) { - if (fp->threequarter_fs == 0) { - //80,90,100 MHz @ 122.88 Ms/s + } else { // 839 sequence + dftlen = 1536; + } + break; + + case 61440: + // 40, 50, 60 MHz @ 61.44 Ms/s + if (prach_sequence_length == 0) { + if (prach_fmt_id == 0 || prach_fmt_id == 1 || prach_fmt_id == 2) + dftlen = 49152; + if (prach_fmt_id == 3) + dftlen = 12288; + } else { // 839 sequence + dftlen = 2048; + } + break; + + case 92160: + // 50, 60, 70, 80, 90 MHz @ 92.16 Ms/s + if (prach_sequence_length == 0) { + if (prach_fmt_id == 0 || prach_fmt_id == 1 || prach_fmt_id == 2) + dftlen = 73728; + if (prach_fmt_id == 3) + dftlen = 18432; + } else { // 839 sequence + dftlen = 3072; + } + break; + + case 122880: + // 70, 80, 90, 100 MHz @ 122.88 Ms/s if (prach_sequence_length == 0) { if (prach_fmt_id == 0 || prach_fmt_id == 1 || prach_fmt_id == 2) dftlen = 98304; if (prach_fmt_id == 3) dftlen = 24576; + } else { // 839 sequence + dftlen = 4096; } - } else { // threequarter sampling - switch (mu){ - case 1: - dftlen = 4096; - break; - default: - AssertFatal(1 == 0, "Shouldn't get here\n"); - break; - } + break; + + default: + AssertFatal(1==0,"sample rate %f MHz not supported for numerology %d\n", fp->samples_per_subframe / 1000.0, mu); } - } else { - AssertFatal(fp->N_RB_UL <= 217, "cannot do more than 217 PRBs with 3/4 sampling\n"); - // 80 MHz @ 92.16 Ms/s - if (prach_sequence_length == 0) { - if (prach_fmt_id == 0 || prach_fmt_id == 1 || prach_fmt_id == 2) - dftlen = 73728; - if (prach_fmt_id == 3) - dftlen = 18432; - } else { - switch (mu){ - case 1: - dftlen = 3072; - break; - default: - AssertFatal(1 == 0, "Shouldn't get here\n"); - break; - } - } - } } else if (mu==3) { if (fp->threequarter_fs) @@ -425,15 +421,16 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, uint8_t slot){ uint8_t use_extended_prach_prefix = 0; if(fp->numerology_index == 0) { if (prachStartSymbol == 0 || prachStartSymbol == 7) - use_extended_prach_prefix = 1; + use_extended_prach_prefix = 1; } else { if (slot%(fp->slots_per_subframe/2)==0 && prachStartSymbol == 0) - use_extended_prach_prefix = 1; + use_extended_prach_prefix = 1; } - - if (fp->N_RB_UL <= 34) { //32 PRB case 61.44Msps - if (fp->threequarter_fs == 0) { + + if (mu == 3) { + switch (fp->samples_per_subframe) { + case 61440: // 32 PRB case, 61.44 Msps Ncp<<=1; //to account for 61.44Mbps // This is after cyclic prefix prach2 = prach+(Ncp<<1); //times 2 for complex samples @@ -491,13 +488,9 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, uint8_t slot){ prach_len = (512*12)+Ncp; } } - } - else - AssertFatal(1==0,"3/4 sampling not supported for this PRACH size %d\n",fp->N_RB_UL); - - } - else if (fp->N_RB_UL <= 68) {//66 PRB case, 122.88 Msps - if (fp->threequarter_fs == 0) { + break; + + case 122880: // 66 PRB case, 122.88 Msps Ncp<<=2; //to account for 122.88Mbps // This is after cyclic prefix prach2 = prach+(Ncp<<1); //times 2 for complex samples @@ -555,13 +548,211 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, uint8_t slot){ prach_len = (1024*12)+Ncp; } } + break; + + default: + AssertFatal(1==0,"sample rate %f MHz not supported for numerology %d\n", fp->samples_per_subframe / 1000.0, mu); } - else - AssertFatal(1==0,"3/4 sampling not supported for this PRACH size %d\n",fp->N_RB_UL); - } - else if (fp->N_RB_UL < 137) { // 46.08 or 61.44 Ms/s - if (fp->threequarter_fs == 0) { // full sampling @ 61.44 Ms/s - Ncp<<=1; //to account for 61.44Mbps + } else if (mu == 1) { + switch (fp->samples_per_subframe) { + case 15360: // full sampling @ 15.36 Ms/s + Ncp = Ncp/2; // to account for 15.36 Ms/s + // This is after cyclic prefix + prach2 = prach+(2*Ncp); // times 2 for complex samples + if (prach_sequence_length == 0){ + if (prach_fmt_id == 0) { // 24576 samples @ 30.72 Ms/s, 12288 samples @ 15.36 Ms/s + idft(IDFT_12288,prachF,prach2,1); + // here we have | empty | Prach12288 | + memmove(prach,prach+(12288<<1),(Ncp<<2)); + // here we have | Prefix | Prach12288 | + prach_len = 12288+Ncp; + } else if (prach_fmt_id == 1) { // 24576 samples @ 30.72 Ms/s, 12288 samples @ 15.36 Ms/s + idft(IDFT_12288,prachF,prach2,1); + // here we have | empty | Prach12288 | empty12288 | + memmove(prach2+(12288<<1),prach2,(12288<<2)); + // here we have | empty | Prach12288 | Prach12288 | + memmove(prach,prach+(12288<<2),(Ncp<<2)); + // here we have | Prefix | Prach12288 | Prach12288 | + prach_len = (12288*2)+Ncp; + } else if (prach_fmt_id == 2) { // 24576 samples @ 30.72 Ms/s, 12288 samples @ 15.36 Ms/s + idft(IDFT_12288,prachF,prach2,1); + // here we have | empty | Prach12288 | empty12288 | empty12288 | empty12288 | + memmove(prach2+(12288<<1),prach2,(12288<<2)); + // here we have | empty | Prach12288 | Prach12288 | empty12288 | empty12288 | + memmove(prach2+(12288<<2),prach2,(12288<<3)); + // here we have | empty | Prach12288 | Prach12288 | Prach12288 | Prach12288 | + memmove(prach,prach+(12288<<3),(Ncp<<2)); + // here we have | Prefix | Prach12288 | Prach12288 | Prach12288 | Prach12288 | + prach_len = (12288*4)+Ncp; + } else if (prach_fmt_id == 3) { // 6144 samples @ 30.72 Ms/s, 3072 samples @ 15.36 Ms/s + idft(IDFT_3072,prachF,prach2,1); + // here we have | empty | Prach3072 | empty3072 | empty3072 | empty3072 | + memmove(prach2+(3072<<1),prach2,(3072<<2)); + // here we have | empty | Prach3072 | Prach3072 | empty3072 | empty3072 | + memmove(prach2+(3072<<2),prach2,(3072<<3)); + // here we have | empty | Prach3072 | Prach3072 | Prach3072 | Prach3072 | + memmove(prach,prach+(3072<<3),(Ncp<<2)); + // here we have | Prefix | Prach3072 | Prach3072 | Prach3072 | Prach3072 | + prach_len = (3072*4)+Ncp; + } + } else { // short PRACH sequence + if (use_extended_prach_prefix) + Ncp += 8; // 16*kappa, kappa=0.5 for 15.36 Ms/s + prach2 = prach+(2*Ncp); // times 2 for complex samples + if (prach_fmt_id == 9) { + idft(IDFT_512,prachF,prach2,1); + // here we have | empty | Prach512 | + memmove(prach,prach+(512<<1),(Ncp<<2)); + // here we have | Prefix | Prach512 | + prach_len = (512*1)+Ncp; + } else if (prach_fmt_id == 4 || prach_fmt_id == 7) { + idft(IDFT_512,prachF,prach2,1); + // here we have | empty | Prach512 | empty512 | + memmove(prach2+(512<<1),prach2,(512<<2)); + // here we have | empty | Prach512 | Prach512 | + memmove(prach,prach+(512<<1),(Ncp<<2)); + // here we have | Prefix | Prach512 | Prach512 | + prach_len = (512*2)+Ncp; + } else if (prach_fmt_id == 5) { // 4x512 + idft(IDFT_512,prachF,prach2,1); + // here we have | empty | Prach512 | empty512 | empty512 | empty512 | + memmove(prach2+(512<<1),prach2,(512<<2)); + // here we have | empty | Prach512 | Prach512 | empty512 | empty512 | + memmove(prach2+(512<<2),prach2,(512<<3)); + // here we have | empty | Prach512 | Prach512 | Prach512 | Prach512 | + memmove(prach,prach+(512<<1),(Ncp<<2)); + // here we have | Prefix | Prach512 | Prach512 | Prach512 | Prach512 | + prach_len = (512*4)+Ncp; + } else if (prach_fmt_id == 6) { // 6x512 + idft(IDFT_512,prachF,prach2,1); + // here we have | empty | Prach512 | empty512 | empty512 | empty512 | empty512 | empty512 | + memmove(prach2+(512<<1),prach2,(512<<2)); + // here we have | empty | Prach512 | Prach512 | empty512 | empty512 | empty512 | empty512 | + memmove(prach2+(512<<2),prach2,(512<<3)); + // here we have | empty | Prach512 | Prach512 | Prach512 | Prach512 | empty512 | empty512 | + memmove(prach2+(512<<3),prach2,(512<<3)); + // here we have | empty | Prach512 | Prach512 | Prach512 | Prach512 | Prach512 | Prach512 | + memmove(prach,prach+(512<<1),(Ncp<<2)); + // here we have | Prefix | Prach512 | Prach512 | Prach512 | Prach512 | Prach512 | Prach512 | + prach_len = (512*6)+Ncp; + } else if (prach_fmt_id == 8) { // 12x512 + idft(IDFT_512,prachF,prach2,1); + // here we have | empty | Prach512 | empty512 | empty512 | empty512 | empty512 | empty512 | empty512 | empty512 | empty512 | empty512 | empty512 | empty512 | + memmove(prach2+(512<<1),prach2,(512<<2)); + // here we have | empty | Prach512 | Prach512 | empty512 | empty512 | empty512 | empty512 | empty512 | empty512 | empty512 | empty512 | empty512 | empty512 | + memmove(prach2+(512<<2),prach2,(512<<3)); + // here we have | empty | Prach512 | Prach512 | Prach512 | Prach512 | empty512 | empty512 | empty512 | empty512 | empty512 | empty512 | empty512 | empty512 | + memmove(prach2+(512<<3),prach2,(512<<3)); + // here we have | empty | Prach512 | Prach512 | Prach512 | Prach512 | Prach512 | Prach512 | empty512 | empty512 | empty512 | empty512 | empty512 | empty512 | + memmove(prach2+(512<<1)*6,prach2,(512<<2)*6); + // here we have | empty | Prach512 | Prach512 | Prach512 | Prach512 | Prach512 | Prach512 | Prach512 | Prach512 | Prach512 | Prach512 | Prach512 | Prach512 | + memmove(prach,prach+(512<<1),(Ncp<<2)); + // here we have | Prefix | Prach512 | Prach512 | Prach512 | Prach512 | Prach512 | Prach512 | Prach512 | Prach512 | Prach512 | Prach512 | Prach512 | Prach512 | + prach_len = (512*12)+Ncp; + } + } + break; + + case 30720: // full sampling @ 30.72 Ms/s + Ncp = Ncp*1; // to account for 30.72 Ms/s + // This is after cyclic prefix + prach2 = prach+(2*Ncp); // times 2 for complex samples + if (prach_sequence_length == 0){ + if (prach_fmt_id == 0) { // 24576 samples @ 30.72 Ms/s + idft(IDFT_24576,prachF,prach2,1); + // here we have | empty | Prach24576 | + memmove(prach,prach+(24576<<1),(Ncp<<2)); + // here we have | Prefix | Prach24576 | + prach_len = 24576+Ncp; + } else if (prach_fmt_id == 1) { // 24576 samples @ 30.72 Ms/s + idft(IDFT_24576,prachF,prach2,1); + // here we have | empty | Prach24576 | empty24576 | + memmove(prach2+(24576<<1),prach2,(24576<<2)); + // here we have | empty | Prach24576 | Prach24576 | + memmove(prach,prach+(24576<<2),(Ncp<<2)); + // here we have | Prefix | Prach24576 | Prach24576 | + prach_len = (24576*2)+Ncp; + } else if (prach_fmt_id == 2) { // 24576 samples @ 30.72 Ms/s + idft(IDFT_24576,prachF,prach2,1); + // here we have | empty | Prach24576 | empty24576 | empty24576 | empty24576 | + memmove(prach2+(24576<<1),prach2,(24576<<2)); + // here we have | empty | Prach24576 | Prach24576 | empty24576 | empty24576 | + memmove(prach2+(24576<<2),prach2,(24576<<3)); + // here we have | empty | Prach24576 | Prach24576 | Prach24576 | Prach24576 | + memmove(prach,prach+(24576<<3),(Ncp<<2)); + // here we have | Prefix | Prach24576 | Prach24576 | Prach24576 | Prach24576 | + prach_len = (24576*4)+Ncp; + } else if (prach_fmt_id == 3) { // 6144 samples @ 30.72 Ms/s + idft(IDFT_6144,prachF,prach2,1); + // here we have | empty | Prach6144 | empty6144 | empty6144 | empty6144 | + memmove(prach2+(6144<<1),prach2,(6144<<2)); + // here we have | empty | Prach6144 | Prach6144 | empty6144 | empty6144 | + memmove(prach2+(6144<<2),prach2,(6144<<3)); + // here we have | empty | Prach6144 | Prach6144 | Prach6144 | Prach6144 | + memmove(prach,prach+(6144<<3),(Ncp<<2)); + // here we have | Prefix | Prach6144 | Prach6144 | Prach6144 | Prach6144 | + prach_len = (6144*4)+Ncp; + } + } else { // short PRACH sequence + if (use_extended_prach_prefix) + Ncp += 16; // 16*kappa, kappa=1 for 30.72Msps + prach2 = prach+(2*Ncp); // times 2 for complex samples + if (prach_fmt_id == 9) { + idft(IDFT_1024,prachF,prach2,1); + // here we have | empty | Prach1024 | + memmove(prach,prach+(1024<<1),(Ncp<<2)); + // here we have | Prefix | Prach1024 | + prach_len = (1024*1)+Ncp; + } else if (prach_fmt_id == 4 || prach_fmt_id == 7) { + idft(IDFT_1024,prachF,prach2,1); + // here we have | empty | Prach1024 | empty1024 | + memmove(prach2+(1024<<1),prach2,(1024<<2)); + // here we have | empty | Prach1024 | Prach1024 | + memmove(prach,prach+(1024<<1),(Ncp<<2)); + // here we have | Prefix | Prach1024 | Prach1024 | + prach_len = (1024*2)+Ncp; + } else if (prach_fmt_id == 5) { // 4x1024 + idft(IDFT_1024,prachF,prach2,1); + // here we have | empty | Prach1024 | empty1024 | empty1024 | empty1024 | + memmove(prach2+(1024<<1),prach2,(1024<<2)); + // here we have | empty | Prach1024 | Prach1024 | empty1024 | empty1024 | + memmove(prach2+(1024<<2),prach2,(1024<<3)); + // here we have | empty | Prach1024 | Prach1024 | Prach1024 | Prach1024 | + memmove(prach,prach+(1024<<1),(Ncp<<2)); + // here we have | Prefix | Prach1024 | Prach1024 | Prach1024 | Prach1024 | + prach_len = (1024*4)+Ncp; + } else if (prach_fmt_id == 6) { // 6x1024 + idft(IDFT_1024,prachF,prach2,1); + // here we have | empty | Prach1024 | empty1024 | empty1024 | empty1024 | empty1024 | empty1024 | + memmove(prach2+(1024<<1),prach2,(1024<<2)); + // here we have | empty | Prach1024 | Prach1024 | empty1024 | empty1024 | empty1024 | empty1024 | + memmove(prach2+(1024<<2),prach2,(1024<<3)); + // here we have | empty | Prach1024 | Prach1024 | Prach1024 | Prach1024 | empty1024 | empty1024 | + memmove(prach2+(1024<<3),prach2,(1024<<3)); + // here we have | empty | Prach1024 | Prach1024 | Prach1024 | Prach1024 | Prach1024 | Prach1024 | + memmove(prach,prach+(1024<<1),(Ncp<<2)); + // here we have | Prefix | Prach1024 | Prach1024 | Prach1024 | Prach1024 | Prach1024 | Prach1024 | + prach_len = (1024*6)+Ncp; + } else if (prach_fmt_id == 8) { // 12x1024 + idft(IDFT_1024,prachF,prach2,1); + // here we have | empty | Prach1024 | empty1024 | empty1024 | empty1024 | empty1024 | empty1024 | empty1024 | empty1024 | empty1024 | empty1024 | empty1024 | empty1024 | + memmove(prach2+(1024<<1),prach2,(1024<<2)); + // here we have | empty | Prach1024 | Prach1024 | empty1024 | empty1024 | empty1024 | empty1024 | empty1024 | empty1024 | empty1024 | empty1024 | empty1024 | empty1024 | + memmove(prach2+(1024<<2),prach2,(1024<<3)); + // here we have | empty | Prach1024 | Prach1024 | Prach1024 | Prach1024 | empty1024 | empty1024 | empty1024 | empty1024 | empty1024 | empty1024 | empty1024 | empty1024 | + memmove(prach2+(1024<<3),prach2,(1024<<3)); + // here we have | empty | Prach1024 | Prach1024 | Prach1024 | Prach1024 | Prach1024 | Prach1024 | empty1024 | empty1024 | empty1024 | empty1024 | empty1024 | empty1024 | + memmove(prach2+(1024<<1)*6,prach2,(1024<<2)*6); + // here we have | empty | Prach1024 | Prach1024 | Prach1024 | Prach1024 | Prach1024 | Prach1024 | Prach1024 | Prach1024 | Prach1024 | Prach1024 | Prach1024 | Prach1024 | + memmove(prach,prach+(1024<<1),(Ncp<<2)); + // here we have | Prefix | Prach1024 | Prach1024 | Prach1024 | Prach1024 | Prach1024 | Prach1024 | Prach1024 | Prach1024 | Prach1024 | Prach1024 | Prach1024 | Prach1024 | + prach_len = (1024*12)+Ncp; + } + } + break; + + case 61440: // full sampling @ 61.44 Ms/s + Ncp = Ncp*2; // to account for 61.44 Ms/s // This is after cyclic prefix prach2 = prach+(Ncp<<1); //times 2 for complex samples if (prach_sequence_length == 0){ @@ -587,7 +778,7 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, uint8_t slot){ memmove(prach,prach+(49152<<3),(Ncp<<2)); // here we have |Prefix | Prach49152 | Prach49152| Prach49152 | Prach49152 prach_len = (49152*4)+Ncp; - } else if (prach_fmt_id == 3) { // //6144 samples @ 30.72 Ms/s, 12288 samples @ 61.44 Ms/s + } else if (prach_fmt_id == 3) { // 6144 samples @ 30.72 Ms/s, 12288 samples @ 61.44 Ms/s idft(IDFT_12288,prachF,prach2,1); memmove(prach2+(12288<<1),prach2,(12288<<2)); // here we have |empty | Prach12288 | Prach12288| empty12288 | empty12288 @@ -649,7 +840,9 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, uint8_t slot){ prach_len = (2048*12)+Ncp; } } - } else { // threequarter sampling @ 46.08 Ms/s + break; + + case 46080: // threequarter sampling @ 46.08 Ms/s Ncp = (Ncp*3)/2; prach2 = prach+(Ncp<<1); if (prach_sequence_length == 0){ @@ -738,9 +931,9 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, uint8_t slot){ prach_len = (1536*12)+Ncp; } } - } - } else if (fp->N_RB_UL <= 273) {// 92.16 or 122.88 Ms/s - if (fp->threequarter_fs == 0) { // full sampling @ 122.88 Ms/s + break; + + case 122880: // full sampling @ 122.88 Ms/s Ncp<<=2; //to account for 122.88Mbps // This is after cyclic prefix prach2 = prach+(Ncp<<1); //times 2 for complex samples @@ -828,7 +1021,9 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, uint8_t slot){ prach_len = (4096*12)+Ncp; } } - } else { // three quarter sampling @ 92.16 Ms/s + break; + + case 92160: // three quarter sampling @ 92.16 Ms/s Ncp = (Ncp*3); //to account for 92.16 Msps prach2 = prach+(Ncp<<1); //times 2 for complex samples if (prach_sequence_length == 0){ @@ -915,6 +1110,10 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, uint8_t slot){ prach_len = (3072*12)+Ncp; } } + break; + + default: + AssertFatal(1==0,"sample rate %f MHz not supported for numerology %d\n", fp->samples_per_subframe / 1000.0, mu); } } diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_transport_ue.h b/openair1/PHY/NR_UE_TRANSPORT/nr_transport_ue.h index 464bcfcfba..aa32ecc8c9 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_transport_ue.h +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_transport_ue.h @@ -105,6 +105,8 @@ typedef struct { uint8_t O_ACK; /// Index of current HARQ round for this ULSCH uint8_t round; + /// Last Ndi for this harq process + uint8_t ndi; /// pointer to pdu from MAC interface (TS 36.212 V15.4.0, Sec 5.1 p. 8) unsigned char *a; /// Pointer to the payload + CRC diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_ue_rf_helpers.c b/openair1/PHY/NR_UE_TRANSPORT/nr_ue_rf_helpers.c index 7cf64b28bb..76fc5f298f 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_ue_rf_helpers.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_ue_rf_helpers.c @@ -78,13 +78,15 @@ void nr_rf_card_config(openair0_config_t *openair0_cfg, openair0_cfg->autocal[i] = 1; - LOG_I(PHY, "HW: Configuring channel %d (rf_chain %d): setting tx_gain %f, rx_gain %f, tx_freq %f Hz, rx_freq %f Hz\n", - i, - rf_chain, - openair0_cfg->tx_gain[i], - openair0_cfg->rx_gain[i], - openair0_cfg->tx_freq[i], - openair0_cfg->rx_freq[i]); + if (i < openair0_cfg->rx_num_channels) { + LOG_I(PHY, "HW: Configuring channel %d (rf_chain %d): setting tx_gain %f, rx_gain %f, tx_freq %f Hz, rx_freq %f Hz\n", + i, + rf_chain, + openair0_cfg->tx_gain[i], + openair0_cfg->rx_gain[i], + openair0_cfg->tx_freq[i], + openair0_cfg->rx_freq[i]); + } } } \ No newline at end of file diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_coding.c b/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_coding.c index f6a346aee9..abb14e834b 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_coding.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_coding.c @@ -202,7 +202,6 @@ NR_UE_ULSCH_t *new_nr_ue_ulsch(uint16_t N_RB_UL, for (i=0; iharq_processes[i]->round=0; } - return(ulsch); } } @@ -257,7 +256,6 @@ int nr_ulsch_encoding(NR_UE_ULSCH_t *ulsch, Ilbrm = 0; Tbslbrm = 950984; //max tbs Coderate = 0.0; - harq_process->round = nr_rv_round_map_ue[harq_process->pusch_pdu.pusch_data.rv_index]; /////////// ///////////////////////////////////////////////////////////////////////////////////////// @@ -267,8 +265,7 @@ int nr_ulsch_encoding(NR_UE_ULSCH_t *ulsch, LOG_D(PHY,"ulsch coding nb_rb %d, Nl = %d\n", nb_rb, harq_process->pusch_pdu.nrOfLayers); LOG_D(PHY,"ulsch coding A %d G %d mod_order %d\n", A,G, mod_order); - // if (harq_process->Ndi == 1) { // this is a new packet - if (harq_process->round == 0) { // this is a new packet + if (harq_process->ndi != harq_process->pusch_pdu.pusch_data.new_data_indicator) { // this is a new packet #ifdef DEBUG_ULSCH_CODING printf("encoding thinks this is a new packet \n"); #endif @@ -415,7 +412,7 @@ int nr_ulsch_encoding(NR_UE_ULSCH_t *ulsch, /////////// /////////////////////////////////////////////////////////////////////////////// - + harq_process->ndi = harq_process->pusch_pdu.pusch_data.new_data_indicator; } F = harq_process->F; Kr = harq_process->K; diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c b/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c index 208901f289..3d8c975a5c 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c @@ -496,13 +496,19 @@ uint8_t nr_ue_pusch_common_procedures(PHY_VARS_NR_UE *UE, int symb_offset = (slot%frame_parms->slots_per_subframe)*frame_parms->symbols_per_slot; for(ap = 0; ap < Nl; ap++) { for (int s=0;s (%d.%d)\n", - s,s+symb_offset,frame_parms->symbol_rotation[2*(s+symb_offset)],frame_parms->symbol_rotation[1+(2*(s+symb_offset))]); - rotate_cpx_vector((int16_t *)&txdataF[ap][frame_parms->ofdm_symbol_size*s], - &frame_parms->symbol_rotation[2*(s+symb_offset)], - (int16_t *)&txdataF[ap][frame_parms->ofdm_symbol_size*s], - frame_parms->ofdm_symbol_size, - 15); + + LOG_D(PHY,"In %s: rotating txdataF symbol %d (%d) => (%d.%d)\n", + __FUNCTION__, + s, + s + symb_offset, + frame_parms->symbol_rotation[1][2 * (s + symb_offset)], + frame_parms->symbol_rotation[1][1 + (2 * (s + symb_offset))]); + + rotate_cpx_vector((int16_t *)&txdataF[ap][frame_parms->ofdm_symbol_size * s], + &frame_parms->symbol_rotation[1][2 * (s + symb_offset)], + (int16_t *)&txdataF[ap][frame_parms->ofdm_symbol_size * s], + frame_parms->ofdm_symbol_size, + 15); } } diff --git a/openair1/PHY/TOOLS/nr_phy_scope.c b/openair1/PHY/TOOLS/nr_phy_scope.c index cb61523852..b45c1abf0b 100644 --- a/openair1/PHY/TOOLS/nr_phy_scope.c +++ b/openair1/PHY/TOOLS/nr_phy_scope.c @@ -282,30 +282,6 @@ static void genericWaterFall (OAIgraph_t *graph, scopeSample_t *values, const in graph->iteration++; } -static void genericLogPowerPerAntena(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); - - for (int ant=0; antmodule_id; @@ -250,7 +251,7 @@ void nr_schedule_response(NR_Sched_Rsp_t *Sched_INFO){ { Sched_INFO->DL_req->SFN = frame; Sched_INFO->DL_req->Slot = slot; - printf("DL tti Frame = %d, slot = %d. \n",frame,slot); + //printf("DL tti Frame = %d, slot = %d. \n",frame,slot); oai_nfapi_dl_tti_req(Sched_INFO->DL_req); } if (Sched_INFO->TX_req->Number_of_PDUs > 0) diff --git a/openair1/SCHED_NR/nr_ru_procedures.c b/openair1/SCHED_NR/nr_ru_procedures.c index a78b1f4805..9a71f96815 100644 --- a/openair1/SCHED_NR/nr_ru_procedures.c +++ b/openair1/SCHED_NR/nr_ru_procedures.c @@ -520,8 +520,7 @@ void nr_fep0(RU_t *ru, int first_half) { ru->common.rxdataF[aa], l, proc->tti_rx, - ru->N_TA_offset, - 0); + ru->N_TA_offset); } } VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_RU_FEPRX+proc->tti_rx, 0); @@ -657,8 +656,7 @@ void nr_fep_full(RU_t *ru, int slot) { ru->common.rxdataF[aa], l, proc->tti_rx, - ru->N_TA_offset, - 0); + ru->N_TA_offset); } } diff --git a/openair1/SCHED_NR/phy_procedures_nr_gNB.c b/openair1/SCHED_NR/phy_procedures_nr_gNB.c index 7e7aff0a09..2617c4686e 100644 --- a/openair1/SCHED_NR/phy_procedures_nr_gNB.c +++ b/openair1/SCHED_NR/phy_procedures_nr_gNB.c @@ -367,7 +367,6 @@ void nr_fill_indication(PHY_VARS_gNB *gNB, int frame, int slot_rx, int ULSCH_id, int timing_advance_update, cqi; int sync_pos; - uint16_t mu = gNB->frame_parms.numerology_index; NR_gNB_ULSCH_t *ulsch = gNB->ulsch[ULSCH_id][0]; NR_UL_gNB_HARQ_t *harq_process = ulsch->harq_processes[harq_pid]; @@ -375,18 +374,10 @@ void nr_fill_indication(PHY_VARS_gNB *gNB, int frame, int slot_rx, int ULSCH_id, // pdu->data = gNB->ulsch[ULSCH_id+1][0]->harq_processes[harq_pid]->b; sync_pos = nr_est_timing_advance_pusch(gNB, ULSCH_id); // estimate timing advance for MAC - timing_advance_update = sync_pos * (1 << mu); // scale by the used scs numerology // scale the 16 factor in N_TA calculation in 38.213 section 4.2 according to the used FFT size - switch (gNB->frame_parms.N_RB_DL) { - case 106: timing_advance_update /= 16; break; - case 217: timing_advance_update /= 32; break; - case 245: timing_advance_update /= 32; break; - case 273: timing_advance_update /= 32; break; - case 66: timing_advance_update /= 12; break; - case 32: timing_advance_update /= 12; break; - default: AssertFatal(0==1,"No case defined for PRB %d to calculate timing_advance_update\n",gNB->frame_parms.N_RB_DL); - } + uint16_t bw_scaling = 16 * gNB->frame_parms.ofdm_symbol_size / 2048; + timing_advance_update = sync_pos / bw_scaling; // put timing advance command in 0..63 range timing_advance_update += 31; @@ -517,15 +508,12 @@ void phy_procedures_gNB_common_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx) unsigned char aa; for(symbol = 0; symbol < (gNB->frame_parms.Ncp==EXTENDED?12:14); symbol++) { - // nr_slot_fep_ul(gNB, symbol, proc->slot_rx, 0, 0); - for (aa = 0; aa < gNB->frame_parms.nb_antennas_rx; aa++) { nr_slot_fep_ul(&gNB->frame_parms, gNB->common_vars.rxdata[aa], gNB->common_vars.rxdataF[aa], symbol, slot_rx, - 0, 0); } } @@ -542,6 +530,9 @@ void phy_procedures_gNB_common_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx) } void phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx) { + /* those variables to log T_GNB_PHY_PUCCH_PUSCH_IQ only when we try to decode */ + int pucch_decode_done = 0; + int pusch_decode_done = 0; VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_gNB_UESPEC_RX,1); LOG_D(PHY,"phy_procedures_gNB_uespec_RX frame %d, slot %d\n",frame_rx,slot_rx); @@ -566,6 +557,8 @@ void phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx) (pucch->frame == frame_rx) && (pucch->slot == slot_rx) ) { + pucch_decode_done = 1; + nfapi_nr_pucch_pdu_t *pucch_pdu = &pucch->pucch_pdu; uint16_t num_ucis; switch (pucch_pdu->format_type) { @@ -657,7 +650,7 @@ void phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx) } #endif -T(T_BENETEL, T_INT(frame_rx), T_INT(slot_rx), T_BUFFER(&gNB->common_vars.rxdataF[0][0], 2048*4*14)); + pusch_decode_done = 1; uint8_t symbol_start = ulsch_harq->ulsch_pdu.start_symbol_index; uint8_t symbol_end = symbol_start + ulsch_harq->ulsch_pdu.nr_of_symbols; @@ -686,5 +679,9 @@ T(T_BENETEL, T_INT(frame_rx), T_INT(slot_rx), T_BUFFER(&gNB->common_vars.rxdataF // figure out a better way to choose slot_rx, 19 is ok for a particular TDD configuration with 30kHz SCS if ((frame_rx&127) == 0 && slot_rx==19) dump_pusch_stats(gNB); + if (pucch_decode_done || pusch_decode_done) { + T(T_GNB_PHY_PUCCH_PUSCH_IQ, T_INT(frame_rx), T_INT(slot_rx), T_BUFFER(&gNB->common_vars.rxdataF[0][0], gNB->frame_parms.symbols_per_slot * gNB->frame_parms.ofdm_symbol_size * 4)); + } + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_gNB_UESPEC_RX,0); } diff --git a/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c b/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c index f516ad8639..14c174c2c0 100644 --- a/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c +++ b/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c @@ -132,6 +132,7 @@ void nr_fill_rx_indication(fapi_nr_rx_indication_t *rx_ind, } switch (pdu_type){ + case FAPI_NR_RX_PDU_TYPE_SIB: case FAPI_NR_RX_PDU_TYPE_DLSCH: case FAPI_NR_RX_PDU_TYPE_RAR: harq_pid = dlsch0->current_harq_pid; @@ -202,20 +203,15 @@ uint8_t get_ra_PreambleIndex(uint8_t Mod_id, uint8_t CC_id, uint8_t gNB_id){ } - -// scale the 16 factor in N_TA calculation in 38.213 section 4.2 according to the used FFT size -uint16_t get_bw_scaling(uint16_t nb_rb){ - uint16_t bw_scaling; - switch (nb_rb) { - case 32: bw_scaling = 4; break; - case 66: bw_scaling = 8; break; - case 106: bw_scaling = 16; break; - case 217: bw_scaling = 32; break; - case 245: bw_scaling = 32; break; - case 273: bw_scaling = 32; break; - default: abort(); - } - return bw_scaling; +// convert time factor "16 * 64 * T_c / (2^mu)" in N_TA calculation in TS38.213 section 4.2 to samples by multiplying with samples per second +// 16 * 64 * T_c / (2^mu) * samples_per_second +// = 16 * T_s / (2^mu) * samples_per_second +// = 16 * 1 / (15 kHz * 2048) / (2^mu) * (15 kHz * 2^mu * ofdm_symbol_size) +// = 16 * 1 / 2048 * ofdm_symbol_size +// = 16 * ofdm_symbol_size / 2048 +static inline +uint16_t get_bw_scaling(uint16_t ofdm_symbol_size){ + return 16 * ofdm_symbol_size / 2048; } // UL time alignment procedures: @@ -233,38 +229,18 @@ void ue_ta_procedures(PHY_VARS_NR_UE *ue, int slot_tx, int frame_tx){ if (frame_tx == ul_time_alignment->ta_frame && slot_tx == ul_time_alignment->ta_slot) { - uint8_t numerology = ue->frame_parms.numerology_index; - uint16_t bwp_ul_NB_RB = ue->frame_parms.N_RB_UL; - int factor_mu = 1 << numerology; - uint16_t bw_scaling = get_bw_scaling(bwp_ul_NB_RB); + uint16_t ofdm_symbol_size = ue->frame_parms.ofdm_symbol_size; + uint16_t bw_scaling = get_bw_scaling(ofdm_symbol_size); - LOG_D(PHY, "In %s: applying timing advance -- frame %d -- slot %d -- UE_mode %d\n", __FUNCTION__, frame_tx, slot_tx, ue->UE_mode[gNB_id]); + ue->timing_advance += (ul_time_alignment->ta_command - 31) * bw_scaling; - if (ue->UE_mode[gNB_id] == RA_RESPONSE){ - - ue->timing_advance = ul_time_alignment->ta_command * bw_scaling / factor_mu; - - LOG_D(PHY, "In %s: [UE %d] [%d.%d] Received (RAR) timing advance command %d new value is %u \n", - __FUNCTION__, - ue->Mod_id, - frame_tx, - slot_tx, - ul_time_alignment->ta_command, - ue->timing_advance); - - } else if (ue->UE_mode[gNB_id] == PUSCH){ - - ue->timing_advance += (ul_time_alignment->ta_command - 31) * bw_scaling / factor_mu; - - LOG_D(PHY, "In %s: [UE %d] [%d.%d] Got timing advance command %u from MAC, new value is %d\n", - __FUNCTION__, - ue->Mod_id, - frame_tx, - slot_tx, - ul_time_alignment->ta_command, - ue->timing_advance); - - } + LOG_I(PHY, "In %s: [UE %d] [%d.%d] Got timing advance command %u from MAC, new value is %d\n", + __FUNCTION__, + ue->Mod_id, + frame_tx, + slot_tx, + ul_time_alignment->ta_command, + ue->timing_advance); ul_time_alignment->ta_frame = -1; ul_time_alignment->ta_slot = -1; @@ -927,33 +903,19 @@ void nr_ue_dlsch_procedures(PHY_VARS_NR_UE *ue, int nr_slot_rx = proc->nr_slot_rx; int ret=0, ret1=0; NR_UE_PDSCH *pdsch_vars; - uint8_t is_cw0_active = 0; - uint8_t is_cw1_active = 0; - uint8_t dmrs_type, nb_re_dmrs; uint16_t dmrs_len = get_num_dmrs(dlsch0->harq_processes[dlsch0->current_harq_pid]->dlDmrsSymbPos); - uint16_t nb_symb_sch = 9; nr_downlink_indication_t dl_indication; fapi_nr_rx_indication_t rx_ind; uint16_t number_pdus = 1; // params for UL time alignment procedure NR_UL_TIME_ALIGNMENT_t *ul_time_alignment = &ue->ul_time_alignment[eNB_id]; - uint16_t slots_per_frame = ue->frame_parms.slots_per_frame; - uint16_t slots_per_subframe = ue->frame_parms.slots_per_subframe; - uint8_t numerology = ue->frame_parms.numerology_index, mapping_type_ul, mapping_type_dl; - int ul_tx_timing_adjustment, N_TA_max, factor_mu, N_t_1, N_t_2, N_1, N_2, d_1_1 = 0, d_2_1, d; - uint8_t d_2_2 = 0;// set to 0 because there is only 1 BWP - // TODO this should corresponds to the switching time as defined in - // TS 38.133 - uint16_t ofdm_symbol_size = ue->frame_parms.ofdm_symbol_size; - uint16_t nb_prefix_samples = ue->frame_parms.nb_prefix_samples; - uint32_t t_subframe = 1; // subframe duration of 1 msec - uint16_t start_symbol; - float tc_factor; - is_cw0_active = dlsch0->harq_processes[harq_pid]->status; - nb_symb_sch = dlsch0->harq_processes[harq_pid]->nb_symbols; - start_symbol = dlsch0->harq_processes[harq_pid]->start_symbol; - dmrs_type = dlsch0->harq_processes[harq_pid]->dmrsConfigType; + uint8_t is_cw0_active = dlsch0->harq_processes[harq_pid]->status; + uint16_t nb_symb_sch = dlsch0->harq_processes[harq_pid]->nb_symbols; + uint16_t start_symbol = dlsch0->harq_processes[harq_pid]->start_symbol; + uint8_t dmrs_type = dlsch0->harq_processes[harq_pid]->dmrsConfigType; + + uint8_t nb_re_dmrs; if (dmrs_type==NFAPI_NR_DMRS_TYPE1) { nb_re_dmrs = 6*dlsch0->harq_processes[harq_pid]->n_dmrs_cdm_groups; } @@ -961,6 +923,7 @@ void nr_ue_dlsch_procedures(PHY_VARS_NR_UE *ue, nb_re_dmrs = 4*dlsch0->harq_processes[harq_pid]->n_dmrs_cdm_groups; } + uint8_t is_cw1_active = 0; if(dlsch1) is_cw1_active = dlsch1->harq_processes[harq_pid]->status; @@ -1208,7 +1171,8 @@ void nr_ue_dlsch_procedures(PHY_VARS_NR_UE *ue, nr_fill_rx_indication(&rx_ind, FAPI_NR_RX_PDU_TYPE_DLSCH, eNB_id, ue, dlsch0, number_pdus); break; case SI_PDSCH: - rx_ind.rx_indication_body[0].pdu_type = FAPI_NR_RX_PDU_TYPE_SIB; + nr_fill_dl_indication(&dl_indication, NULL, &rx_ind, proc, ue, eNB_id); + nr_fill_rx_indication(&rx_ind, FAPI_NR_RX_PDU_TYPE_SIB, eNB_id, ue, dlsch0, number_pdus); break; default: break; @@ -1222,53 +1186,29 @@ void nr_ue_dlsch_procedures(PHY_VARS_NR_UE *ue, } } - // TODO CRC check for CW0 - - // Check CRC for CW 0 - /*if (ret == (1+dlsch0->max_turbo_iterations)) { - *dlsch_errors=*dlsch_errors+1; - if(dlsch0->rnti != 0xffff){ - LOG_D(PHY,"[UE %d][PDSCH %x/%d] AbsSubframe %d.%d : DLSCH CW0 in error (rv %d,round %d, mcs %d,TBS %d)\n", - ue->Mod_id,dlsch0->rnti, - harq_pid,frame_rx,nr_slot_rx, - dlsch0->harq_processes[harq_pid]->rvidx, - dlsch0->harq_processes[harq_pid]->round, - dlsch0->harq_processes[harq_pid]->mcs, - dlsch0->harq_processes[harq_pid]->TBS); - } - } else { - if(dlsch0->rnti != 0xffff){ - LOG_D(PHY,"[UE %d][PDSCH %x/%d] AbsSubframe %d.%d : Received DLSCH CW0 (rv %d,round %d, mcs %d,TBS %d)\n", - ue->Mod_id,dlsch0->rnti, - harq_pid,frame_rx,nr_slot_rx, - dlsch0->harq_processes[harq_pid]->rvidx, - dlsch0->harq_processes[harq_pid]->round, - dlsch0->harq_processes[harq_pid]->mcs, - dlsch0->harq_processes[harq_pid]->TBS); - } - if ( LOG_DEBUGFLAG(DEBUG_UE_PHYPROC)){ - int j; - LOG_D(PHY,"dlsch harq_pid %d (rx): \n",dlsch0->current_harq_pid); - - for (j=0; jharq_processes[dlsch0->current_harq_pid]->TBS>>3; j++) - LOG_T(PHY,"%x.",dlsch0->harq_processes[dlsch0->current_harq_pid]->b[j]); - LOG_T(PHY,"\n"); - }*/ - if (ue->mac_enabled == 1) { - uint16_t bw_scaling = get_bw_scaling(ue->frame_parms.N_RB_DL); - /* Time Alignment procedure // - UE processing capability 1 // - Setting the TA update to be applied after the reception of the TA command // - Timing adjustment computed according to TS 38.213 section 4.2 // - Durations of N1 and N2 symbols corresponding to PDSCH and PUSCH are // computed according to sections 5.3 and 6.4 of TS 38.214 */ - factor_mu = 1 << numerology; - N_TA_max = 3846 * bw_scaling / factor_mu; + const int numerology = ue->frame_parms.numerology_index; + const int ofdm_symbol_size = ue->frame_parms.ofdm_symbol_size; + const int nb_prefix_samples = ue->frame_parms.nb_prefix_samples; + const int samples_per_subframe = ue->frame_parms.samples_per_subframe; + const int slots_per_frame = ue->frame_parms.slots_per_frame; + const int slots_per_subframe = ue->frame_parms.slots_per_subframe; + + const double tc_factor = 1.0 / samples_per_subframe; + const uint16_t bw_scaling = get_bw_scaling(ofdm_symbol_size); + + const int Ta_max = 3846; // Max value of 12 bits TA Command + const double N_TA_max = Ta_max * bw_scaling * tc_factor; /* PDSCH decoding time N_1 for processing capability 1 */ + int N_1; if (ue->dmrs_DownlinkConfig.pdsch_dmrs_AdditionalPosition == pdsch_dmrs_pos0) N_1 = pdsch_N_1_capability_1[numerology][1]; else if (ue->dmrs_DownlinkConfig.pdsch_dmrs_AdditionalPosition == pdsch_dmrs_pos1 || ue->dmrs_DownlinkConfig.pdsch_dmrs_AdditionalPosition == 2) // TODO set to pdsch_dmrs_pos2 when available @@ -1277,12 +1217,12 @@ void nr_ue_dlsch_procedures(PHY_VARS_NR_UE *ue, N_1 = pdsch_N_1_capability_1[numerology][3]; /* PUSCH preapration time N_2 for processing capability 1 */ - N_2 = pusch_N_2_timing_capability_1[numerology][1]; - mapping_type_dl = ue->PDSCH_Config.pdsch_TimeDomainResourceAllocation[0]->mappingType; - mapping_type_ul = ue->pusch_config.pusch_TimeDomainResourceAllocation[0]->mappingType; + const int N_2 = pusch_N_2_timing_capability_1[numerology][1]; /* d_1_1 depending on the number of PDSCH symbols allocated */ - d = 0; // TODO number of overlapping symbols of the scheduling PDCCH and the scheduled PDSCH + const int d = 0; // TODO number of overlapping symbols of the scheduling PDCCH and the scheduled PDSCH + int d_1_1 = 0; + mappingType_t mapping_type_dl = ue->PDSCH_Config.pdsch_TimeDomainResourceAllocation[0]->mappingType; if (mapping_type_dl == typeA) if (nb_symb_sch + start_symbol < 7) d_1_1 = 7 - (nb_symb_sch + start_symbol); @@ -1297,22 +1237,26 @@ void nr_ue_dlsch_procedures(PHY_VARS_NR_UE *ue, } /* d_2_1 */ + int d_2_1; + mappingType_t mapping_type_ul = ue->pusch_config.pusch_TimeDomainResourceAllocation[0]->mappingType; if (mapping_type_ul == typeB && start_symbol != 0) d_2_1 = 0; else d_2_1 = 1; + /* d_2_2 */ + const double d_2_2 = 0.0; // set to 0 because there is only 1 BWP: TODO this should corresponds to the switching time as defined in TS 38.133 + /* N_t_1 time duration in msec of N_1 symbols corresponding to a PDSCH reception time // N_t_2 time duration in msec of N_2 symbols corresponding to a PUSCH preparation time */ - N_t_1 = (N_1 + d_1_1) * (ofdm_symbol_size + nb_prefix_samples) / factor_mu; - N_t_2 = (N_2 + d_2_1) * (ofdm_symbol_size + nb_prefix_samples) / factor_mu; + double N_t_1 = (N_1 + d_1_1) * (ofdm_symbol_size + nb_prefix_samples) * tc_factor; + double N_t_2 = (N_2 + d_2_1) * (ofdm_symbol_size + nb_prefix_samples) * tc_factor; if (N_t_2 < d_2_2) N_t_2 = d_2_2; /* Time alignment procedure */ - // N_t_1 + N_t_2 + N_TA_max is in unit of Ts, therefore must be converted to Tc // N_t_1 + N_t_2 + N_TA_max must be in msec - tc_factor = 64 * 0.509 * 10e-7; - ul_tx_timing_adjustment = 1 + ceil(slots_per_subframe*((N_t_1 + N_t_2 + N_TA_max)*tc_factor + 0.5)/t_subframe); + const double t_subframe = 1.0; // subframe duration of 1 msec + const int ul_tx_timing_adjustment = 1 + (int)ceil(slots_per_subframe*(N_t_1 + N_t_2 + N_TA_max + 0.5)/t_subframe); if (ul_time_alignment->apply_ta == 1){ ul_time_alignment->ta_slot = (nr_slot_rx + ul_tx_timing_adjustment) % slots_per_frame; @@ -1326,13 +1270,6 @@ void nr_ue_dlsch_procedures(PHY_VARS_NR_UE *ue, LOG_D(PHY,"Frame %d slot %d -- Starting UL time alignment procedures. TA update will be applied at frame %d slot %d\n", frame_rx, nr_slot_rx, ul_time_alignment->ta_frame, ul_time_alignment->ta_slot); } } - - /*ue->total_TBS[eNB_id] = ue->total_TBS[eNB_id] + dlsch0->harq_processes[dlsch0->current_harq_pid]->TBS; - ue->total_received_bits[eNB_id] = ue->total_TBS[eNB_id] + dlsch0->harq_processes[dlsch0->current_harq_pid]->TBS; - }*/ - - // TODO CRC check for CW1 - } } @@ -1736,9 +1673,7 @@ int phy_procedures_nrUE_RX(PHY_VARS_NR_UE *ue, nr_slot_fep(ue, proc, (ue->symbol_offset+i)%(fp->symbols_per_slot), - nr_slot_rx, - 0, - 0); + nr_slot_rx); #if UE_TIMING_TRACE start_meas(&ue->dlsch_channel_estimation_stats); @@ -1791,9 +1726,7 @@ int phy_procedures_nrUE_RX(PHY_VARS_NR_UE *ue, nr_slot_fep(ue, proc, l, - nr_slot_rx, - 0, - 0); + nr_slot_rx); dci_cnt = 0; for(int n_ss = 0; n_ssnb_search_space; n_ss++) { @@ -1852,9 +1785,7 @@ int phy_procedures_nrUE_RX(PHY_VARS_NR_UE *ue, nr_slot_fep(ue, proc, m, //to be updated from higher layer - nr_slot_rx, - 0, - 0); + nr_slot_rx); } } } else { diff --git a/openair1/SIMULATION/NR_PHY/dlsim.c b/openair1/SIMULATION/NR_PHY/dlsim.c index 6784535391..4c6a02b69f 100644 --- a/openair1/SIMULATION/NR_PHY/dlsim.c +++ b/openair1/SIMULATION/NR_PHY/dlsim.c @@ -79,8 +79,8 @@ int32_t uplink_frequency_offset[MAX_NUM_CCs][4]; double cpuf; -int sf_ahead=4 ; -int sl_ahead=0; +uint16_t sf_ahead=4 ; +uint16_t sl_ahead=0; //uint8_t nfapi_mode = 0; uint64_t downlink_frequency[MAX_NUM_CCs][4]; @@ -97,6 +97,21 @@ int8_t nr_mac_rrc_data_ind_ue(const module_id_t module_id, return 0; } +void nr_rrc_ue_generate_RRCSetupRequest(module_id_t module_id, const uint8_t gNB_index) +{ + return; +} + +int8_t nr_mac_rrc_data_req_ue(const module_id_t Mod_idP, + const int CC_id, + const uint8_t gNB_id, + const frame_t frameP, + const rb_id_t Srb_id, + uint8_t *buffer_pP) +{ + return 0; +} + void rrc_data_ind( const protocol_ctxt_t *const ctxt_pP, @@ -185,14 +200,11 @@ int oai_nfapi_tx_data_req(nfapi_nr_tx_data_request_t *tx_data_req){ return(0); int oai_nfapi_ul_dci_req(nfapi_nr_ul_dci_request_t *ul_dci_req){ return(0); } int oai_nfapi_ul_tti_req(nfapi_nr_ul_tti_request_t *ul_tti_req){ return(0); } -int8_t nr_rrc_ue_decode_NR_SIB1_Message(module_id_t module_id, uint8_t gNB_index, uint8_t *const bufferP, const uint8_t buffer_len) { - return 0; -} - // needed for some functions openair0_config_t openair0_cfg[MAX_CARDS]; void update_ptrs_config(NR_CellGroupConfig_t *secondaryCellGroup, uint16_t *rbSize, uint8_t *mcsIndex,int8_t *ptrs_arg); void update_dmrs_config(NR_CellGroupConfig_t *scg,PHY_VARS_NR_UE *ue, int8_t* dmrs_arg); +extern void fix_scd(NR_ServingCellConfig_t *scd);// forward declaration /* specific dlsim DL preprocessor: uses rbStart/rbSize/mcs from command line of dlsim, does not search for CCE/PUCCH occasion but simply sets to 0 */ @@ -248,7 +260,10 @@ 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 roundStats[50]; + double roundStats[500] = {0}; + double blerStats[500] = {0}; + double berStats[500] = {0}; + double snrStats[500] = {0}; float effRate; //float psnr; float eff_tp_check = 0.7; @@ -659,6 +674,7 @@ int main(int argc, char **argv) rrc.carrier.servingcellconfigcommon = calloc(1,sizeof(*rrc.carrier.servingcellconfigcommon)); NR_ServingCellConfigCommon_t *scc = rrc.carrier.servingcellconfigcommon; + NR_ServingCellConfig_t *scd = calloc(1,sizeof(NR_ServingCellConfig_t)); NR_CellGroupConfig_t *secondaryCellGroup=calloc(1,sizeof(*secondaryCellGroup)); prepare_scc(rrc.carrier.servingcellconfigcommon); uint64_t ssb_bitmap; @@ -666,13 +682,18 @@ int main(int argc, char **argv) fix_scc(scc,ssb_bitmap); - fill_default_secondaryCellGroup(scc, - secondaryCellGroup, - 0, - 1, - n_tx, - 0); + prepare_scd(scd); + fill_default_secondaryCellGroup(scc, + scd, + secondaryCellGroup, + 0, + 1, + n_tx, + 0); + + /* RRC parameter validation for secondaryCellGroup */ + fix_scd(scd); /* -U option modify DMRS */ if(modify_dmrs) { update_dmrs_config(secondaryCellGroup, NULL,dmrs_arg); @@ -1114,7 +1135,9 @@ int main(int argc, char **argv) if (UE_harq_process->harq_ack.ack==1) effRate += ((float)TBS)/round; } // noise trials + blerStats[snrRun] = (float) n_errors / (float) n_trials; roundStats[snrRun]/=((float)n_trials); + berStats[snrRun] = (double)errors_scrambling/available_bits/n_trials; effRate /= n_trials; printf("*****************************************\n"); printf("SNR %f, (false positive %f)\n", SNR, @@ -1122,7 +1145,7 @@ int main(int argc, char **argv) printf("*****************************************\n"); printf("\n"); dump_pdsch_stats(gNB); - printf("SNR %f : n_errors (negative CRC) = %d/%d, Avg round %.2f, Channel BER %e, Eff Rate %.4f bits/slot, Eff Throughput %.2f, TBS %u bits/slot\n", SNR, n_errors, n_trials,roundStats[snrRun],(double)errors_scrambling/available_bits/n_trials,effRate,effRate/TBS*100,TBS); + printf("SNR %f : n_errors (negative CRC) = %d/%d, Avg round %.2f, Channel BER %e, BLER %.2f, Eff Rate %.4f bits/slot, Eff Throughput %.2f, TBS %u bits/slot\n", SNR, n_errors, n_trials,roundStats[snrRun],berStats[snrRun],blerStats[snrRun],effRate,effRate/TBS*100,TBS); printf("\n"); if (print_perf==1) { @@ -1187,15 +1210,19 @@ int main(int argc, char **argv) break; } - //if ((float)n_errors/(float)n_trials <= target_error_rate) { if (effRate > (eff_tp_check*TBS)) { printf("PDSCH test OK\n"); break; } + snrStats[snrRun] = SNR; snrRun++; } // NSR + LOG_M("dlsimStats.m","SNR",snrStats,snrRun,1,7); + LOG_MM("dlsimStats.m","BLER",blerStats,snrRun,1,7); + LOG_MM("dlsimStats.m","BER",berStats,snrRun,1,7); + LOG_MM("dlsimStats.m","rounds",roundStats,snrRun,1,7); /*if (n_trials>1) { printf("HARQ stats:\nSNR\tRounds\n"); psnr = snr0; diff --git a/openair1/SIMULATION/NR_PHY/nr_unitary_defs.h b/openair1/SIMULATION/NR_PHY/nr_unitary_defs.h index 8004fbb6b5..b78b42db91 100644 --- a/openair1/SIMULATION/NR_PHY/nr_unitary_defs.h +++ b/openair1/SIMULATION/NR_PHY/nr_unitary_defs.h @@ -55,19 +55,6 @@ signed char quantize(double D, double x, unsigned char B) { return ((char) qxd); } - -int8_t -mac_rrc_data_req_ue( - const module_id_t Mod_idP, - const int CC_id, - const frame_t frameP, - const rb_id_t Srb_id, - const uint8_t Nb_tb, - uint8_t *const buffer_pP, - const mac_enb_index_t eNB_indexP, - const uint8_t mbsfn_sync_area - ) { return(0);} - int oai_nfapi_rach_ind(nfapi_rach_indication_t *rach_ind) {return(0);} //NR_IF_Module_t *NR_IF_Module_init(int Mod_id){return(NULL);} int oai_nfapi_ul_config_req(nfapi_ul_config_request_t *ul_config_req) { return(0); } @@ -235,6 +222,7 @@ void fill_scc(NR_ServingCellConfigCommon_t *scc,uint64_t *ssb_bitmap,int N_RB_DL void fix_scc(NR_ServingCellConfigCommon_t *scc,uint64_t ssbmap); void prepare_scc(NR_ServingCellConfigCommon_t *scc); +void prepare_scd(NR_ServingCellConfig_t *scd); ngap_gNB_config_t ngap_config; uint32_t ngap_generate_gNB_id(void) {return 0;} void configure_nfapi_pnf(char *vnf_ip_addr, int vnf_p5_port, char *pnf_ip_addr, int pnf_p7_port, int vnf_p7_port) { return;} diff --git a/openair1/SIMULATION/NR_PHY/pbchsim.c b/openair1/SIMULATION/NR_PHY/pbchsim.c index 2512988371..a3c2501197 100644 --- a/openair1/SIMULATION/NR_PHY/pbchsim.c +++ b/openair1/SIMULATION/NR_PHY/pbchsim.c @@ -101,8 +101,8 @@ void nr_phy_config_request_sim_pbchsim(PHY_VARS_gNB *gNB, //gNB_config->subframe_config.dl_cyclic_prefix_type.value = (fp->Ncp == NORMAL) ? NFAPI_CP_NORMAL : NFAPI_CP_EXTENDED; gNB->mac_enabled = 1; - fp->dl_CarrierFreq = 3500000000;//from_nrarfcn(gNB_config->nfapi_config.rf_bands.rf_band[0],gNB_config->nfapi_config.nrarfcn.value); - fp->ul_CarrierFreq = 3500000000;//fp->dl_CarrierFreq - (get_uldl_offset(gNB_config->nfapi_config.rf_bands.rf_band[0])*100000); + fp->dl_CarrierFreq = 3600000000;//from_nrarfcn(gNB_config->nfapi_config.rf_bands.rf_band[0],gNB_config->nfapi_config.nrarfcn.value); + fp->ul_CarrierFreq = 3600000000;//fp->dl_CarrierFreq - (get_uldl_offset(gNB_config->nfapi_config.rf_bands.rf_band[0])*100000); if (mu>2) fp->nr_band = 257; else fp->nr_band = 78; fp->threequarter_fs= 0; @@ -111,7 +111,7 @@ void nr_phy_config_request_sim_pbchsim(PHY_VARS_gNB *gNB, nr_init_frame_parms(gNB_config, fp); - init_symbol_rotation(fp,fp->dl_CarrierFreq); + init_symbol_rotation(fp); gNB->configured = 1; LOG_I(PHY,"gNB configured\n"); @@ -540,7 +540,7 @@ int main(int argc, char **argv) if (input_fd==NULL) { gNB->pbch_configured = 1; - gNB->ssb_pdu.ssb_pdu_rel15.bchPayload = 0; + gNB->ssb_pdu.ssb_pdu_rel15.bchPayload = 0x55dd33; for (int slot=0;slotslots_per_frame;slot++) { for (aa=0; aaframe_parms.nb_antennas_tx; aa++) @@ -692,9 +692,7 @@ int main(int argc, char **argv) nr_slot_fep(UE, &proc, i%frame_parms->symbols_per_slot, - ssb_slot, - 0, - 0); + ssb_slot); nr_pbch_channel_estimation(UE,&proc,0,ssb_slot,i%frame_parms->symbols_per_slot,i-(UE->symbol_offset+1),ssb_index%8,n_hf); @@ -718,9 +716,9 @@ int main(int argc, char **argv) payload_ret = (UE->pbch_vars[0]->xtra_byte == gNB_xtra_byte); for (i=0;i<3;i++){ - payload_ret += (UE->pbch_vars[0]->decoded_output[i] == (gNB->ssb_pdu.ssb_pdu_rel15.bchPayload>>(8*i))); + payload_ret += (UE->pbch_vars[0]->decoded_output[i] == ((gNB->ssb_pdu.ssb_pdu_rel15.bchPayload>>(8*i)) & 0xff)); } - //printf("xtra byte gNB: 0x%02x UE: 0x%02x\n",gNB_xtra_byte, UE->rx_ind.rx_indication_body->mib_pdu.additional_bits); + //printf("xtra byte gNB: 0x%02x UE: 0x%02x\n",gNB_xtra_byte, UE->pbch_vars[0]->xtra_byte); //printf("ret %d\n", payload_ret); if (payload_ret!=4) n_errors_payload++; diff --git a/openair1/SIMULATION/NR_PHY/prachsim.c b/openair1/SIMULATION/NR_PHY/prachsim.c index c90bcf1395..74ca8d9184 100644 --- a/openair1/SIMULATION/NR_PHY/prachsim.c +++ b/openair1/SIMULATION/NR_PHY/prachsim.c @@ -64,7 +64,7 @@ double cpuf; extern uint16_t prach_root_sequence_map0_3[838]; openair0_config_t openair0_cfg[MAX_CARDS]; //uint8_t nfapi_mode=0; -int sl_ahead = 0; +uint16_t sl_ahead = 0; //void dump_nr_prach_config(NR_DL_FRAME_PARMS *frame_parms,uint8_t subframe); @@ -132,13 +132,24 @@ nr_rrc_gNB_process_GTPV1U_CREATE_TUNNEL_RESP( int8_t nr_mac_rrc_data_ind_ue(const module_id_t module_id, const int CC_id, const uint8_t gNB_index, const int8_t channel, const uint8_t* pduP, const sdu_size_t pdu_len) {return 0;} -// Dummy function to avoid linking error at compilation of nr-prachsim -int is_x2ap_enabled(void) +void nr_rrc_ue_generate_RRCSetupRequest(module_id_t module_id, const uint8_t gNB_index) +{ + return; +} + +int8_t nr_mac_rrc_data_req_ue(const module_id_t Mod_idP, + const int CC_id, + const uint8_t gNB_id, + const frame_t frameP, + const rb_id_t Srb_id, + uint8_t *buffer_pP) { return 0; } -int8_t nr_rrc_ue_decode_NR_SIB1_Message(module_id_t module_id, uint8_t gNB_index, uint8_t *const bufferP, const uint8_t buffer_len) { +// Dummy function to avoid linking error at compilation of nr-prachsim +int is_x2ap_enabled(void) +{ return 0; } @@ -454,7 +465,10 @@ int main(int argc, char **argv){ nr_phy_config_request_sim(gNB, N_RB_UL, N_RB_UL, mu, Nid_cell, SSB_positions); - uint64_t absoluteFrequencyPointA = (mu==1 ? 640000 : 2070833); + uint64_t absoluteFrequencyPointA = to_nrarfcn(frame_parms->nr_band, + frame_parms->dl_CarrierFreq, + frame_parms->numerology_index, + frame_parms->N_RB_UL*(180e3)*(1 << frame_parms->numerology_index)); uint8_t subframe = slot/frame_parms->slots_per_subframe; diff --git a/openair1/SIMULATION/NR_PHY/ulsim.c b/openair1/SIMULATION/NR_PHY/ulsim.c index 443ee6e1c0..d8fef539ba 100644 --- a/openair1/SIMULATION/NR_PHY/ulsim.c +++ b/openair1/SIMULATION/NR_PHY/ulsim.c @@ -75,13 +75,14 @@ PHY_VARS_NR_UE *UE; RAN_CONTEXT_t RC; int32_t uplink_frequency_offset[MAX_NUM_CCs][4]; -int sf_ahead=4 ; +uint16_t sf_ahead=4 ; int slot_ahead=6 ; -int sl_ahead=0; +uint16_t sl_ahead=0; double cpuf; //uint8_t nfapi_mode = 0; uint64_t downlink_frequency[MAX_NUM_CCs][4]; +extern void fix_scd(NR_ServingCellConfig_t *scd);// forward declaration int8_t nr_mac_rrc_data_ind_ue(const module_id_t module_id, const int CC_id, const uint8_t gNB_index, const int8_t channel, const uint8_t* pduP, const sdu_size_t pdu_len) { return 0; } @@ -155,15 +156,27 @@ int is_x2ap_enabled(void) return 0; } -//nFAPI P7 dummy functions +void nr_rrc_ue_generate_RRCSetupRequest(module_id_t module_id, const uint8_t gNB_index) +{ + return; +} + +int8_t nr_mac_rrc_data_req_ue(const module_id_t Mod_idP, + const int CC_id, + const uint8_t gNB_id, + const frame_t frameP, + const rb_id_t Srb_id, + uint8_t *buffer_pP) +{ + return 0; +} + +//nFAPI P7 dummy functions int oai_nfapi_dl_tti_req(nfapi_nr_dl_tti_request_t *dl_config_req) { return(0); } int oai_nfapi_tx_data_req(nfapi_nr_tx_data_request_t *tx_data_req){ return(0); } int oai_nfapi_ul_dci_req(nfapi_nr_ul_dci_request_t *ul_dci_req){ return(0); } int oai_nfapi_ul_tti_req(nfapi_nr_ul_tti_request_t *ul_tti_req){ return(0); } -int8_t nr_rrc_ue_decode_NR_SIB1_Message(module_id_t module_id, uint8_t gNB_index, uint8_t *const bufferP, const uint8_t buffer_len) { - return 0; -} int nr_derive_key(int alg_type, uint8_t alg_id, const uint8_t key[32], uint8_t **out) @@ -607,8 +620,8 @@ int main(int argc, char **argv) frame_parms = &gNB->frame_parms; //to be initialized I suppose (maybe not necessary for PBCH) - frame_parms->nb_antennas_tx = n_tx; - frame_parms->nb_antennas_rx = n_rx; + //frame_parms->nb_antennas_tx = n_tx; + //frame_parms->nb_antennas_rx = n_rx; frame_parms->N_RB_DL = N_RB_DL; frame_parms->N_RB_UL = N_RB_UL; frame_parms->Ncp = extended_prefix_flag ? EXTENDED : NORMAL; @@ -626,6 +639,7 @@ int main(int argc, char **argv) rrc.carrier.servingcellconfigcommon = calloc(1,sizeof(*rrc.carrier.servingcellconfigcommon)); NR_ServingCellConfigCommon_t *scc = rrc.carrier.servingcellconfigcommon; + NR_ServingCellConfig_t *scd = calloc(1,sizeof(NR_ServingCellConfig_t)); NR_CellGroupConfig_t *secondaryCellGroup=calloc(1,sizeof(*secondaryCellGroup)); prepare_scc(rrc.carrier.servingcellconfigcommon); uint64_t ssb_bitmap; @@ -633,7 +647,10 @@ int main(int argc, char **argv) fix_scc(scc,ssb_bitmap); + prepare_scd(scd); + fill_default_secondaryCellGroup(scc, + scd, secondaryCellGroup, 0, 1, @@ -642,11 +659,14 @@ int main(int argc, char **argv) // xer_fprint(stdout, &asn_DEF_NR_CellGroupConfig, (const void*)secondaryCellGroup); + /* RRC parameter validation for secondaryCellGroup */ + fix_scd(scd); + AssertFatal((gNB->if_inst = NR_IF_Module_init(0))!=NULL,"Cannot register interface"); gNB->if_inst->NR_PHY_config_req = nr_phy_config_request; // common configuration - rrc_mac_config_req_gNB(0,0,1,pusch_tgt_snrx10,pucch_tgt_snrx10,scc,0,0,NULL); + rrc_mac_config_req_gNB(0,0,n_rx,pusch_tgt_snrx10,pucch_tgt_snrx10,scc,0,0,NULL); // UE dedicated configuration rrc_mac_config_req_gNB(0,0,1,pusch_tgt_snrx10,pucch_tgt_snrx10,NULL,1,secondaryCellGroup->spCellConfig->reconfigurationWithSync->newUE_Identity,secondaryCellGroup); phy_init_nr_gNB(gNB,0,0); @@ -1053,70 +1073,69 @@ int main(int argc, char **argv) } - nr_fill_ulsch(gNB,frame,slot,pusch_pdu); + //nr_fill_ulsch(gNB,frame,slot,pusch_pdu); // Not needed as its its already filled as apart of "nr_schedule_response(Sched_INFO);" for (int i=0;i<(TBS/8);i++) ulsch_ue[0]->harq_processes[harq_pid]->a[i]=i&0xff; if (input_fd == NULL) { - // set FAPI parameters for UE, put them in the scheduled response and call - nr_ue_scheduled_response(&scheduled_response); - - - /////////////////////////phy_procedures_nr_ue_TX/////////////////////// - /////////// - - phy_procedures_nrUE_TX(UE, &UE_proc, gNB_id); - - - if (n_trials==1) { - LOG_M("txsig0.m","txs0", UE->common_vars.txdata[0],frame_parms->samples_per_subframe*10,1,1); - LOG_M("txsig0F.m","txs0F", UE->common_vars.txdataF[0],frame_parms->ofdm_symbol_size*14,1,1); - } - /////////// - //////////////////////////////////////////////////// - tx_offset = frame_parms->get_samples_slot_timestamp(slot,frame_parms,0); - - txlev = signal_energy(&UE->common_vars.txdata[0][tx_offset + 5*frame_parms->ofdm_symbol_size + 4*frame_parms->nb_prefix_samples + frame_parms->nb_prefix_samples0], - frame_parms->ofdm_symbol_size + frame_parms->nb_prefix_samples); + // set FAPI parameters for UE, put them in the scheduled response and call + nr_ue_scheduled_response(&scheduled_response); + + + /////////////////////////phy_procedures_nr_ue_TX/////////////////////// + /////////// + + phy_procedures_nrUE_TX(UE, &UE_proc, gNB_id); + + + if (n_trials==1) { + LOG_M("txsig0.m","txs0", UE->common_vars.txdata[0],frame_parms->samples_per_subframe*10,1,1); + LOG_M("txsig0F.m","txs0F", UE->common_vars.txdataF[0],frame_parms->ofdm_symbol_size*14,1,1); + } + /////////// + //////////////////////////////////////////////////// + tx_offset = frame_parms->get_samples_slot_timestamp(slot,frame_parms,0); + + txlev = signal_energy(&UE->common_vars.txdata[0][tx_offset + 5*frame_parms->ofdm_symbol_size + 4*frame_parms->nb_prefix_samples + frame_parms->nb_prefix_samples0], + frame_parms->ofdm_symbol_size + frame_parms->nb_prefix_samples); } else n_trials = 1; if (input_fd == NULL ) { - sigma_dB = 10 * log10((double)txlev * ((double)frame_parms->ofdm_symbol_size/(12*nb_rb))) - SNR;; - sigma = pow(10,sigma_dB/10); + sigma_dB = 10 * log10((double)txlev * ((double)frame_parms->ofdm_symbol_size/(12*nb_rb))) - SNR;; + sigma = pow(10,sigma_dB/10); - if(n_trials==1) printf("sigma %f (%f dB), txlev %f (factor %f)\n",sigma,sigma_dB,10*log10((double)txlev),(double)(double)frame_parms->ofdm_symbol_size/(12*nb_rb)); + if(n_trials==1) printf("sigma %f (%f dB), txlev %f (factor %f)\n",sigma,sigma_dB,10*log10((double)txlev),(double)(double) + frame_parms->ofdm_symbol_size/(12*nb_rb)); - for (i=0; icommon_vars.txdata[aa][slot_offset]))[(i<<1)]); - s_im[aa][i] = ((double)(((short *)&UE->common_vars.txdata[aa][slot_offset]))[(i<<1)+1]); - } - } - + for (i=0; inb_antennas_rx; aa++) { + s_re[aa][i] = ((double)(((short *)&UE->common_vars.txdata[aa][slot_offset]))[(i<<1)]); + s_im[aa][i] = ((double)(((short *)&UE->common_vars.txdata[aa][slot_offset]))[(i<<1)+1]); + } + } - if (UE2gNB->max_Doppler == 0) { - multipath_channel(UE2gNB,s_re,s_im,r_re,r_im, - slot_length,0,(n_trials==1)?1:0); - } else { - multipath_tv_channel(UE2gNB,s_re,s_im,r_re,r_im, - 2*slot_length,0); - } - for (i=0; inb_antennas_rx; ap++) { - ((int16_t*) &gNB->common_vars.rxdata[ap][slot_offset])[(2*i) + (delay*2)] = (int16_t)((r_re[ap][i]) + (sqrt(sigma/2)*gaussdouble(0.0,1.0))); // convert to fixed point - ((int16_t*) &gNB->common_vars.rxdata[ap][slot_offset])[(2*i)+1 + (delay*2)] = (int16_t)((r_im[ap][i]) + (sqrt(sigma/2)*gaussdouble(0.0,1.0))); + + if (UE2gNB->max_Doppler == 0) { + multipath_channel(UE2gNB, s_re, s_im, r_re, r_im, slot_length, 0, (n_trials==1)?1:0); + } else { + multipath_tv_channel(UE2gNB, s_re, s_im, r_re, r_im, 2*slot_length, 0); + } + for (i=0; inb_antennas_rx; ap++) { + ((int16_t*) &gNB->common_vars.rxdata[ap][slot_offset])[(2*i) + (delay*2)] = (int16_t)((r_re[ap][i]) + (sqrt(sigma/2)*gaussdouble(0.0,1.0))); // convert to fixed point + ((int16_t*) &gNB->common_vars.rxdata[ap][slot_offset])[(2*i)+1 + (delay*2)] = (int16_t)((r_im[ap][i]) + (sqrt(sigma/2)*gaussdouble(0.0,1.0))); /* Add phase noise if enabled */ if (pdu_bit_map & PUSCH_PDU_BITMAP_PUSCH_PTRS) { phase_noise(ts, &((int16_t*)&gNB->common_vars.rxdata[ap][slot_offset])[(2*i)], &((int16_t*)&gNB->common_vars.rxdata[ap][slot_offset])[(2*i)+1]); } - } - } + } + } - } + } /*End input_fd */ if(pusch_pdu->pdu_bit_map & PUSCH_PDU_BITMAP_PUSCH_PTRS) { diff --git a/openair2/COMMON/rrc_messages_types.h b/openair2/COMMON/rrc_messages_types.h index 02f878ee2e..87f926b206 100644 --- a/openair2/COMMON/rrc_messages_types.h +++ b/openair2/COMMON/rrc_messages_types.h @@ -42,6 +42,7 @@ #include "LTE_SL-DiscResourcePool-r12.h" #include "NR_RACH-ConfigCommon.h" #include "NR_ServingCellConfigCommon.h" +#include "NR_ServingCellConfig.h" //-------------------------------------------------------------------------------------------// // Messages for RRC logging #if defined(DISABLE_ITTI_XER_PRINT) @@ -405,6 +406,7 @@ typedef struct NRRrcConfigurationReq_s { uint16_t mnc[PLMN_LIST_MAX_SIZE]; uint8_t mnc_digit_length[PLMN_LIST_MAX_SIZE]; NR_ServingCellConfigCommon_t *scc; + NR_ServingCellConfig_t *scd; int ssb_SubcarrierOffset; int pdsch_AntennaPorts; int pusch_TargetSNRx10; diff --git a/openair2/COMMON/s1ap_messages_types.h b/openair2/COMMON/s1ap_messages_types.h index bd0788d2d0..2151375686 100644 --- a/openair2/COMMON/s1ap_messages_types.h +++ b/openair2/COMMON/s1ap_messages_types.h @@ -398,6 +398,11 @@ typedef struct s1ap_register_enb_req_s { /* Number of SCTP streams used for a mme association */ uint16_t sctp_in_streams; uint16_t sctp_out_streams; + uint16_t s1_setuprsp_wait_timer; + uint16_t s1_setupreq_wait_timer; + uint16_t s1_setupreq_count; + uint16_t sctp_req_timer; + uint16_t sctp_req_count; } s1ap_register_enb_req_t; //-------------------------------------------------------------------------------------------// diff --git a/openair2/ENB_APP/enb_config.c b/openair2/ENB_APP/enb_config.c index 6c709ea63b..d05fe7ac26 100644 --- a/openair2/ENB_APP/enb_config.c +++ b/openair2/ENB_APP/enb_config.c @@ -2429,6 +2429,65 @@ int RCconfig_S1( "to\n" " tracking_area_code = 1; // no string!!\n" " plmn_list = ( { mcc = 208; mnc = 93; mnc_length = 2; } )\n"); + if(*ENBParamList.paramarray[k][ENB_S1SETUP_RSP_TIMER_IDX].uptr <= 0xffff) + { + S1AP_REGISTER_ENB_REQ(msg_p).s1_setuprsp_wait_timer = *ENBParamList.paramarray[k][ENB_S1SETUP_RSP_TIMER_IDX].uptr; + } + else + { + LOG_E(S1AP, + "s1setup_rsp_timer value in conf file is invalid (%d). Default value is set.\n", + *ENBParamList.paramarray[k][ENB_S1SETUP_RSP_TIMER_IDX].uptr); + S1AP_REGISTER_ENB_REQ(msg_p).s1_setuprsp_wait_timer = 5; + } + + if(*ENBParamList.paramarray[k][ENB_S1SETUP_REQ_TIMER_IDX].uptr <= 0xffff) + { + S1AP_REGISTER_ENB_REQ(msg_p).s1_setupreq_wait_timer = *ENBParamList.paramarray[k][ENB_S1SETUP_REQ_TIMER_IDX].uptr; + } + else + { + LOG_E(S1AP, + "s1setup_req_timer value in conf file is invalid (%d). Default value is set.\n", + *ENBParamList.paramarray[k][ENB_S1SETUP_REQ_TIMER_IDX].uptr); + S1AP_REGISTER_ENB_REQ(msg_p).s1_setupreq_wait_timer = 5; + } + + if(*ENBParamList.paramarray[k][ENB_S1SETUP_REQ_COUNT_IDX].uptr <= 0xffff) + { + S1AP_REGISTER_ENB_REQ(msg_p).s1_setupreq_count = *ENBParamList.paramarray[k][ENB_S1SETUP_REQ_COUNT_IDX].uptr; + } + else + { + LOG_E(S1AP, + "s1setup_req_count value in conf file is invalid (%d). Default value is set.\n", + *ENBParamList.paramarray[k][ENB_S1SETUP_REQ_COUNT_IDX].uptr); + S1AP_REGISTER_ENB_REQ(msg_p).s1_setupreq_count = 0xffff; + } + + if(*ENBParamList.paramarray[k][ENB_SCTP_REQ_TIMER_IDX].uptr <= 0xffff) + { + S1AP_REGISTER_ENB_REQ(msg_p).sctp_req_timer = *ENBParamList.paramarray[k][ENB_SCTP_REQ_TIMER_IDX].uptr; + } + else + { + LOG_E(S1AP, + "sctp_req_timer value in conf file is invalid (%d). Default value is set.\n", + *ENBParamList.paramarray[k][ENB_SCTP_REQ_TIMER_IDX].uptr); + S1AP_REGISTER_ENB_REQ(msg_p).sctp_req_timer = 180; + } + + if(*ENBParamList.paramarray[k][ENB_SCTP_REQ_COUNT_IDX].uptr <= 0xffff) + { + S1AP_REGISTER_ENB_REQ(msg_p).sctp_req_count = *ENBParamList.paramarray[k][ENB_SCTP_REQ_COUNT_IDX].uptr; + } + else + { + LOG_E(S1AP, + "sctp_req_count value in conf file is invalid (%d). Default value is set.\n", + *ENBParamList.paramarray[k][ENB_SCTP_REQ_COUNT_IDX].uptr); + S1AP_REGISTER_ENB_REQ(msg_p).sctp_req_count = 0xffff; + } config_getlist(&PLMNParamList, PLMNParams, sizeof(PLMNParams)/sizeof(paramdef_t), aprefix); if (PLMNParamList.numelt < 1 || PLMNParamList.numelt > 6) { diff --git a/openair2/ENB_APP/enb_paramdef.h b/openair2/ENB_APP/enb_paramdef.h index de7e0bbdad..f26863414c 100644 --- a/openair2/ENB_APP/enb_paramdef.h +++ b/openair2/ENB_APP/enb_paramdef.h @@ -214,6 +214,11 @@ typedef enum { #define ENB_CONFIG_STRING_X2 "enable_x2" #define ENB_CONFIG_STRING_ENB_M2 "enable_enb_m2" #define ENB_CONFIG_STRING_MCE_M2 "enable_mce_m2" +#define ENB_CONFIG_STRING_S1SETUP_RSP_TIMER "s1setup_rsp_timer" +#define ENB_CONFIG_STRING_S1SETUP_REQ_TIMER "s1setup_req_timer" +#define ENB_CONFIG_STRING_S1SETUP_REQ_COUNT "s1setup_req_count" +#define ENB_CONFIG_STRING_SCTP_REQ_TIMER "sctp_req_timer" +#define ENB_CONFIG_STRING_SCTP_REQ_COUNT "sctp_req_count" /*-----------------------------------------------------------------------------------------------------------------------------------------*/ /* cell configuration parameters */ /* optname helpstr paramflags XXXptr defXXXval type numelt */ @@ -239,6 +244,11 @@ typedef enum { {ENB_CONFIG_STRING_X2, NULL, 0, strptr:NULL, defstrval:NULL, TYPE_STRING, 0}, \ {ENB_CONFIG_STRING_ENB_M2, NULL, 0, strptr:NULL, defstrval:"no", TYPE_STRING, 0}, \ {ENB_CONFIG_STRING_MCE_M2, NULL, 0, strptr:NULL, defstrval:"no", TYPE_STRING, 0}, \ + {ENB_CONFIG_STRING_S1SETUP_RSP_TIMER, NULL, 0, uptr:NULL, defuintval:5, TYPE_UINT, 0}, \ + {ENB_CONFIG_STRING_S1SETUP_REQ_TIMER, NULL, 0, uptr:NULL, defuintval:5, TYPE_UINT, 0}, \ + {ENB_CONFIG_STRING_S1SETUP_REQ_COUNT, NULL, 0, uptr:NULL, defuintval:65535, TYPE_UINT, 0}, \ + {ENB_CONFIG_STRING_SCTP_REQ_TIMER, NULL, 0, uptr:NULL, defuintval:180, TYPE_UINT, 0}, \ + {ENB_CONFIG_STRING_SCTP_REQ_COUNT, NULL, 0, uptr:NULL, defuintval:65535, TYPE_UINT, 0}, \ } #define ENB_ENB_ID_IDX 0 @@ -261,6 +271,11 @@ typedef enum { #define ENB_ENABLE_X2 17 #define ENB_ENABLE_ENB_M2 18 #define ENB_ENABLE_MCE_M2 19 +#define ENB_S1SETUP_RSP_TIMER_IDX 20 +#define ENB_S1SETUP_REQ_TIMER_IDX 21 +#define ENB_S1SETUP_REQ_COUNT_IDX 22 +#define ENB_SCTP_REQ_TIMER_IDX 23 +#define ENB_SCTP_REQ_COUNT_IDX 24 #define TRACKING_AREA_CODE_OKRANGE {0x0001,0xFFFD} #define ENBPARAMS_CHECK { \ diff --git a/openair2/GNB_APP/RRC_nr_paramsvalues.h b/openair2/GNB_APP/RRC_nr_paramsvalues.h index 1f1d076e9d..d05908e8ed 100644 --- a/openair2/GNB_APP/RRC_nr_paramsvalues.h +++ b/openair2/GNB_APP/RRC_nr_paramsvalues.h @@ -211,6 +211,24 @@ #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_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" + /*--------------------------------------------------------------------------------------------------------------------*/ /* pdcch_ConfigSIB1 parameters */ /*--------------------------------------------------------------------------------------------------------------------*/ @@ -395,6 +413,26 @@ {GNB_CONFIG_STRING_SSPBCHBLOCKPOWER,NULL,0,i64ptr:&scc->ss_PBCH_BlockPower,defint64val:20,TYPE_INT64,0}, \ {GNB_CONFIG_STRING_MSG1SUBCARRIERSPACING,NULL,0,i64ptr:scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->msg1_SubcarrierSpacing,defintval:-1,TYPE_INT64,0}} +/*-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/ +/* Serving Cell Config Dedicated configuration parameters */ +/*-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/ + +#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}} diff --git a/openair2/GNB_APP/gnb_config.c b/openair2/GNB_APP/gnb_config.c index 957485a992..608827cc7a 100644 --- a/openair2/GNB_APP/gnb_config.c +++ b/openair2/GNB_APP/gnb_config.c @@ -293,6 +293,171 @@ 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(1, sizeof(scd->downlinkBWP_ToAddModList)); + + // Downlink bandwidth part + NR_BWP_Downlink_t *bwp = calloc(1, sizeof(*bwp)); + bwp->bwp_Id = 1; + + // Allocate downlink dedicated bandwidth part and PDSCH structures + bwp->bwp_Dedicated = calloc(1, sizeof(*bwp->bwp_Dedicated)); + bwp->bwp_Dedicated->pdsch_Config = calloc(1, sizeof(*bwp->bwp_Dedicated->pdsch_Config)); + bwp->bwp_Dedicated->pdsch_Config->present = NR_SetupRelease_PDSCH_Config_PR_setup; + bwp->bwp_Dedicated->pdsch_Config->choice.setup = calloc(1, sizeof(*bwp->bwp_Dedicated->pdsch_Config->choice.setup)); + bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA = calloc(1, sizeof(*bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA)); + bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->present = NR_SetupRelease_DMRS_DownlinkConfig_PR_setup; + + // Allocate DL DMRS and PTRS configuration + bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup = calloc(1, sizeof(*bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup)); + NR_DMRS_DownlinkConfig_t *NR_DMRS_DownlinkCfg = bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup; + NR_DMRS_DownlinkCfg->phaseTrackingRS=CALLOC(1, sizeof(*NR_DMRS_DownlinkCfg->phaseTrackingRS)); + NR_DMRS_DownlinkCfg->phaseTrackingRS->present = NR_SetupRelease_PTRS_DownlinkConfig_PR_setup; + NR_DMRS_DownlinkCfg->phaseTrackingRS->choice.setup = CALLOC(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(1, sizeof(NR_PTRS_DownlinkCfg->frequencyDensity)); + int *dl_rbs[2]; + for (int i=0;i<2;i++) { + dl_rbs[i] = CALLOC(1, sizeof(*dl_rbs[i])); + *dl_rbs[i] = 0; + ASN_SEQUENCE_ADD(&NR_PTRS_DownlinkCfg->frequencyDensity->list, dl_rbs[i]); + } + NR_PTRS_DownlinkCfg->timeDensity = CALLOC(1, sizeof(NR_PTRS_DownlinkCfg->timeDensity)); + int *dl_mcs[3]; + for (int i=0;i<3;i++) { + dl_mcs[i] = CALLOC(1, sizeof(*dl_mcs[i])); + *dl_mcs[i] = 0; + ASN_SEQUENCE_ADD(&NR_PTRS_DownlinkCfg->timeDensity->list, dl_mcs[i]); + } + NR_PTRS_DownlinkCfg->epre_Ratio = CALLOC(1, sizeof(NR_PTRS_DownlinkCfg->epre_Ratio)); + NR_PTRS_DownlinkCfg->resourceElementOffset = CALLOC(1, sizeof(NR_PTRS_DownlinkCfg->resourceElementOffset)); + *NR_PTRS_DownlinkCfg->resourceElementOffset = 0; + ASN_SEQUENCE_ADD(&scd->downlinkBWP_ToAddModList->list,bwp); + + // Allocate uplink structures + + scd->uplinkConfig = CALLOC(1, sizeof(NR_UplinkConfig_t)); + scd->uplinkConfig->uplinkBWP_ToAddModList = CALLOC(1, sizeof(scd->uplinkConfig->uplinkBWP_ToAddModList)); + + NR_PUSCH_Config_t *pusch_Config = CALLOC(1, sizeof(*pusch_Config)); + + // Allocate UL DMRS and PTRS structures + pusch_Config->dmrs_UplinkForPUSCH_MappingTypeB = CALLOC(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(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(1, sizeof(*NR_DMRS_UplinkConfig->phaseTrackingRS)); + NR_DMRS_UplinkConfig->phaseTrackingRS->present = NR_SetupRelease_PTRS_UplinkConfig_PR_setup; + NR_DMRS_UplinkConfig->phaseTrackingRS->choice.setup = CALLOC(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(1, sizeof(*NR_PTRS_UplinkConfig->transformPrecoderDisabled)); + NR_PTRS_UplinkConfig->transformPrecoderDisabled->frequencyDensity = CALLOC(1, sizeof(*NR_PTRS_UplinkConfig->transformPrecoderDisabled->frequencyDensity)); + int *n_rbs[2]; + for (int i=0;i<2;i++) { + n_rbs[i] = CALLOC(1, sizeof(*n_rbs[i])); + *n_rbs[i] = 0; + ASN_SEQUENCE_ADD(&NR_PTRS_UplinkConfig->transformPrecoderDisabled->frequencyDensity->list, n_rbs[i]); + } + NR_PTRS_UplinkConfig->transformPrecoderDisabled->timeDensity = CALLOC(1, sizeof(*NR_PTRS_UplinkConfig->transformPrecoderDisabled->timeDensity)); + int *ptrs_mcs[3]; + for (int i = 0; i < 3; i++) { + ptrs_mcs[i] = CALLOC(1, sizeof(*ptrs_mcs[i])); + *ptrs_mcs[i] = 0; + ASN_SEQUENCE_ADD(&NR_PTRS_UplinkConfig->transformPrecoderDisabled->timeDensity->list, ptrs_mcs[i]); + } + NR_PTRS_UplinkConfig->transformPrecoderDisabled->resourceElementOffset = CALLOC(1, sizeof(NR_PTRS_UplinkConfig->transformPrecoderDisabled->resourceElementOffset)); + *NR_PTRS_UplinkConfig->transformPrecoderDisabled->resourceElementOffset = 0; + + // UL bandwidth part + NR_BWP_Uplink_t *ubwp = CALLOC(1, sizeof(*ubwp)); + ubwp->bwp_Id = 1; + ubwp->bwp_Dedicated = CALLOC(1, sizeof(*ubwp->bwp_Dedicated)); + + ubwp->bwp_Dedicated->pusch_Config = CALLOC(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; + + ASN_SEQUENCE_ADD(&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) { + // Check for DL PTRS parameters validity + if (scd->downlinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->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 = scd->downlinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->phaseTrackingRS->choice.setup->frequencyDensity->list.count-1; i >= 0; i--) { + if ((*scd->downlinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->phaseTrackingRS->choice.setup->frequencyDensity->list.array[i] < 1) + || (*scd->downlinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->phaseTrackingRS->choice.setup->frequencyDensity->list.array[i] > 276)) { + LOG_I(RRC, "DL PTRS frequencyDensity %d not set. Assuming PTRS not present! \n", i); + free(scd->downlinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->phaseTrackingRS); + scd->downlinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->phaseTrackingRS = NULL; + break; + } + } + } + if (scd->downlinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->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 = scd->downlinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->phaseTrackingRS->choice.setup->timeDensity->list.count-1; i >= 0; i--) { + if ((*scd->downlinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->phaseTrackingRS->choice.setup->timeDensity->list.array[i] < 0) + || (*scd->downlinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->phaseTrackingRS->choice.setup->timeDensity->list.array[i] > 29)) { + LOG_I(RRC, "DL PTRS timeDensity %d not set. Assuming PTRS not present! \n", i); + free(scd->downlinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->phaseTrackingRS); + scd->downlinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->phaseTrackingRS = NULL; + break; + } + } + } + if (scd->downlinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->phaseTrackingRS) { + if (*scd->downlinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->phaseTrackingRS->choice.setup->resourceElementOffset > 2) { + LOG_I(RRC, "Freeing DL PTRS resourceElementOffset \n"); + free(scd->downlinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->phaseTrackingRS->choice.setup->resourceElementOffset); + scd->downlinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->phaseTrackingRS->choice.setup->resourceElementOffset = NULL; + } + if (*scd->downlinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->phaseTrackingRS->choice.setup->epre_Ratio > 1) { + LOG_I(RRC, "Freeing DL PTRS epre_Ratio \n"); + free(scd->downlinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->phaseTrackingRS->choice.setup->epre_Ratio); + scd->downlinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->phaseTrackingRS->choice.setup->epre_Ratio = NULL; + } + } + + if (scd->uplinkConfig->uplinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pusch_Config->choice.setup->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup->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 = scd->uplinkConfig->uplinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pusch_Config->choice.setup->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup->phaseTrackingRS->choice.setup->transformPrecoderDisabled->frequencyDensity->list.count-1; i >= 0; i--) { + if ((*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[i] < 1) + || (*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[i] > 276)) { + LOG_I(RRC, "UL PTRS frequencyDensity %d not set. Assuming PTRS not present! \n", i); + free(scd->uplinkConfig->uplinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pusch_Config->choice.setup->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup->phaseTrackingRS); + scd->uplinkConfig->uplinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pusch_Config->choice.setup->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup->phaseTrackingRS = NULL; + break; + } + } + } + + if (scd->uplinkConfig->uplinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pusch_Config->choice.setup->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup->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 = scd->uplinkConfig->uplinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pusch_Config->choice.setup->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup->phaseTrackingRS->choice.setup->transformPrecoderDisabled->timeDensity->list.count-1; i >= 0; i--) { + if ((*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[i] < 0) + || (*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[i] > 29)) { + LOG_I(RRC, "UL PTRS timeDensity %d not set. Assuming PTRS not present! \n", i); + free(scd->uplinkConfig->uplinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pusch_Config->choice.setup->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup->phaseTrackingRS); + scd->uplinkConfig->uplinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pusch_Config->choice.setup->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup->phaseTrackingRS = NULL; + break; + } + } + } + if (scd->uplinkConfig->uplinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pusch_Config->choice.setup->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup->phaseTrackingRS) { + // Check for UL PTRS parameters validity + if (*scd->uplinkConfig->uplinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pusch_Config->choice.setup->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup->phaseTrackingRS->choice.setup->transformPrecoderDisabled->resourceElementOffset > 2) { + LOG_I(RRC, "Freeing UL PTRS resourceElementOffset \n"); + free(scd->uplinkConfig->uplinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pusch_Config->choice.setup->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup->phaseTrackingRS->choice.setup->transformPrecoderDisabled->resourceElementOffset); + scd->uplinkConfig->uplinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pusch_Config->choice.setup->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup->phaseTrackingRS->choice.setup->transformPrecoderDisabled->resourceElementOffset = NULL; + } + } +} + void RCconfig_nr_flexran() { uint16_t i; @@ -627,6 +792,13 @@ void RCconfig_NRRRC(MessageDef *msg_p, uint32_t i, gNB_RRC_INST *rrc) { prepare_scc(scc); paramdef_t SCCsParams[] = SCCPARAMS_DESC(scc); paramlist_def_t SCCsParamList = {GNB_CONFIG_STRING_SERVINGCELLCONFIGCOMMON, NULL, 0}; + + // Serving Cell Config Dedicated + NR_ServingCellConfig_t *scd = calloc(1,sizeof(NR_ServingCellConfig_t)); + memset((void*)scd,0,sizeof(NR_ServingCellConfig_t)); + prepare_scd(scd); + paramdef_t SCDsParams[] = SCDPARAMS_DESC(scd); + paramlist_def_t SCDsParamList = {GNB_CONFIG_STRING_SERVINGCELLCONFIGDEDICATED, NULL, 0}; ////////// Physical parameters @@ -700,6 +872,23 @@ void RCconfig_NRRRC(MessageDef *msg_p, uint32_t i, gNB_RRC_INST *rrc) { (int)scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->rach_ConfigGeneric.preambleReceivedTargetPower); fix_scc(scc,ssb_bitmap); } + + sprintf(aprefix, "%s.[%i]", GNB_CONFIG_STRING_GNB_LIST, 0); + + config_getlist(&SCDsParamList, NULL, 0, aprefix); + if (SCDsParamList.numelt > 0) { + sprintf(aprefix, "%s.[%i].%s.[%i]", GNB_CONFIG_STRING_GNB_LIST,0,GNB_CONFIG_STRING_SERVINGCELLCONFIGDEDICATED, 0); + config_get( SCDsParams,sizeof(SCDsParams)/sizeof(paramdef_t),aprefix); + LOG_I(RRC,"Read in ServingCellConfigDedicated UL (FreqDensity_0 %d, FreqDensity_1 %d, TimeDensity_0 %d, TimeDensity_1 %d, TimeDensity_2 %d, RE offset %d \n", + (int)*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], + (int)*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], + (int)*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], + (int)*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], + (int)*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], + (int)*scd->uplinkConfig->uplinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pusch_Config->choice.setup->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup->phaseTrackingRS->choice.setup->transformPrecoderDisabled->resourceElementOffset); + } + fix_scd(scd); + printf("NRRRC %d: Southbound Transport %s\n",i,*(GNBParamList.paramarray[i][GNB_TRANSPORT_S_PREFERENCE_IDX].strptr)); if (strcmp(*(GNBParamList.paramarray[i][GNB_TRANSPORT_S_PREFERENCE_IDX].strptr), "local_mac") == 0) { @@ -770,6 +959,7 @@ void RCconfig_NRRRC(MessageDef *msg_p, uint32_t i, gNB_RRC_INST *rrc) { printf("pucch_TargetSNRx10 %d\n",*GNBParamList.paramarray[i][GNB_PUCCH_TARGETPOW_X10_IDX].iptr); NRRRC_CONFIGURATION_REQ (msg_p).pucch_TargetSNRx10 = *GNBParamList.paramarray[i][GNB_PUCCH_TARGETPOW_X10_IDX].iptr; NRRRC_CONFIGURATION_REQ (msg_p).scc = scc; + NRRRC_CONFIGURATION_REQ (msg_p).scd = scd; }// diff --git a/openair2/LAYER2/MAC/mac.h b/openair2/LAYER2/MAC/mac.h index 1bae590a59..ae8522bc83 100644 --- a/openair2/LAYER2/MAC/mac.h +++ b/openair2/LAYER2/MAC/mac.h @@ -490,7 +490,7 @@ typedef struct { /*! \brief Uplink SCH PDU Structure */ typedef struct { - int8_t payload[SCH_PAYLOAD_SIZE_MAX]; /*!< \brief SACH payload */ + uint8_t payload[SCH_PAYLOAD_SIZE_MAX]; /*!< \brief SACH payload */ uint16_t Pdu_size; } __attribute__ ((__packed__)) ULSCH_PDU; diff --git a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c index 5d1b08bcf6..cdeb23c099 100644 --- a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c +++ b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c @@ -31,6 +31,7 @@ */ #include "LAYER2/NR_MAC_gNB/mac_proto.h" +#include "common/utils/nr/nr_common.h" #include #define reserved 0xffff @@ -1220,6 +1221,11 @@ int get_nr_prach_occasion_info_from_index(uint8_t index, else { // FDD x = table_6_3_3_2_2_prachConfig_Index[index][2]; s_map = table_6_3_3_2_2_prachConfig_Index[index][4]; + for(int i = 0; i < 64 ; i++) { + if ( (s_map >> i) & 0x01) { + (*N_RA_sfn)++; + } + } *N_RA_slot = table_6_3_3_2_2_prachConfig_Index[index][6]; if (start_symbol != NULL && N_t_slot != NULL && N_dur != NULL && format != NULL){ *start_symbol = table_6_3_3_2_2_prachConfig_Index[index][5]; @@ -1396,19 +1402,17 @@ int get_nr_prach_info_from_index(uint8_t index, if (table_6_3_3_2_3_prachConfig_Index[index][1] != -1) format2 = (uint8_t) table_6_3_3_2_3_prachConfig_Index[index][1]; *format = ((uint8_t) table_6_3_3_2_3_prachConfig_Index[index][0]) | (format2<<8); - LOG_D(MAC,"Frame %d slot %d: Getting PRACH info from index %d (col 6 %lu) absoluteFrequencyPointA %u mu %u frame_type %u start_symbol %u N_t_slot %u N_dur %u N_RA_slot %u RA_sfn_index %u \n", - frame, - slot, - index, - table_6_3_3_2_3_prachConfig_Index[index][6], - pointa, - mu, - unpaired, - *start_symbol, - *N_t_slot, - *N_dur, - *N_RA_slot, - *RA_sfn_index); + LOG_D(MAC,"Frame %d slot %d: Getting PRACH info from index %d (col 6 %lu) absoluteFrequencyPointA %u mu %u frame_type %u start_symbol %u N_t_slot %u N_dur %u N_RA_slot %u RA_sfn_index %u \n", frame, + slot, + index, table_6_3_3_2_3_prachConfig_Index[index][6], + pointa, + mu, + unpaired, + *start_symbol, + *N_t_slot, + *N_dur, + *N_RA_slot, + *RA_sfn_index); } return 1; } @@ -1429,6 +1433,11 @@ int get_nr_prach_info_from_index(uint8_t index, if ( (table_6_3_3_2_2_prachConfig_Index[index][6] <= 1) && (slot%2 == 0) ) return 0; // no prach in even slots @ 30kHz for 1 prach per subframe } + for(int i = 0; i <= subframe ; i++) { + if ( (s_map >> i) & 0x01) { + (*RA_sfn_index)++; + } + } if (start_symbol != NULL && N_t_slot != NULL && N_dur != NULL && format != NULL){ *start_symbol = table_6_3_3_2_2_prachConfig_Index[index][5]; *N_t_slot = table_6_3_3_2_2_prachConfig_Index[index][7]; @@ -1567,79 +1576,6 @@ uint8_t compute_nr_root_seq(NR_RACH_ConfigCommon_t *rach_config, } } -// Table 5.2-1 NR operating bands in FR1 & FR2 (3GPP TS 38.101) -// Table 5.4.2.3-1 Applicable NR-ARFCN per operating band in FR1 & FR2 (3GPP TS 38.101) -// Notes: -// - N_OFFs for bands from 80 to 89 and band 95 is referred to UL -// - Frequencies are expressed in KHz -// - col: NR_band ul_min ul_max dl_min dl_max step N_OFFs_DL deltaf_raster -nr_bandentry_t nr_bandtable[] = { - {1, 1920000, 1980000, 2110000, 2170000, 20, 422000, 100}, - {2, 1850000, 1910000, 1930000, 1990000, 20, 386000, 100}, - {3, 1710000, 1785000, 1805000, 1880000, 20, 361000, 100}, - {5, 824000, 849000, 869000, 894000, 20, 173800, 100}, - {7, 2500000, 2570000, 2620000, 2690000, 20, 524000, 100}, - {8, 880000, 915000, 925000, 960000, 20, 185000, 100}, - {12, 698000, 716000, 729000, 746000, 20, 145800, 100}, - {14, 788000, 798000, 758000, 768000, 20, 151600, 100}, - {18, 815000, 830000, 860000, 875000, 20, 172000, 100}, - {20, 832000, 862000, 791000, 821000, 20, 158200, 100}, - {25, 1850000, 1915000, 1930000, 1995000, 20, 386000, 100}, - {26, 814000, 849000, 859000, 894000, 20, 171800, 100}, - {28, 703000, 758000, 758000, 813000, 20, 151600, 100}, - {29, 000, 000, 717000, 728000, 20, 143400, 100}, - {30, 2305000, 2315000, 2350000, 2360000, 20, 470000, 100}, - {34, 2010000, 2025000, 2010000, 2025000, 20, 402000, 100}, - {38, 2570000, 2620000, 2570000, 2630000, 20, 514000, 100}, - {39, 1880000, 1920000, 1880000, 1920000, 20, 376000, 100}, - {40, 2300000, 2400000, 2300000, 2400000, 20, 460000, 100}, - {41, 2496000, 2690000, 2496000, 2690000, 3, 499200, 15}, - {41, 2496000, 2690000, 2496000, 2690000, 6, 499200, 30}, - {47, 5855000, 5925000, 5855000, 5925000, 1, 790334, 15}, - //{48, 3550000, 3700000, 3550000, 3700000, 1, 636667, 15}, - //{48, 3550000, 3700000, 3550000, 3700000, 2, 636668, 30}, - {50, 1432000, 1517000, 1432000, 1517000, 20, 286400, 100}, - {51, 1427000, 1432000, 1427000, 1432000, 20, 285400, 100}, - {53, 2483500, 2495000, 2483500, 2495000, 20, 496700, 100}, - {65, 1920000, 2010000, 2110000, 2200000, 20, 422000, 100}, - {66, 1710000, 1780000, 2110000, 2200000, 20, 422000, 100}, - {70, 1695000, 1710000, 1995000, 2020000, 20, 399000, 100}, - {71, 663000, 698000, 617000, 652000, 20, 123400, 100}, - {74, 1427000, 1470000, 1475000, 1518000, 20, 295000, 100}, - {75, 000, 000, 1432000, 1517000, 20, 286400, 100}, - {76, 000, 000, 1427000, 1432000, 20, 285400, 100}, - {77, 3300000, 4200000, 3300000, 4200000, 1, 620000, 15}, - {77, 3300000, 4200000, 3300000, 4200000, 2, 620000, 30}, - {78, 3300000, 3800000, 3300000, 3800000, 1, 620000, 15}, - {78, 3300000, 3800000, 3300000, 3800000, 2, 620000, 30}, - {79, 4400010, 5000000, 4400010, 5000000, 1, 693334, 15}, - {79, 4400010, 5000000, 4400010, 5000000, 2, 693334, 30}, - {80, 1710000, 1785000, 000, 000, 20, 342000, 100}, - {81, 880000, 915000, 000, 000, 20, 176000, 100}, - {82, 832000, 862000, 000, 000, 20, 166400, 100}, - {83, 703000, 748000, 000, 000, 20, 140600, 100}, - {84, 1920000, 1980000, 000, 000, 20, 384000, 100}, - {86, 1710000, 1785000, 000, 000, 20, 342000, 100}, - {89, 824000, 849000, 000, 000, 20, 342000, 100}, - {90, 2496000, 2690000, 2496000, 2690000, 3, 499200, 15}, - {90, 2496000, 2690000, 2496000, 2690000, 6, 499200, 30}, - {90, 2496000, 2690000, 2496000, 2690000, 20, 499200, 100}, - {91, 832000, 862000, 1427000, 1432000, 20, 285400, 100}, - {92, 832000, 862000, 1432000, 1517000, 20, 286400, 100}, - {93, 880000, 915000, 1427000, 1432000, 20, 285400, 100}, - {94, 880000, 915000, 1432000, 1517000, 20, 286400, 100}, - {95, 2010000, 2025000, 000, 000, 20, 402000, 100}, - {257,26500020,29500000,26500020,29500000, 1,2054166, 60}, - {257,26500080,29500000,26500080,29500000, 2,2054167, 120}, - {258,24250080,27500000,24250080,27500000, 1,2016667, 60}, - {258,24250080,27500000,24250080,27500000, 2,2016667, 120}, - {260,37000020,40000000,37000020,40000000, 1,2229166, 60}, - {260,37000080,40000000,37000080,40000000, 2,2229167, 120}, - {261,27500040,28350000,27500040,28350000, 1,2070833, 60}, - {261,27500040,28350000,27500040,28350000, 2,2070833, 120} -}; - - // TS 38.211 Table 6.4.1.1.3-3: PUSCH DMRS positions l' within a slot for single-symbol DMRS and intra-slot frequency hopping disabled. // The first 4 colomns are PUSCH mapping type A and the last 4 colomns are PUSCH mapping type B. // When l' = l0, it is represented by 1 @@ -1680,11 +1616,9 @@ int32_t table_6_4_1_1_3_4_pusch_dmrs_positions_l [12][8] = { {1, 1025, -1, -1, 1, 513, -1, -1}, //14 // (DMRS l' position) }; -#define NR_BANDTABLE_SIZE (sizeof(nr_bandtable)/sizeof(nr_bandentry_t)) - // Returns the corresponding row index of the NR table -int get_nr_table_idx(int nr_bandP, uint8_t scs_index){ - +int get_nr_table_idx(int nr_bandP, uint8_t scs_index) +{ int i, j; int scs_khz = 15 << scs_index; int supplementary_bands[] = {29,75,76,80,81,82,83,84,86,89,95}; @@ -1695,8 +1629,8 @@ int get_nr_table_idx(int nr_bandP, uint8_t scs_index){ AssertFatal(0 == 1, "Band %d is a supplementary band (%d). This is not supported yet.\n", nr_bandP, supplementary_bands[j]); } - AssertFatal(nr_bandP <= nr_bandtable[NR_BANDTABLE_SIZE-1].band, "NR band %d exceeds NR bands table maximum limit %d\n", nr_bandP, nr_bandtable[NR_BANDTABLE_SIZE-1].band); - for (i = 0; i < NR_BANDTABLE_SIZE && nr_bandtable[i].band != nr_bandP; i++); + AssertFatal(nr_bandP <= nr_bandtable[nr_bandtable_size-1].band, "NR band %d exceeds NR bands table maximum limit %d\n", nr_bandP, nr_bandtable[nr_bandtable_size-1].band); + for (i = 0; i < nr_bandtable_size && nr_bandtable[i].band != nr_bandP; i++); // selection of correct Deltaf raster according to SCS if ((nr_bandtable[i].deltaf_raster != 100) && (nr_bandtable[i].deltaf_raster != scs_khz)) @@ -1705,35 +1639,33 @@ int get_nr_table_idx(int nr_bandP, uint8_t scs_index){ LOG_D(PHY, "NR band table index %d (Band %d, dl_min %lu, ul_min %lu)\n", i, nr_bandtable[i].band, nr_bandtable[i].dl_min,nr_bandtable[i].ul_min); return i; - } // Computes the duplex spacing (either positive or negative) in KHz -void get_delta_duplex(int nr_bandP, uint8_t scs_index, int32_t *delta_duplex){ - +int32_t get_delta_duplex(int nr_bandP, uint8_t scs_index) +{ int nr_table_idx = get_nr_table_idx(nr_bandP, scs_index); - *delta_duplex = (nr_bandtable[nr_table_idx].ul_min - nr_bandtable[nr_table_idx].dl_min); + int32_t delta_duplex = (nr_bandtable[nr_table_idx].ul_min - nr_bandtable[nr_table_idx].dl_min); - LOG_D(PHY, "NR band duplex spacing is %d KHz (nr_bandtable[%d].band = %d)\n", *delta_duplex, nr_table_idx, nr_bandtable[nr_table_idx].band); + LOG_I(PHY, "NR band duplex spacing is %d KHz (nr_bandtable[%d].band = %d)\n", delta_duplex, nr_table_idx, nr_bandtable[nr_table_idx].band); + return delta_duplex; } -void get_frame_type(uint16_t current_band, - uint8_t scs_index, - lte_frame_type_t *current_type){ +lte_frame_type_t get_frame_type(uint16_t current_band, uint8_t scs_index) +{ + lte_frame_type_t current_type; + int32_t delta_duplex = get_delta_duplex(current_band, scs_index); - int32_t current_offset; - get_delta_duplex(current_band, scs_index, ¤t_offset); - - current_offset *= 1000; - if (current_offset == 0) - *current_type = TDD; + if (delta_duplex == 0) + current_type = TDD; else - *current_type = FDD; + current_type = FDD; - LOG_I(MAC, "NR band %d, duplex mode %s, duplex spacing = %d KHz\n", current_band, duplex_mode[*current_type], current_offset); + LOG_I(MAC, "NR band %d, duplex mode %s, duplex spacing = %d KHz\n", current_band, duplex_mode[current_type], delta_duplex); + return current_type; } uint16_t config_bandwidth(int mu, int nb_rb, int nr_band) @@ -1911,7 +1843,6 @@ uint64_t from_nrarfcn(int nr_bandP, int deltaFglobal = 5; uint32_t N_REF_Offs = 0; uint64_t F_REF_Offs_khz = 0; - int32_t delta_duplex; uint64_t N_OFFs, frequency, freq_min; int i = get_nr_table_idx(nr_bandP, scs_index); @@ -1926,7 +1857,7 @@ uint64_t from_nrarfcn(int nr_bandP, F_REF_Offs_khz = 24250080; } - get_delta_duplex(nr_bandP, scs_index, &delta_duplex); + int32_t delta_duplex = get_delta_duplex(nr_bandP, scs_index); if (delta_duplex <= 0){ // DL band >= UL band if (nrarfcn >= nr_bandtable[i].N_OFFs_DL){ // is TDD of FDD DL @@ -2836,11 +2767,15 @@ int is_nr_DL_slot(NR_ServingCellConfigCommon_t *scc,slot_t slot) { else return(slot_in_period <= slots1+scc->tdd_UL_DL_ConfigurationCommon->pattern2->nrofDownlinkSlots ? 1 : 0); } -int is_nr_UL_slot(NR_ServingCellConfigCommon_t *scc,slot_t slot) { +int is_nr_UL_slot(NR_ServingCellConfigCommon_t *scc, slot_t slot, lte_frame_type_t frame_type) { int period,period1,period2=0; - if (scc->tdd_UL_DL_ConfigurationCommon==NULL) return(1); + // Note: condition on frame_type + // goal: the UL scheduler assumes mode is TDD therefore this hack is needed to make FDD work + if (scc->tdd_UL_DL_ConfigurationCommon == NULL || frame_type == FDD) { + return(1); + } if (scc->tdd_UL_DL_ConfigurationCommon->pattern1.ext1 && scc->tdd_UL_DL_ConfigurationCommon->pattern1.ext1->dl_UL_TransmissionPeriodicity_v1530) @@ -3064,51 +2999,14 @@ bool set_dl_ptrs_values(NR_PTRS_DownlinkConfig_t *ptrs_config, valid = false; return valid; } - //printf("[MAC] PTRS is set K= %u L= %u\n", *K_ptrs,1<<*L_ptrs); + + /* Moved below check from scheduler function to here */ + if (*L_ptrs >= NrOfSymbols) { + valid = false; + return valid; + } return valid; } -void get_band(uint64_t downlink_frequency, - uint16_t *current_band, - int32_t *current_offset, - lte_frame_type_t *current_type) -{ - int ind; - uint64_t center_frequency_khz; - uint64_t center_freq_diff_khz; - uint64_t dl_freq_khz = downlink_frequency/1000; - - center_freq_diff_khz = 999999999999999999; // 2^64 - *current_band = 0; - - for ( ind=0; - ind < sizeof(nr_bandtable) / sizeof(nr_bandtable[0]); - ind++) { - - LOG_I(PHY, "Scanning band %d, dl_min %"PRIu64", ul_min %"PRIu64"\n", nr_bandtable[ind].band, nr_bandtable[ind].dl_min,nr_bandtable[ind].ul_min); - - if ( nr_bandtable[ind].dl_min <= dl_freq_khz && nr_bandtable[ind].dl_max >= dl_freq_khz ) { - - center_frequency_khz = (nr_bandtable[ind].dl_max + nr_bandtable[ind].dl_min)/2; - if (abs(dl_freq_khz - center_frequency_khz) < center_freq_diff_khz){ - *current_band = nr_bandtable[ind].band; - *current_offset = (nr_bandtable[ind].ul_min - nr_bandtable[ind].dl_min)*1000; - center_freq_diff_khz = abs(dl_freq_khz - center_frequency_khz); - - if (*current_offset == 0) - *current_type = TDD; - else - *current_type = FDD; - } - } - } - - LOG_I( PHY, "DL frequency %"PRIu64": band %d, frame_type %d, UL frequency %"PRIu64"\n", - downlink_frequency, *current_band, *current_type, downlink_frequency+*current_offset); - - AssertFatal(*current_band != 0, - "Can't find EUTRA band for frequency %lu\n", downlink_frequency); -} - uint32_t get_ssb_slot(uint32_t ssb_index){ // this function now only support f <= 3GHz @@ -3480,3 +3378,79 @@ int get_type0_PDCCH_CSS_config_parameters(NR_Type0_PDCCH_CSS_config_t *type0_PDC return 0; } + +/* extract UL PTRS values from RRC and validate it based upon 38.214 6.2.3 */ +bool set_ul_ptrs_values(NR_PTRS_UplinkConfig_t *ul_ptrs_config, + uint16_t rbSize,uint8_t mcsIndex, uint8_t mcsTable, + uint8_t *K_ptrs, uint8_t *L_ptrs, + uint8_t *reOffset, uint8_t *maxNumPorts, uint8_t *ulPower, + uint8_t NrOfSymbols) +{ + bool valid = true; + + /* as defined in T 38.214 6.2.3 */ + if(rbSize < 3) { + valid = false; + return valid; + } + /* Check for Frequency Density values */ + if(ul_ptrs_config->transformPrecoderDisabled->frequencyDensity->list.count < 2) { + /* Default value for K_PTRS = 2 as defined in T 38.214 6.2.3 */ + *K_ptrs = 2; + } + else { + *K_ptrs = get_K_ptrs(*ul_ptrs_config->transformPrecoderDisabled->frequencyDensity->list.array[0], + *ul_ptrs_config->transformPrecoderDisabled->frequencyDensity->list.array[1], + rbSize); + } + /* Check for time Density values */ + if(ul_ptrs_config->transformPrecoderDisabled->timeDensity->list.count < 3) { + *L_ptrs = 0; + } + else { + *L_ptrs = get_L_ptrs(*ul_ptrs_config->transformPrecoderDisabled->timeDensity->list.array[0], + *ul_ptrs_config->transformPrecoderDisabled->timeDensity->list.array[1], + *ul_ptrs_config->transformPrecoderDisabled->timeDensity->list.array[2], + mcsIndex, + mcsTable); + } + + *reOffset = *ul_ptrs_config->transformPrecoderDisabled->resourceElementOffset; + *maxNumPorts = ul_ptrs_config->transformPrecoderDisabled->maxNrofPorts; + *ulPower = ul_ptrs_config->transformPrecoderDisabled->ptrs_Power; + /* If either or both of the parameters PT-RS time density (LPT-RS) and PT-RS frequency density (KPT-RS), shown in Table + * 6.2.3.1-1 and Table 6.2.3.1-2, indicates that 'PT-RS not present', the UE shall assume that PT-RS is not present + */ + if(*K_ptrs ==2 || *K_ptrs ==4 ) { + valid = true; + } + else { + valid = false; + return valid; + } + if(*L_ptrs ==0 || *L_ptrs ==1 || *L_ptrs ==2 ) { + valid = true; + } + else { + valid = false; + return valid; + } + /* PTRS is not present also : + * When the UE is receiving a PUSCH with allocation duration of 4 symbols and if LPT-RS is set to 4, the UE shall assume + * PT-RS is not transmitted + * When the UE is receiving a PUSCH with allocation duration of 2 symbols as defined in Clause 6.4.1.2.2 of [4, TS + * 38.211] and if LPT-RS is set to 2 or 4, the UE shall assume PT-RS is not transmitted. + */ + if((NrOfSymbols == 4 && *L_ptrs ==2) || ((NrOfSymbols == 2 && *L_ptrs > 0))) { + valid = false; + return valid; + } + + /* Moved below check from nr_ue_scheduler function to here */ + if (*L_ptrs >= NrOfSymbols) { + valid = false; + return valid; + } + return valid; +} + diff --git a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h index 087d316567..3e21131b69 100644 --- a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h +++ b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h @@ -39,9 +39,9 @@ uint16_t config_bandwidth(int mu, int nb_rb, int nr_band); -void get_frame_type(uint16_t nr_bandP, uint8_t scs_index, lte_frame_type_t *current_type); +lte_frame_type_t get_frame_type(uint16_t nr_bandP, uint8_t scs_index); -void get_delta_duplex(int nr_bandP, uint8_t scs_index, int32_t *delta_duplex); +int32_t get_delta_duplex(int nr_bandP, uint8_t scs_index); uint64_t from_nrarfcn(int nr_bandP, uint8_t scs_index, uint32_t dl_nrarfcn); @@ -51,7 +51,7 @@ int16_t fill_dmrs_mask(NR_PDSCH_Config_t *pdsch_Config,int dmrs_TypeA_Position,i int is_nr_DL_slot(NR_ServingCellConfigCommon_t *scc,slot_t slotP); -int is_nr_UL_slot(NR_ServingCellConfigCommon_t *scc,slot_t slotP); +int is_nr_UL_slot(NR_ServingCellConfigCommon_t *scc, slot_t slotP, lte_frame_type_t frame_type); uint16_t nr_dci_size(const NR_ServingCellConfigCommon_t *scc, const NR_CellGroupConfig_t *secondaryCellGroup, @@ -81,7 +81,7 @@ int get_nr_prach_info_from_index(uint8_t index, uint8_t *N_dur, uint16_t *RA_sfn_index, uint8_t *N_RA_slot, - uint8_t *config_period); + uint8_t *config_period); int get_nr_prach_occasion_info_from_index(uint8_t index, uint32_t pointa, @@ -140,8 +140,12 @@ bool set_dl_ptrs_values(NR_PTRS_DownlinkConfig_t *ptrs_config, uint8_t *K_ptrs, uint8_t *L_ptrs,uint8_t *portIndex, uint8_t *nERatio,uint8_t *reOffset, uint8_t NrOfSymbols); -void get_band(uint64_t downlink_frequency, uint16_t *current_band, int32_t *current_offset, lte_frame_type_t *current_type); +bool set_ul_ptrs_values(NR_PTRS_UplinkConfig_t *ul_ptrs_config, + uint16_t rbSize,uint8_t mcsIndex, uint8_t mcsTable, + uint8_t *K_ptrs, uint8_t *L_ptrs, + uint8_t *reOffset, uint8_t *maxNumPorts, uint8_t *ulPower, + uint8_t NrOfSymbols); uint8_t get_num_dmrs_symbols(NR_PDSCH_Config_t *pdsch_Config,int dmrs_TypeA_Position,int NrOfSymbols); /* \brief Set the transform precoding according to 6.1.3 of 3GPP TS 38.214 version 16.3.0 Release 16 diff --git a/openair2/LAYER2/NR_MAC_UE/config_ue.c b/openair2/LAYER2/NR_MAC_UE/config_ue.c index f6bd5436bc..fee2efc4a8 100755 --- a/openair2/LAYER2/NR_MAC_UE/config_ue.c +++ b/openair2/LAYER2/NR_MAC_UE/config_ue.c @@ -203,13 +203,12 @@ void config_common_ue(NR_UE_MAC_INST_t *mac, uint32_t band = *scc->downlinkConfigCommon->frequencyInfoDL->frequencyBandList.list.array[0]; frequency_range_t frequency_range = band<100?FR1:FR2; - lte_frame_type_t frame_type; - get_frame_type(*scc->downlinkConfigCommon->frequencyInfoDL->frequencyBandList.list.array[0], *scc->ssbSubcarrierSpacing, &frame_type); + mac->frame_type = get_frame_type(*scc->downlinkConfigCommon->frequencyInfoDL->frequencyBandList.list.array[0], *scc->ssbSubcarrierSpacing); // cell config cfg->cell_config.phy_cell_id = *scc->physCellId; - cfg->cell_config.frame_duplex_type = frame_type; + cfg->cell_config.frame_duplex_type = mac->frame_type; // SSB config cfg->ssb_config.ss_pbch_power = scc->ss_PBCH_BlockPower; @@ -313,7 +312,7 @@ void config_common_ue(NR_UE_MAC_INST_t *mac, cfg->prach_config.num_prach_fd_occasions_list[i].k1 = scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->rach_ConfigGeneric.msg1_FrequencyStart; cfg->prach_config.num_prach_fd_occasions_list[i].prach_zero_corr_conf = scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->rach_ConfigGeneric.zeroCorrelationZoneConfig; - cfg->prach_config.num_prach_fd_occasions_list[i].num_root_sequences = compute_nr_root_seq(scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup, nb_preambles, frame_type,frequency_range); + cfg->prach_config.num_prach_fd_occasions_list[i].num_root_sequences = compute_nr_root_seq(scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup, nb_preambles, mac->frame_type, frequency_range); //cfg->prach_config.num_prach_fd_occasions_list[i].num_unused_root_sequences = ??? } diff --git a/openair2/LAYER2/NR_MAC_UE/mac_defs.h b/openair2/LAYER2/NR_MAC_UE/mac_defs.h index dd0aa15c52..3e299d291e 100755 --- a/openair2/LAYER2/NR_MAC_UE/mac_defs.h +++ b/openair2/LAYER2/NR_MAC_UE/mac_defs.h @@ -325,6 +325,8 @@ typedef struct { NR_ControlResourceSet_t *coreset[MAX_NUM_BWP][FAPI_NR_MAX_CORESET_PER_BWP]; NR_SearchSpace_t *SSpace[MAX_NUM_BWP][FAPI_NR_MAX_CORESET_PER_BWP][FAPI_NR_MAX_SS_PER_CORESET]; + lte_frame_type_t frame_type; + /*BWP*/ // dedicated active DL BWP NR_BWP_Id_t DL_BWP_Id; diff --git a/openair2/LAYER2/NR_MAC_UE/mac_proto.h b/openair2/LAYER2/NR_MAC_UE/mac_proto.h index c4909c1384..14d1ea63fb 100755 --- a/openair2/LAYER2/NR_MAC_UE/mac_proto.h +++ b/openair2/LAYER2/NR_MAC_UE/mac_proto.h @@ -56,14 +56,14 @@ int8_t nr_ue_decode_mib( void *pduP, uint16_t cell_id ); -/**\brief decode sib1 pdu in NR_UE, from if_module dl_ind +/**\brief decode SIB1 and other SIs pdus in NR_UE, from if_module dl_ind \param module_id module id \param cc_id component carrier id \param gNB_index gNB index \param sibs_mask sibs mask \param pduP pointer to pdu \param pdu_length length of pdu */ -int8_t nr_ue_decode_sib1(module_id_t module_id, +int8_t nr_ue_decode_BCCH_DL_SCH(module_id_t module_id, int cc_id, unsigned int gNB_index, uint32_t sibs_mask, diff --git a/openair2/LAYER2/NR_MAC_UE/mac_vars.c b/openair2/LAYER2/NR_MAC_UE/mac_vars.c index ecabdb870c..383267090f 100644 --- a/openair2/LAYER2/NR_MAC_UE/mac_vars.c +++ b/openair2/LAYER2/NR_MAC_UE/mac_vars.c @@ -32,7 +32,7 @@ #include -const char *rnti_types[]={"RNTI_new", "RNTI_C", "RNTI_RA", "NR_RNTI_P", "NR_RNTI_CS", "NR_RNTI_TC"}; +const char *rnti_types[]={"RNTI_new", "RNTI_C", "RNTI_RA", "NR_RNTI_P", "NR_RNTI_CS", "NR_RNTI_TC", "NR_RNTI_SP_CSI", "NR_RNTI_SI"}; const char *dci_formats[]={"1_0", "1_1", "2_0", "2_1", "2_2", "2_3", "0_0", "0_1"}; // table_7_3_1_1_2_2_3_4_5 contains values for number of layers and precoding information for tables 7.3.1.1.2-2/3/4/5 from TS 38.212 subclause 7.3.1.1.2 diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c index b4b63e0064..8f234cb585 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c @@ -35,6 +35,7 @@ /* RRC */ #include "NR_RACH-ConfigCommon.h" +#include "RRC/NR_UE/rrc_proto.h" /* PHY */ #include "PHY/NR_TRANSPORT/nr_transport_common_proto.h" @@ -514,7 +515,8 @@ uint8_t nr_ue_get_rach(NR_PRACH_RESOURCES_t *prach_resources, uint8_t sdu_lcids[NB_RB_MAX] = {0}; uint16_t sdu_lengths[NB_RB_MAX] = {0}; - int TBS_bytes = 848, header_length_total=0, num_sdus, offset, mac_ce_len; + int num_sdus = 0; + int offset = 0; // Delay init RA procedure to allow the convergence of the IIR filter on PRACH noise measurements at gNB side if (!prach_resources->init_msg1) { @@ -532,36 +534,27 @@ uint8_t nr_ue_get_rach(NR_PRACH_RESOURCES_t *prach_resources, LOG_D(MAC, "RA not active. Checking for data to transmit from upper layers...\n"); - payload = (uint8_t*) &mac->CCCH_pdu.payload; - mac_ce_len = 0; + uint8_t TBS_max = 8 + sizeof(NR_MAC_SUBHEADER_SHORT) + sizeof(NR_MAC_SUBHEADER_SHORT); + payload = (uint8_t*) mac->CCCH_pdu.payload; + num_sdus = 1; post_padding = 1; + sdu_lcids[0] = lcid; - if (0){ - // initialisation by RRC - // CCCH PDU - // size_sdu = (uint16_t) mac_rrc_data_req_ue(mod_id, - // CC_id, - // frame, - // CCCH, - // 1, - // mac_sdus, - // gNB_id, - // 0); - LOG_D(MAC,"[UE %d] Frame %d: Requested RRCConnectionRequest, got %d bytes\n", mod_id, frame, size_sdu); - } else { - // fill ulsch_buffer with random data - for (int i = 0; i < TBS_bytes; i++){ - mac_sdus[i] = (unsigned char) (lrand48()&0xff); - } - //Sending SDUs with size 1 - //Initialize elements of sdu_lcids and sdu_lengths - sdu_lcids[0] = lcid; - sdu_lengths[0] = TBS_bytes - 3 - post_padding - mac_ce_len; - header_length_total += 2 + (sdu_lengths[0] >= 128); - size_sdu += sdu_lengths[0]; + // initialisation by RRC + + // TODO: To be removed after RA procedures fully implemented + if(get_softmodem_params()->do_ra) { + nr_rrc_ue_generate_RRCSetupRequest(mod_id,gNB_id); } + // CCCH PDU + size_sdu = (uint16_t) nr_mac_rrc_data_req_ue(mod_id, CC_id, gNB_id, frame, CCCH, mac_sdus); + + sdu_lengths[0] = size_sdu; + + LOG_D(MAC,"[UE %d] Frame %d: Requested RRCConnectionRequest, got %d bytes\n", mod_id, frame, size_sdu); + if (size_sdu > 0) { LOG_D(MAC, "[UE %d][%d.%d]: starting initialisation Random Access Procedure...\n", mod_id, frame, nr_slot_tx); @@ -589,12 +582,27 @@ uint8_t nr_ue_get_rach(NR_PRACH_RESOURCES_t *prach_resources, post_padding, 0); + AssertFatal(TBS_max > offset, "Frequency resources are not enough for Msg3!\n"); + // Padding: fill remainder with 0 if (post_padding > 0){ - for (int j = 0; j < (TBS_bytes - offset); j++) - payload[offset + j] = 0; // mac_pdu[offset + j] = 0; + for (int j = 0; j < (TBS_max - offset); j++) + payload[offset + j] = 0; } - } + } + + LOG_D(MAC,"size_sdu = %i\n", size_sdu); + LOG_D(MAC,"offset = %i\n", offset); + for(int k = 0; k < TBS_max; k++) { + LOG_D(MAC,"(%i): %i\n", k, prach_resources->Msg3[k]); + } + + // Msg3 was initialized with TBS_max bytes because the RA_Msg3_size will only be known after + // receiving Msg2 (which contains the Msg3 resource reserve). + // Msg3 will be transmitted with RA_Msg3_size bytes, removing unnecessary 0s. + mac->ulsch_pdu.Pdu_size = TBS_max; + memcpy(mac->ulsch_pdu.payload, prach_resources->Msg3, TBS_max); + } else if (ra->RA_window_cnt != -1) { // RACH is active LOG_D(MAC, "In %s [%d.%d] RA is active: RA window count %d, RA backoff count %d\n", __FUNCTION__, frame, nr_slot_tx, ra->RA_window_cnt, ra->RA_backoff_cnt); diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c index 64067e9d60..cb104092f1 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c @@ -154,13 +154,13 @@ int8_t nr_ue_decode_mib(module_id_t module_id, return 0; } -int8_t nr_ue_decode_sib1(module_id_t module_id, - int cc_id, - unsigned int gNB_index, - uint32_t sibs_mask, - uint8_t *pduP, - uint32_t pdu_len) { - LOG_D(MAC, "Decode sib1\n"); +int8_t nr_ue_decode_BCCH_DL_SCH(module_id_t module_id, + int cc_id, + unsigned int gNB_index, + uint32_t sibs_mask, + uint8_t *pduP, + uint32_t pdu_len) { + LOG_D(NR_MAC, "Decoding NR-BCCH-DL-SCH-Message (SIB1 or SI)\n"); nr_mac_rrc_data_ind_ue(module_id, cc_id, gNB_index, NR_BCCH_DL_SCH, (uint8_t *) pduP, pdu_len); return 0; } @@ -583,7 +583,6 @@ int8_t nr_ue_process_dci(module_id_t module_id, int cc_id, uint8_t gNB_index, fr } } - break; } @@ -814,7 +813,17 @@ int8_t nr_ue_process_dci(module_id_t module_id, int cc_id, uint8_t gNB_index, fr dl_config->dl_config_list[dl_config->number_pdus].pdu_type = FAPI_NR_DL_CONFIG_TYPE_DLSCH; dl_config->dl_config_list[dl_config->number_pdus].dlsch_config_pdu.rnti = rnti; + + // FIXME: fix number of additional dmrs + if(pdsch_config->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->dmrs_AdditionalPosition == NULL) + pdsch_config->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->dmrs_AdditionalPosition=calloc(1,sizeof(*pdsch_config->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->dmrs_AdditionalPosition)); + fapi_nr_dl_config_dlsch_pdu_rel15_t *dlsch_config_pdu_1_1 = &dl_config->dl_config_list[dl_config->number_pdus].dlsch_config_pdu.dlsch_config_rel15; + + dlsch_config_pdu_1_1->BWPSize = NRRIV2BW(mac->DLbwp[0]->bwp_Common->genericParameters.locationAndBandwidth, MAX_BWP_SIZE); + dlsch_config_pdu_1_1->BWPStart = NRRIV2PRBOFFSET(mac->DLbwp[0]->bwp_Common->genericParameters.locationAndBandwidth, MAX_BWP_SIZE); + dlsch_config_pdu_1_1->SubcarrierSpacing = mac->DLbwp[0]->bwp_Common->genericParameters.subcarrierSpacing; + /* IDENTIFIER_DCI_FORMATS */ /* CARRIER_IND */ /* BANDWIDTH_PART_IND */ @@ -1010,6 +1019,7 @@ int8_t nr_ue_process_dci(module_id_t module_id, int cc_id, uint8_t gNB_index, fr &dlsch_config_pdu_1_1->PTRSReOffset, dlsch_config_pdu_1_1->number_symbols); if(valid_ptrs_setup==true) { dlsch_config_pdu_1_1->pduBitmap |= 0x1; + LOG_D(MAC, "DL PTRS values: PTRS time den: %d, PTRS freq den: %d\n", dlsch_config_pdu_1_1->PTRSTimeDensity, dlsch_config_pdu_1_1->PTRSFreqDensity); } } @@ -2230,7 +2240,7 @@ int nr_ue_process_rar(nr_downlink_indication_t *dl_info, NR_UL_TIME_ALIGNMENT_t // TA command ul_time_alignment->apply_ta = 1; - ul_time_alignment->ta_command = rar->TA2 + (rar->TA1 << 5); + ul_time_alignment->ta_command = 31 + rar->TA2 + (rar->TA1 << 5); #ifdef DEBUG_RAR // CSI diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c index d6e1cba6df..ad1958ef33 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c @@ -118,13 +118,14 @@ long get_k2(NR_UE_MAC_INST_t *mac, uint8_t time_domain_ind) { * This function returns the UL config corresponding to a given UL slot * from MAC instance . */ -fapi_nr_ul_config_request_t *get_ul_config_request(NR_UE_MAC_INST_t *mac, int slot) { +fapi_nr_ul_config_request_t *get_ul_config_request(NR_UE_MAC_INST_t *mac, int slot) +{ //Check if request to access ul_config is for a UL slot - if (is_nr_UL_slot(mac->scc, slot) == 0) { + if (is_nr_UL_slot(mac->scc, slot, mac->frame_type) == 0) { LOG_W(MAC, "Slot %d is not a UL slot. %s called for wrong slot!!!\n", slot, __FUNCTION__); return NULL; } - + // Calculate the index of the UL slot in mac->ul_config_request list. This is // based on the TDD pattern (slot configuration period) and number of UL+mixed // slots in the period. TS 38.213 Sec 11.1 @@ -560,20 +561,11 @@ int nr_config_pusch_pdu(NR_UE_MAC_INST_t *mac, } else if (dci) { int target_ss; - uint8_t ptrs_time_density; - uint8_t ptrs_freq_density; - nfapi_nr_ue_ptrs_ports_t ptrs_ports_list; + bool valid_ptrs_setup = 0; uint16_t n_RB_ULBWP = NRRIV2BW(mac->ULbwp[0]->bwp_Common->genericParameters.locationAndBandwidth, MAX_BWP_SIZE); fapi_nr_pusch_config_dedicated_t *pusch_config_dedicated = &mac->phy_config.config_req.ul_bwp_dedicated.pusch_config_dedicated; NR_PUSCH_Config_t *pusch_Config = mac->ULbwp[0]->bwp_Dedicated->pusch_Config->choice.setup; - // These should come from RRC config!!! - uint8_t ptrs_mcs1 = 2; - uint8_t ptrs_mcs2 = 4; - uint8_t ptrs_mcs3 = 10; - uint16_t n_rb0 = 25; - uint16_t n_rb1 = 75; - // Basic sanity check for MCS value to check for a false or erroneous DCI if (dci->mcs > 28) { LOG_W(MAC, "MCS value %d out of bounds! Possibly due to false DCI. Ignoring DCI!\n", dci->mcs); @@ -689,12 +681,6 @@ int nr_config_pusch_pdu(NR_UE_MAC_INST_t *mac, pusch_config_pdu->absolute_delta_PUSCH = 4; } - ptrs_time_density = get_L_ptrs(ptrs_mcs1, ptrs_mcs2, ptrs_mcs3, pusch_config_pdu->mcs_index, pusch_config_pdu->mcs_table); - ptrs_freq_density = get_K_ptrs(n_rb0, n_rb1, pusch_config_pdu->rb_size); - // PTRS ports configuration - // TbD: ptrs_dmrs_port and ptrs_port_index are not initialised! - ptrs_ports_list.ptrs_re_offset = 0; - /* DMRS */ l_prime_mask = get_l_prime(pusch_config_pdu->nr_of_symbols, typeB, pusch_dmrs_pos0, pusch_len1); if (pusch_config_pdu->transform_precoding == transform_precoder_disabled) @@ -708,12 +694,20 @@ int nr_config_pusch_pdu(NR_UE_MAC_INST_t *mac, } /* PTRS */ - pusch_config_pdu->pusch_ptrs.ptrs_time_density = ptrs_time_density; - pusch_config_pdu->pusch_ptrs.ptrs_freq_density = ptrs_freq_density; - pusch_config_pdu->pusch_ptrs.ptrs_ports_list = &ptrs_ports_list; - - if (1 << pusch_config_pdu->pusch_ptrs.ptrs_time_density >= pusch_config_pdu->nr_of_symbols) { - pusch_config_pdu->pdu_bit_map &= ~PUSCH_PDU_BITMAP_PUSCH_PTRS; // disable PUSCH PTRS + if (mac->ULbwp[0]->bwp_Dedicated->pusch_Config->choice.setup->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup->phaseTrackingRS != NULL) { + if (pusch_config_pdu->transform_precoding == transform_precoder_disabled) { + nfapi_nr_ue_ptrs_ports_t ptrs_ports_list; + pusch_config_pdu->pusch_ptrs.ptrs_ports_list = &ptrs_ports_list; + valid_ptrs_setup = set_ul_ptrs_values(mac->ULbwp[0]->bwp_Dedicated->pusch_Config->choice.setup->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup->phaseTrackingRS->choice.setup, + pusch_config_pdu->rb_size, pusch_config_pdu->mcs_index, pusch_config_pdu->mcs_table, + &pusch_config_pdu->pusch_ptrs.ptrs_freq_density,&pusch_config_pdu->pusch_ptrs.ptrs_time_density, + &pusch_config_pdu->pusch_ptrs.ptrs_ports_list->ptrs_re_offset,&pusch_config_pdu->pusch_ptrs.num_ptrs_ports, + &pusch_config_pdu->pusch_ptrs.ul_ptrs_power, pusch_config_pdu->nr_of_symbols); + if(valid_ptrs_setup==true) { + pusch_config_pdu->pdu_bit_map |= PUSCH_PDU_BITMAP_PUSCH_PTRS; + } + LOG_D(MAC, "UL PTRS values: PTRS time den: %d, PTRS freq den: %d\n", pusch_config_pdu->pusch_ptrs.ptrs_time_density, pusch_config_pdu->pusch_ptrs.ptrs_freq_density); + } } } @@ -889,34 +883,40 @@ NR_UE_L2_STATE_t nr_ue_scheduler(nr_downlink_indication_t *dl_info, nr_uplink_in uint16_t TBS_bytes = ulcfg_pdu->pusch_config_pdu.pusch_data.tb_size; - // Push data from MAC to PHY only when NDI toggles - if (IS_SOFTMODEM_NOS1 && (mac->UL_ndi[ulcfg_pdu->pusch_config_pdu.pusch_data.harq_process_id] != ulcfg_pdu->pusch_config_pdu.pusch_data.new_data_indicator)){ - // Getting IP traffic to be transmitted - data_existing = nr_ue_get_sdu(mod_id, - cc_id, - frame_tx, - slot_tx, - 0, - ulsch_input_buffer, - TBS_bytes, - &access_mode); - } + if (ra->ra_state == WAIT_RAR){ + memcpy(ulsch_input_buffer, mac->ulsch_pdu.payload, TBS_bytes); + LOG_D(NR_MAC,"[RAPROC] Msg3 to be transmitted:\n"); + for (int k = 0; k < TBS_bytes; k++) { + LOG_D(NR_MAC,"(%i): 0x%x\n",k,mac->ulsch_pdu.payload[k]); + } + } else { + if (IS_SOFTMODEM_NOS1 && (mac->UL_ndi[ulcfg_pdu->pusch_config_pdu.pusch_data.harq_process_id] != ulcfg_pdu->pusch_config_pdu.pusch_data.new_data_indicator)){ + // Getting IP traffic to be transmitted + data_existing = nr_ue_get_sdu(mod_id, + cc_id, + frame_tx, + slot_tx, + 0, + ulsch_input_buffer, + TBS_bytes, + &access_mode); + } - mac->UL_ndi[ulcfg_pdu->pusch_config_pdu.pusch_data.harq_process_id] = ulcfg_pdu->pusch_config_pdu.pusch_data.new_data_indicator; - //Random traffic to be transmitted if there is no IP traffic available for this Tx opportunity - if (!IS_SOFTMODEM_NOS1 || !data_existing) { - //Use zeros for the header bytes in noS1 mode, in order to make sure that the LCID is not valid - //and block this traffic from being forwarded to the upper layers at the gNB - LOG_D(PHY, "In %s: Random data to be transmitted: TBS_bytes %d \n", __FUNCTION__, TBS_bytes); + mac->UL_ndi[ulcfg_pdu->pusch_config_pdu.pusch_data.harq_process_id] = ulcfg_pdu->pusch_config_pdu.pusch_data.new_data_indicator; + //Random traffic to be transmitted if there is no IP traffic available for this Tx opportunity + if (!IS_SOFTMODEM_NOS1 || !data_existing) { + //Use zeros for the header bytes in noS1 mode, in order to make sure that the LCID is not valid + //and block this traffic from being forwarded to the upper layers at the gNB + LOG_D(PHY, "In %s: Random data to be transmitted: TBS_bytes %d \n", __FUNCTION__, TBS_bytes); - //Give the first byte a dummy value (a value not corresponding to any valid LCID based on 38.321, Table 6.2.1-2) - //in order to distinguish the PHY random packets at the MAC layer of the gNB receiver from the normal packets that should - //have a valid LCID (nr_process_mac_pdu function) - ulsch_input_buffer[0] = 0x31; + //Give the first byte a dummy value (a value not corresponding to any valid LCID based on 38.321, Table 6.2.1-2) + //in order to distinguish the PHY random packets at the MAC layer of the gNB receiver from the normal packets that should + //have a valid LCID (nr_process_mac_pdu function) + ulsch_input_buffer[0] = 0x31; - for (int i = 1; i < TBS_bytes; i++) { - ulsch_input_buffer[i] = (unsigned char) rand(); - //printf(" input encoder a[%d]=0x%02x\n",i,harq_process_ul_ue->a[i]); + for (int i = 1; i < TBS_bytes; i++) { + ulsch_input_buffer[i] = (unsigned char) rand(); + } } } @@ -1662,7 +1662,7 @@ void nr_ue_prach_scheduler(module_id_t module_idP, frame_t frameP, sub_frame_t s ra->RA_offset = 2; // to compensate the rx frame offset at the gNB ra->generate_nr_prach = 0; // Reset flag for PRACH generation - if (is_nr_UL_slot(scc, slotP)) { + if (is_nr_UL_slot(scc, slotP, mac->frame_type)) { // WIP Need to get the proper selected ssb_idx // Initial beam selection functionality is not available yet @@ -1683,13 +1683,11 @@ void nr_ue_prach_scheduler(module_id_t module_idP, frame_t frameP, sub_frame_t s format0 = format & 0xff; // single PRACH format format1 = (format >> 8) & 0xff; // dual PRACH format - ul_config->sfn = frameP; - ul_config->slot = slotP; - - ul_config->ul_config_list[ul_config->number_pdus].pdu_type = FAPI_NR_UL_CONFIG_TYPE_PRACH; prach_config_pdu = &ul_config->ul_config_list[ul_config->number_pdus].prach_config_pdu; memset(prach_config_pdu, 0, sizeof(fapi_nr_ul_config_prach_pdu)); - ul_config->number_pdus += 1; + + fill_ul_config(ul_config, frameP, slotP, FAPI_NR_UL_CONFIG_TYPE_PRACH); + LOG_D(PHY, "In %s: (%p) %d UL PDUs:\n", __FUNCTION__, ul_config, ul_config->number_pdus); ncs = get_NCS(rach_ConfigGeneric->zeroCorrelationZoneConfig, format0, setup->restrictedSetConfig); @@ -1767,11 +1765,10 @@ void nr_ue_prach_scheduler(module_id_t module_idP, frame_t frameP, sub_frame_t s AssertFatal(1 == 0, "Invalid PRACH format"); } } // if format1 + fill_scheduled_response(&scheduled_response, NULL, ul_config, NULL, module_idP, 0 /*TBR fix*/, frameP, slotP, thread_id); + if(mac->if_module != NULL && mac->if_module->scheduled_response != NULL) + mac->if_module->scheduled_response(&scheduled_response); } // is_nr_prach_slot - - fill_scheduled_response(&scheduled_response, NULL, ul_config, NULL, module_idP, 0 /*TBR fix*/, frameP, slotP, thread_id); - if(mac->if_module != NULL && mac->if_module->scheduled_response != NULL) - mac->if_module->scheduled_response(&scheduled_response); } // if is_nr_UL_slot } diff --git a/openair2/LAYER2/NR_MAC_gNB/config.c b/openair2/LAYER2/NR_MAC_gNB/config.c index bce0719556..39bad35af7 100644 --- a/openair2/LAYER2/NR_MAC_gNB/config.c +++ b/openair2/LAYER2/NR_MAC_gNB/config.c @@ -127,8 +127,7 @@ void config_common(int Mod_idP, int pdsch_AntennaPorts, NR_ServingCellConfigComm uint32_t band = *scc->downlinkConfigCommon->frequencyInfoDL->frequencyBandList.list.array[0]; frequency_range_t frequency_range = band<100?FR1:FR2; - lte_frame_type_t frame_type; - get_frame_type(*scc->downlinkConfigCommon->frequencyInfoDL->frequencyBandList.list.array[0], *scc->ssbSubcarrierSpacing, &frame_type); + lte_frame_type_t frame_type = get_frame_type(*scc->downlinkConfigCommon->frequencyInfoDL->frequencyBandList.list.array[0], *scc->ssbSubcarrierSpacing); RC.nrmac[Mod_idP]->common_channels[0].frame_type = frame_type; // Cell configuration @@ -311,8 +310,6 @@ void config_common(int Mod_idP, int pdsch_AntennaPorts, NR_ServingCellConfigComm } - - extern uint16_t sl_ahead; int rrc_mac_config_req_gNB(module_id_t Mod_idP, int ssb_SubcarrierOffset, diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c index 4ada9eb9f3..de9c64cd46 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c @@ -66,11 +66,15 @@ void dump_mac_stats(gNB_MAC_INST *gNB) int num = 1; for (int UE_id = UE_info->list.head; UE_id >= 0; UE_id = UE_info->list.next[UE_id]) { LOG_I(MAC, "UE ID %d RNTI %04x (%d/%d)\n", UE_id, UE_info->rnti[UE_id], num++, UE_info->num_UEs); - const NR_mac_stats_t *stats = &UE_info->mac_stats[UE_id]; - LOG_I(MAC, "UE %d: dlsch_rounds %d/%d/%d/%d, dlsch_errors %d\n", + NR_mac_stats_t *stats = &UE_info->mac_stats[UE_id]; + const int avg_rsrp = stats->num_rsrp_meas > 0 ? stats->cumul_rsrp / stats->num_rsrp_meas : 0; + LOG_I(MAC, "UE %d: dlsch_rounds %d/%d/%d/%d, dlsch_errors %d, average RSRP %d (%d meas)\n", UE_id, stats->dlsch_rounds[0], stats->dlsch_rounds[1], - stats->dlsch_rounds[2], stats->dlsch_rounds[3], stats->dlsch_errors); + stats->dlsch_rounds[2], stats->dlsch_rounds[3], stats->dlsch_errors, + avg_rsrp, stats->num_rsrp_meas); + stats->num_rsrp_meas = 0; + stats->cumul_rsrp = 0 ; LOG_I(MAC, "UE %d: dlsch_total_bytes %d\n", UE_id, stats->dlsch_total_bytes); LOG_I(MAC, "UE %d: ulsch_rounds %d/%d/%d/%d, ulsch_errors %d\n", UE_id, @@ -365,7 +369,9 @@ void gNB_dlsch_ulsch_scheduler(module_id_t module_idP, /* send tick to RLC and RRC every ms */ if ((slot & ((1 << *scc->ssbSubcarrierSpacing) - 1)) == 0) { void nr_rlc_tick(int frame, int subframe); + void nr_pdcp_tick(int frame, int subframe); nr_rlc_tick(frame, slot >> *scc->ssbSubcarrierSpacing); + nr_pdcp_tick(frame, slot >> *scc->ssbSubcarrierSpacing); nr_rrc_trigger(&ctxt, 0 /*CC_id*/, frame, slot >> *scc->ssbSubcarrierSpacing); } diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c index ac3a4e77d2..64867c5be5 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c @@ -245,7 +245,8 @@ void schedule_nr_prach(module_id_t module_idP, frame_t frameP, sub_frame_t slotP nfapi_nr_ul_tti_request_t *UL_tti_req = &RC.nrmac[module_idP]->UL_tti_req_ahead[0][slotP]; nfapi_nr_config_request_scf_t *cfg = &RC.nrmac[module_idP]->config[0]; - if (is_nr_UL_slot(scc,slotP)) { + if (is_nr_UL_slot(scc, slotP, cc->frame_type)) { + uint8_t config_index = scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->rach_ConfigGeneric.prach_ConfigurationIndex; uint8_t mu,N_dur,N_t_slot,start_symbol = 0,N_RA_slot; uint16_t RA_sfn_index = -1; @@ -647,7 +648,8 @@ void nr_get_Msg3alloc(module_id_t module_id, NR_RA_t *ra) { // msg3 is schedulend in mixed slot in the following TDD period - // for now we consider a TBS of 18 bytes + + uint16_t msg3_nb_rb = 8 + sizeof(NR_MAC_SUBHEADER_SHORT) + sizeof(NR_MAC_SUBHEADER_SHORT); // sdu has 6 or 8 bytes int mu = ubwp->bwp_Common->genericParameters.subcarrierSpacing; int StartSymbolIndex, NrOfSymbols, startSymbolAndLength, temp_slot; @@ -677,21 +679,22 @@ void nr_get_Msg3alloc(module_id_t module_id, uint16_t *vrb_map_UL = &RC.nrmac[module_id]->common_channels[CC_id].vrb_map_UL[ra->Msg3_slot * MAX_BWP_SIZE]; const uint16_t bwpSize = NRRIV2BW(ubwp->bwp_Common->genericParameters.locationAndBandwidth, MAX_BWP_SIZE); - /* search 18 free RBs */ + + /* search msg3_nb_rb free RBs */ int rbSize = 0; int rbStart = 0; - while (rbSize < 18) { + while (rbSize < msg3_nb_rb) { rbStart += rbSize; /* last iteration rbSize was not enough, skip it */ rbSize = 0; while (rbStart < bwpSize && vrb_map_UL[rbStart]) rbStart++; - AssertFatal(rbStart < bwpSize - 18, "no space to allocate Msg 3 for RA!\n"); + AssertFatal(rbStart < bwpSize - msg3_nb_rb, "no space to allocate Msg 3 for RA!\n"); while (rbStart + rbSize < bwpSize && !vrb_map_UL[rbStart + rbSize] - && rbSize < 18) + && rbSize < msg3_nb_rb) rbSize++; } - ra->msg3_nb_rb = 18; + ra->msg3_nb_rb = msg3_nb_rb; ra->msg3_first_rb = rbStart; } diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c index 1de46aaea4..3f69cfbe74 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c @@ -235,6 +235,7 @@ void schedule_control_sib1(module_id_t module_id, int time_domain_allocation, uint8_t mcsTableIdx, uint8_t mcs, + uint8_t candidate_idx, int num_total_bytes) { gNB_MAC_INST *gNB_mac = RC.nrmac[module_id]; @@ -266,13 +267,10 @@ void schedule_control_sib1(module_id_t module_id, gNB_mac->sched_ctrlCommon->coreset, gNB_mac->sched_ctrlCommon->aggregation_level, 0, - 0, + candidate_idx, nr_of_candidates); - if (gNB_mac->sched_ctrlCommon->cce_index < 0) { - LOG_E(MAC, "%s(): could not find CCE for coreset0\n", __func__); - return; - } + AssertFatal(gNB_mac->sched_ctrlCommon->cce_index >= 0, "Could not find CCE for coreset0\n"); const uint16_t bwpSize = gNB_mac->type0_PDCCH_CSS_config.num_rbs; int rbStart = gNB_mac->type0_PDCCH_CSS_config.cset_start_rb; @@ -301,9 +299,7 @@ void schedule_control_sib1(module_id_t module_id, TBS = nr_compute_tbs(nr_get_Qm_dl(gNB_mac->sched_ctrlCommon->mcs, gNB_mac->sched_ctrlCommon->mcsTableIdx), nr_get_code_rate_dl(gNB_mac->sched_ctrlCommon->mcs, gNB_mac->sched_ctrlCommon->mcsTableIdx), rbSize, nrOfSymbols, N_PRB_DMRS * dmrs_length,0, 0,1) >> 3; - - // FIXME: Something is not working in nr_modulation() for TBS = 84, so we need to skip it - } while ( (rbStart + rbSize < bwpSize && !vrb_map[rbStart + rbSize] && TBS < gNB_mac->sched_ctrlCommon->num_total_bytes) || (TBS==84) ); + } while (rbStart + rbSize < bwpSize && !vrb_map[rbStart + rbSize] && TBS < gNB_mac->sched_ctrlCommon->num_total_bytes); gNB_mac->sched_ctrlCommon->rbSize = rbSize; gNB_mac->sched_ctrlCommon->rbStart = 0; @@ -467,6 +463,7 @@ void schedule_nr_sib1(module_id_t module_idP, frame_t frameP, sub_frame_t slotP) int time_domain_allocation = 0; uint8_t mcsTableIdx = 0; uint8_t mcs = 6; + uint8_t candidate_idx = 0; gNB_MAC_INST *gNB_mac = RC.nrmac[module_idP]; @@ -482,7 +479,7 @@ void schedule_nr_sib1(module_id_t module_idP, frame_t frameP, sub_frame_t slotP) for (int i=0;iphy_test || get_softmodem_params()->do_ra) { + else if (get_softmodem_params()->phy_test || get_softmodem_params()->do_ra || get_softmodem_params()->sa) { /* we will need the large header, phy-test typically allocates all * resources and fills to the last byte below */ NR_MAC_SUBHEADER_LONG *header = (NR_MAC_SUBHEADER_LONG *) buf; diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c index 00e53dd21e..37cafff9cc 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c @@ -647,6 +647,7 @@ void nr_configure_pucch(nfapi_nr_pucch_pdu_t* pucch_pdu, int res_found = 0; pucch_pdu->bit_len_harq = O_ack; + pucch_pdu->bit_len_csi_part1 = O_csi; uint16_t O_uci = O_csi + O_ack; @@ -699,6 +700,8 @@ void nr_configure_pucch(nfapi_nr_pucch_pdu_t* pucch_pdu, n_set = pucch_Config->resourceSetToAddModList->list.count; AssertFatal(n_set>0,"PUCCH resourceSetToAddModList is empty\n"); + LOG_D(MAC, "UCI n_set= %d\n", n_set); + N2 = 2; // procedure to select pucch resource id from resource sets according to // number of uci bits and pucch resource indicator pucch_resource @@ -1642,7 +1645,7 @@ int add_new_nr_ue(module_id_t mod_idP, rnti_t rntiP, NR_CellGroupConfig_t *secon add_nr_list(&UE_info->list, UE_id); memset(&UE_info->mac_stats[UE_id], 0, sizeof(NR_mac_stats_t)); set_Y(UE_info->Y[UE_id], rntiP); - compute_csi_bitlen(secondaryCellGroup, UE_info, UE_id); + compute_csi_bitlen (secondaryCellGroup->spCellConfig->spCellConfigDedicated->csi_MeasConfig->choice.setup, UE_info, UE_id, mod_idP); NR_UE_sched_ctrl_t *sched_ctrl = &UE_info->UE_sched_ctrl[UE_id]; memset(sched_ctrl, 0, sizeof(*sched_ctrl)); sched_ctrl->ta_frame = 0; diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c index 3ae3707962..a6f7105769 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c @@ -80,6 +80,42 @@ void nr_fill_nfapi_pucch(module_id_t mod_id, pucch->sr_flag); } +#define MIN_RSRP_VALUE -141 +#define MAX_NUM_SSB 128 +#define MAX_SSB_SCHED 8 +#define L1_RSRP_HYSTERIS 10 //considering 10 dBm as hysterisis for avoiding frequent SSB Beam Switching. !Fixme provide exact value if any +//#define L1_DIFF_RSRP_STEP_SIZE 2 + +int ssb_index_sorted[MAX_NUM_SSB] = {0}; +int ssb_rsrp_sorted[MAX_NUM_SSB] = {0}; + +//Measured RSRP Values Table 10.1.16.1-1 from 36.133 +//Stored all the upper limits[Max RSRP Value of corresponding index] +//stored -1 for invalid values +int L1_SSB_CSI_RSRP_measReport_mapping_38133_10_1_6_1_1[128] = { + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, //0 - 9 + -1, -1, -1, -1, -1, -1, -140, -139, -138, -137, //10 - 19 + -136, -135, -134, -133, -132, -131, -130, -129, -128, -127, //20 - 29 + -126, -125, -124, -123, -122, -121, -120, -119, -118, -117, //30 - 39 + -116, -115, -114, -113, -112, -111, -110, -109, -108, -107, //40 - 49 + -106, -105, -104, -103, -102, -101, -100, -99, -98, -97, //50 - 59 + -96, -95, -94, -93, -92, -91, -90, -89, -88, -87, //60 - 69 + -86, -85, -84, -83, -82, -81, -80, -79, -78, -77, //70 - 79 + -76, -75, -74, -73, -72, -71, -70, -69, -68, -67, //80 - 89 + -66, -65, -64, -63, -62, -61, -60, -59, -58, -57, //90 - 99 + -56, -55, -54, -53, -52, -51, -50, -49, -48, -47, //100 - 109 + -46, -45, -44, -44, -1, -1, -1, -1, -1, -1, //110 - 119 + -1, -1, -1, -1, -1, -1, -1, -1//120 - 127 + }; + +//Differential RSRP values Table 10.1.6.1-2 from 36.133 +//Stored the upper limits[MAX RSRP Value] +int diff_rsrp_ssb_csi_meas_10_1_6_1_2[16] = { + 0, -2, -4, -6, -8, -10, -12, -14, -16, -18, //0 - 9 + -20, -22, -24, -26, -28, -30 //10 - 15 +}; + + void nr_schedule_pucch(int Mod_idP, frame_t frameP, sub_frame_t slotP) { @@ -106,74 +142,293 @@ void nr_schedule_pucch(int Mod_idP, } +//! Calculating number of bits set +uint8_t number_of_bits_set (uint8_t buf,uint8_t * max_ri){ + uint8_t nb_of_bits_set = 0; + uint8_t mask = 0xff; + uint8_t index = 0; + + for (index=7; (buf & mask) && (index>=0) ; index--){ + if (buf & (1<>=1; + } + *max_ri = 8-index; + return nb_of_bits_set; +} + + //!TODO : same function can be written to handle csi_resources -void compute_csi_bitlen (NR_CellGroupConfig_t *secondaryCellGroup, NR_UE_info_t *UE_info, int UE_id) { +void compute_csi_bitlen(NR_CSI_MeasConfig_t *csi_MeasConfig, NR_UE_info_t *UE_info, int UE_id, module_id_t Mod_idP){ uint8_t csi_report_id = 0; uint8_t csi_resourceidx =0; uint8_t csi_ssb_idx =0; - - NR_CSI_MeasConfig_t *csi_MeasConfig = secondaryCellGroup->spCellConfig->spCellConfigDedicated->csi_MeasConfig->choice.setup; + NR_CSI_ReportConfig__reportQuantity_PR reportQuantity_type; NR_CSI_ResourceConfigId_t csi_ResourceConfigId; + for (csi_report_id=0; csi_report_id < csi_MeasConfig->csi_ReportConfigToAddModList->list.count; csi_report_id++){ - csi_ResourceConfigId=csi_MeasConfig->csi_ReportConfigToAddModList->list.array[csi_report_id]->resourcesForChannelMeasurement; - UE_info->csi_report_template[UE_id][csi_report_id].reportQuantity_type = csi_MeasConfig->csi_ReportConfigToAddModList->list.array[csi_report_id]->reportQuantity.present; + struct NR_CSI_ReportConfig *csi_reportconfig = csi_MeasConfig->csi_ReportConfigToAddModList->list.array[csi_report_id]; + nr_csi_report_t *csi_report = &UE_info->csi_report_template[UE_id][csi_report_id]; + csi_ResourceConfigId=csi_reportconfig->resourcesForChannelMeasurement; + reportQuantity_type = csi_reportconfig->reportQuantity.present; + csi_report->reportQuantity_type = reportQuantity_type; for ( csi_resourceidx = 0; csi_resourceidx < csi_MeasConfig->csi_ResourceConfigToAddModList->list.count; csi_resourceidx++) { - if ( csi_MeasConfig->csi_ResourceConfigToAddModList->list.array[csi_resourceidx]->csi_ResourceConfigId != csi_ResourceConfigId) - continue; + struct NR_CSI_ResourceConfig *csi_resourceconfig = csi_MeasConfig->csi_ResourceConfigToAddModList->list.array[csi_resourceidx]; + if ( csi_resourceconfig->csi_ResourceConfigId != csi_ResourceConfigId) + continue; else { - //Finding the CSI_RS or SSB Resources - UE_info->csi_report_template[UE_id][csi_report_id].CSI_Resource_type= csi_MeasConfig->csi_ResourceConfigToAddModList->list.array[csi_resourceidx]->csi_RS_ResourceSetList.present; - if (NR_CSI_ResourceConfig__csi_RS_ResourceSetList_PR_nzp_CSI_RS_SSB ==UE_info->csi_report_template[UE_id][csi_report_id].CSI_Resource_type){ - struct NR_CSI_ResourceConfig__csi_RS_ResourceSetList__nzp_CSI_RS_SSB * nzp_CSI_RS_SSB = csi_MeasConfig->csi_ResourceConfigToAddModList->list.array[csi_resourceidx]->csi_RS_ResourceSetList.choice.nzp_CSI_RS_SSB; + uint8_t nb_ssb_resources =0; + //Finding the CSI_RS or SSB Resources + if (NR_CSI_ReportConfig__reportQuantity_PR_cri_RSRP == reportQuantity_type || + NR_CSI_ReportConfig__reportQuantity_PR_ssb_Index_RSRP == reportQuantity_type) { - UE_info->csi_report_template[UE_id][csi_report_id].nb_of_nzp_csi_report = nzp_CSI_RS_SSB->nzp_CSI_RS_ResourceSetList!=NULL ? nzp_CSI_RS_SSB->nzp_CSI_RS_ResourceSetList->list.count:0; - UE_info->csi_report_template[UE_id][csi_report_id].nb_of_csi_ssb_report = nzp_CSI_RS_SSB->csi_SSB_ResourceSetList!=NULL ? nzp_CSI_RS_SSB->csi_SSB_ResourceSetList->list.count:0; + if (NR_CSI_ReportConfig__groupBasedBeamReporting_PR_disabled == csi_reportconfig->groupBasedBeamReporting.present) { + if (NULL != csi_reportconfig->groupBasedBeamReporting.choice.disabled->nrofReportedRS) + csi_report->CSI_report_bitlen.nb_ssbri_cri = *(csi_reportconfig->groupBasedBeamReporting.choice.disabled->nrofReportedRS)+1; + else + /*! From Spec 38.331 + * nrofReportedRS + * The number (N) of measured RS resources to be reported per report setting in a non-group-based report. N <= N_max, where N_max is either 2 or 4 depending on UE + * capability. FFS: The signaling mechanism for the gNB to select a subset of N beams for the UE to measure and report. + * When the field is absent the UE applies the value 1 + */ + csi_report->CSI_report_bitlen.nb_ssbri_cri= 1; + }else + csi_report->CSI_report_bitlen.nb_ssbri_cri= 2; + + if (NR_CSI_ReportConfig__reportQuantity_PR_ssb_Index_RSRP == csi_report->reportQuantity_type) { + for ( csi_ssb_idx = 0; csi_ssb_idx < csi_MeasConfig->csi_SSB_ResourceSetToAddModList->list.count; csi_ssb_idx++) { + if (csi_MeasConfig->csi_SSB_ResourceSetToAddModList->list.array[csi_ssb_idx]->csi_SSB_ResourceSetId == + *(csi_resourceconfig->csi_RS_ResourceSetList.choice.nzp_CSI_RS_SSB->csi_SSB_ResourceSetList->list.array[0])){ + + ///We can configure only one SSB resource set from spec 38.331 IE CSI-ResourceConfig + nb_ssb_resources= csi_MeasConfig->csi_SSB_ResourceSetToAddModList->list.array[csi_ssb_idx]->csi_SSB_ResourceList.list.count; + csi_report->SSB_Index_list = csi_MeasConfig->csi_SSB_ResourceSetToAddModList->list.array[csi_ssb_idx]->csi_SSB_ResourceList.list.array; + csi_report->CSI_Index_list = NULL; + break; + } + } + } else /*if (NR_CSI_ReportConfig__reportQuantity_PR_cri_RSRP == UE_info->csi_report_template[UE_id][csi_report_id].reportQuantity_type)*/{ + for ( csi_ssb_idx = 0; csi_ssb_idx < csi_MeasConfig->nzp_CSI_RS_ResourceSetToAddModList->list.count; csi_ssb_idx++) { + if (csi_MeasConfig->nzp_CSI_RS_ResourceSetToAddModList->list.array[csi_ssb_idx]->nzp_CSI_ResourceSetId == + *(csi_resourceconfig->csi_RS_ResourceSetList.choice.nzp_CSI_RS_SSB->nzp_CSI_RS_ResourceSetList->list.array[0])) { + + ///For periodic and semi-persistent CSI Resource Settings, the number of CSI-RS Resource Sets configured is limited to S=1 for spec 38.212 + nb_ssb_resources= csi_MeasConfig->nzp_CSI_RS_ResourceSetToAddModList->list.array[csi_ssb_idx]->nzp_CSI_RS_Resources.list.count; + csi_report->CSI_Index_list = csi_MeasConfig->nzp_CSI_RS_ResourceSetToAddModList->list.array[csi_ssb_idx]->nzp_CSI_RS_Resources.list.array; + csi_report->SSB_Index_list = NULL; + break; + } + } + } + + if (nb_ssb_resources) { + csi_report->CSI_report_bitlen.cri_ssbri_bitlen =ceil(log2 (nb_ssb_resources)); + csi_report->CSI_report_bitlen.rsrp_bitlen = 7; //From spec 38.212 Table 6.3.1.1.2-6: CRI, SSBRI, and RSRP + csi_report->CSI_report_bitlen.diff_rsrp_bitlen =4; //From spec 38.212 Table 6.3.1.1.2-6: CRI, SSBRI, and RSRP + } else { + csi_report->CSI_report_bitlen.cri_ssbri_bitlen =0; + csi_report->CSI_report_bitlen.rsrp_bitlen = 0; + csi_report->CSI_report_bitlen.diff_rsrp_bitlen =0; + } + + LOG_I (MAC, "UCI: CSI_bit len : ssbri %d, rsrp: %d, diff_rsrp: %d\n", + csi_report->CSI_report_bitlen.cri_ssbri_bitlen, + csi_report->CSI_report_bitlen.rsrp_bitlen, + csi_report->CSI_report_bitlen.diff_rsrp_bitlen); } - if (0 != UE_info->csi_report_template[UE_id][csi_report_id].nb_of_csi_ssb_report){ - uint8_t nb_ssb_resources =0; + uint8_t ri_restriction; + uint8_t ri_bitlen; + uint8_t nb_allowed_ri; + uint8_t max_ri; + + if (NR_CSI_ReportConfig__reportQuantity_PR_cri_RI_PMI_CQI == reportQuantity_type || + NR_CSI_ReportConfig__reportQuantity_PR_cri_RI_LI_PMI_CQI==reportQuantity_type || + NR_CSI_ReportConfig__reportQuantity_PR_cri_RI_CQI==reportQuantity_type || + NR_CSI_ReportConfig__reportQuantity_PR_cri_RI_i1_CQI==reportQuantity_type|| + NR_CSI_ReportConfig__reportQuantity_PR_cri_RI_i1==reportQuantity_type){ + for ( csi_ssb_idx = 0; csi_ssb_idx < csi_MeasConfig->csi_SSB_ResourceSetToAddModList->list.count; csi_ssb_idx++) { - if (csi_MeasConfig->csi_SSB_ResourceSetToAddModList->list.array[csi_ssb_idx]->csi_SSB_ResourceSetId == - *(csi_MeasConfig->csi_ResourceConfigToAddModList->list.array[csi_resourceidx]->csi_RS_ResourceSetList.choice.nzp_CSI_RS_SSB->csi_SSB_ResourceSetList->list.array[0])) { - ///We can configure only one SSB resource set from spec 38.331 IE CSI-ResourceConfig - if (NR_CSI_ReportConfig__groupBasedBeamReporting_PR_disabled == - csi_MeasConfig->csi_ReportConfigToAddModList->list.array[csi_report_id]->groupBasedBeamReporting.present ) { - if (NULL != csi_MeasConfig->csi_ReportConfigToAddModList->list.array[csi_report_id]->groupBasedBeamReporting.choice.disabled->nrofReportedRS) - UE_info->csi_report_template[UE_id][csi_report_id].CSI_report_bitlen[0].nb_ssbri_cri = *(csi_MeasConfig->csi_ReportConfigToAddModList->list.array[csi_report_id]->groupBasedBeamReporting.choice.disabled->nrofReportedRS)+1; - else - /*! From Spec 38.331 - * nrofReportedRS - * The number (N) of measured RS resources to be reported per report setting in a non-group-based report. N <= N_max, where N_max is either 2 or 4 depending on UE - * capability. FFS: The signaling mechanism for the gNB to select a subset of N beams for the UE to measure and report. - * When the field is absent the UE applies the value 1 - */ - UE_info->csi_report_template[UE_id][csi_report_id].CSI_report_bitlen[0].nb_ssbri_cri= 1; - } else - UE_info->csi_report_template[UE_id][csi_report_id].CSI_report_bitlen[0].nb_ssbri_cri= 2; + if (csi_MeasConfig->nzp_CSI_RS_ResourceSetToAddModList->list.array[csi_ssb_idx]->nzp_CSI_ResourceSetId == + *(csi_resourceconfig->csi_RS_ResourceSetList.choice.nzp_CSI_RS_SSB->nzp_CSI_RS_ResourceSetList->list.array[0])) { + ///For periodic and semi-persistent CSI Resource Settings, the number of CSI-RS Resource Sets configured is limited to S=1 for spec 38.212 + nb_ssb_resources= csi_MeasConfig->nzp_CSI_RS_ResourceSetToAddModList->list.array[csi_ssb_idx]->nzp_CSI_RS_Resources.list.count; + csi_report->CSI_Index_list = csi_MeasConfig->nzp_CSI_RS_ResourceSetToAddModList->list.array[csi_ssb_idx]->nzp_CSI_RS_Resources.list.array; + csi_report->SSB_Index_list = NULL; + } + break; + } + csi_report->csi_meas_bitlen.cri_bitlen=ceil(log2 (nb_ssb_resources)); - nb_ssb_resources= csi_MeasConfig->csi_SSB_ResourceSetToAddModList->list.array[csi_ssb_idx]->csi_SSB_ResourceList.list.count; - if (nb_ssb_resources){ - UE_info->csi_report_template[UE_id][csi_report_id].CSI_report_bitlen[0].cri_ssbri_bitlen =ceil(log2 (nb_ssb_resources)); - UE_info->csi_report_template[UE_id][csi_report_id].CSI_report_bitlen[0].rsrp_bitlen = 7; //From spec 38.212 Table 6.3.1.1.2-6: CRI, SSBRI, and RSRP - UE_info->csi_report_template[UE_id][csi_report_id].CSI_report_bitlen[0].diff_rsrp_bitlen =4; //From spec 38.212 Table 6.3.1.1.2-6: CRI, SSBRI, and RSRP - } - else{ - UE_info->csi_report_template[UE_id][csi_report_id].CSI_report_bitlen[0].cri_ssbri_bitlen =0; - UE_info->csi_report_template[UE_id][csi_report_id].CSI_report_bitlen[0].rsrp_bitlen = 0; - UE_info->csi_report_template[UE_id][csi_report_id].CSI_report_bitlen[0].diff_rsrp_bitlen =0; - } + if (NR_CodebookConfig__codebookType__type1__subType_PR_typeI_SinglePanel==csi_reportconfig->codebookConfig->codebookType.choice.type1->subType.present){ - LOG_I (MAC, "UCI: CSI_bit len : ssbri %d, rsrp: %d, diff_rsrp: %d\n", - UE_info->csi_report_template[UE_id][csi_report_id].CSI_report_bitlen[0].cri_ssbri_bitlen, - UE_info->csi_report_template[UE_id][csi_report_id].CSI_report_bitlen[0].rsrp_bitlen, - UE_info->csi_report_template[UE_id][csi_report_id].CSI_report_bitlen[0].diff_rsrp_bitlen); - break ; + switch (RC.nrmac[Mod_idP]->config[0].carrier_config.num_tx_ant.value) { + case 1:; + csi_report->csi_meas_bitlen.ri_bitlen=0; + break; + case 2: + /* From Spec 38.212 + * If the higher layer parameter nrofCQIsPerReport=1, nRI in Table 6.3.1.1.2-3 is the number of allowed rank indicator + * values in the 4 LSBs of the higher layer parameter typeI-SinglePanel-ri-Restriction according to Subclause 5.2.2.2.1 [6, + * TS 38.214]; otherwise nRI in Table 6.3.1.1.2-3 is the number of allowed rank indicator values according to Subclause + * 5.2.2.2.1 [6, TS 38.214]. + * + * But from Current RRC ASN structures nrofCQIsPerReport is not present. Present a dummy variable is present so using it to + * calculate RI for antennas equal or more than two. + * */ + AssertFatal (NULL!=csi_reportconfig->dummy, "nrofCQIsPerReport is not present"); + + ri_restriction = csi_reportconfig->codebookConfig->codebookType.choice.type1->subType.choice.typeI_SinglePanel->typeI_SinglePanel_ri_Restriction.buf[0]; + + /* Replace dummy with the nrofCQIsPerReport from the CSIreport + config when equalent ASN structure present */ + if (0==*(csi_reportconfig->dummy)){ + nb_allowed_ri = number_of_bits_set((ri_restriction & 0xf0), &max_ri); + ri_bitlen = ceil(log2(nb_allowed_ri)); + } + else{ + nb_allowed_ri = number_of_bits_set(ri_restriction, &max_ri); + ri_bitlen = ceil(log2(nb_allowed_ri)); + } + ri_bitlen = ri_bitlen<1?ri_bitlen:1; //from the spec 38.212 and table 6.3.1.1.2-3: RI, LI, CQI, and CRI of codebookType=typeI-SinglePanel + csi_report->csi_meas_bitlen.ri_bitlen=ri_bitlen; + break; + case 4: + AssertFatal (NULL!=csi_reportconfig->dummy, "nrofCQIsPerReport is not present"); + + ri_restriction = csi_reportconfig->codebookConfig->codebookType.choice.type1->subType.choice.typeI_SinglePanel->typeI_SinglePanel_ri_Restriction.buf[0]; + + /* Replace dummy with the nrofCQIsPerReport from the CSIreport + config when equalent ASN structure present */ + if (0==*(csi_reportconfig->dummy)){ + nb_allowed_ri = number_of_bits_set((ri_restriction & 0xf0), &max_ri); + ri_bitlen = ceil(log2(nb_allowed_ri)); + } + else{ + nb_allowed_ri = number_of_bits_set(ri_restriction,&max_ri); + ri_bitlen = ceil(log2(nb_allowed_ri)); + } + ri_bitlen = ri_bitlen<2?ri_bitlen:2; //from the spec 38.212 and table 6.3.1.1.2-3: RI, LI, CQI, and CRI of codebookType=typeI-SinglePanel + csi_report->csi_meas_bitlen.ri_bitlen=ri_bitlen; + break; + case 6: + case 8: + AssertFatal (NULL!=csi_reportconfig->dummy, "nrofCQIsPerReport is not present"); + + ri_restriction = csi_reportconfig->codebookConfig->codebookType.choice.type1->subType.choice.typeI_SinglePanel->typeI_SinglePanel_ri_Restriction.buf[0]; + + /* Replace dummy with the nrofCQIsPerReport from the CSIreport + config when equalent ASN structure present */ + if (0==*(csi_reportconfig->dummy)){ + nb_allowed_ri = number_of_bits_set((ri_restriction & 0xf0),&max_ri); + ri_bitlen = ceil(log2(nb_allowed_ri)); + } + else{ + nb_allowed_ri = number_of_bits_set(ri_restriction, &max_ri); + ri_bitlen = ceil(log2(nb_allowed_ri)); + } + csi_report->csi_meas_bitlen.ri_bitlen=ri_bitlen; + break; + default: + AssertFatal(RC.nrmac[Mod_idP]->config[0].carrier_config.num_tx_ant.value>8,"Number of antennas %d are out of range", RC.nrmac[Mod_idP]->config[0].carrier_config.num_tx_ant.value); + } + } + csi_report->csi_meas_bitlen.li_bitlen=0; + csi_report->csi_meas_bitlen.cqi_bitlen=0; + csi_report->csi_meas_bitlen.pmi_x1_bitlen=0; + csi_report->csi_meas_bitlen.pmi_x2_bitlen=0; + } + + if( NR_CSI_ReportConfig__reportQuantity_PR_cri_RI_LI_PMI_CQI==reportQuantity_type ){ + if (NR_CodebookConfig__codebookType__type1__subType_PR_typeI_SinglePanel==csi_reportconfig->codebookConfig->codebookType.choice.type1->subType.present){ + + switch (RC.nrmac[Mod_idP]->config[0].carrier_config.num_tx_ant.value) { + case 1:; + csi_report->csi_meas_bitlen.li_bitlen=0; + break; + case 2: + case 4: + case 6: + case 8: + /* From Spec 38.212 + * If the higher layer parameter nrofCQIsPerReport=1, nRI in Table 6.3.1.1.2-3 is the number of allowed rank indicator + * values in the 4 LSBs of the higher layer parameter typeI-SinglePanel-ri-Restriction according to Subclause 5.2.2.2.1 [6, + * TS 38.214]; otherwise nRI in Table 6.3.1.1.2-3 is the number of allowed rank indicator values according to Subclause + * 5.2.2.2.1 [6, TS 38.214]. + * + * But from Current RRC ASN structures nrofCQIsPerReport is not present. Present a dummy variable is present so using it to + * calculate RI for antennas equal or more than two. + * */ + //! TODO: The bit length of LI is as follows LI = log2(RI), Need to confirm wheather we should consider maximum RI can be reported from ri_restricted + // or we should consider reported RI. If we need to consider reported RI for calculating LI bit length then we need to modify the code. + csi_report->csi_meas_bitlen.li_bitlen=ceil(log2(max_ri))<2?ceil(log2(max_ri)):2; + break; + default: + AssertFatal(RC.nrmac[Mod_idP]->config[0].carrier_config.num_tx_ant.value>8,"Number of antennas %d are out of range", RC.nrmac[Mod_idP]->config[0].carrier_config.num_tx_ant.value); + } + } + } + + if (NR_CSI_ReportConfig__reportQuantity_PR_cri_RI_PMI_CQI == reportQuantity_type || + NR_CSI_ReportConfig__reportQuantity_PR_cri_RI_LI_PMI_CQI==reportQuantity_type || + NR_CSI_ReportConfig__reportQuantity_PR_cri_RI_CQI==reportQuantity_type || + NR_CSI_ReportConfig__reportQuantity_PR_cri_RI_i1_CQI==reportQuantity_type){ + + switch (RC.nrmac[Mod_idP]->config[0].carrier_config.num_tx_ant.value){ + case 1: + case 2: + case 4: + case 6: + case 8: + /* From Spec 38.212 + * If the higher layer parameter nrofCQIsPerReport=1, nRI in Table 6.3.1.1.2-3 is the number of allowed rank indicator + * values in the 4 LSBs of the higher layer parameter typeI-SinglePanel-ri-Restriction according to Subclause 5.2.2.2.1 [6, + * TS 38.214]; otherwise nRI in Table 6.3.1.1.2-3 is the number of allowed rank indicator values according to Subclause + * 5.2.2.2.1 [6, TS 38.214]. + * + * But from Current RRC ASN structures nrofCQIsPerReport is not present. Present a dummy variable is present so using it to + * calculate RI for antennas equal or more than two. + * */ + + if (max_ri > 4 && max_ri < 8){ + if (NR_CodebookConfig__codebookType__type1__subType_PR_typeI_SinglePanel==csi_reportconfig->codebookConfig->codebookType.choice.type1->subType.present){ + if (NR_CSI_ReportConfig__reportFreqConfiguration__cqi_FormatIndicator_widebandCQI==csi_reportconfig->reportFreqConfiguration->cqi_FormatIndicator) + csi_report->csi_meas_bitlen.cqi_bitlen = 8; + else + csi_report->csi_meas_bitlen.cqi_bitlen = 4; + } + }else{ //This condition will work even for type1-multipanel. + if (NR_CSI_ReportConfig__reportFreqConfiguration__cqi_FormatIndicator_widebandCQI==csi_reportconfig->reportFreqConfiguration->cqi_FormatIndicator) + csi_report->csi_meas_bitlen.cqi_bitlen = 4; + else + csi_report->csi_meas_bitlen.cqi_bitlen = 2; + } + break; + default: + AssertFatal(RC.nrmac[Mod_idP]->config[0].carrier_config.num_tx_ant.value>8,"Number of antennas %d are out of range", RC.nrmac[Mod_idP]->config[0].carrier_config.num_tx_ant.value); + } + } + if (NR_CSI_ReportConfig__reportQuantity_PR_cri_RI_PMI_CQI == reportQuantity_type || + NR_CSI_ReportConfig__reportQuantity_PR_cri_RI_LI_PMI_CQI==reportQuantity_type){ + if (NR_CodebookConfig__codebookType__type1__subType_PR_typeI_SinglePanel==csi_reportconfig->codebookConfig->codebookType.choice.type1->subType.present){ + switch (csi_reportconfig->codebookConfig->codebookType.choice.type1->subType.choice.typeI_SinglePanel->nrOfAntennaPorts.present){ + case NR_CodebookConfig__codebookType__type1__subType__typeI_SinglePanel__nrOfAntennaPorts_PR_two: + if (max_ri ==1) + csi_report->csi_meas_bitlen.pmi_x1_bitlen = 2; + else if (max_ri ==2) + csi_report->csi_meas_bitlen.pmi_x1_bitlen = 1; + break; + default: + AssertFatal(csi_reportconfig->codebookConfig->codebookType.choice.type1->subType.choice.typeI_SinglePanel->nrOfAntennaPorts.present!= + NR_CodebookConfig__codebookType__type1__subType__typeI_SinglePanel__nrOfAntennaPorts_PR_two, + "Not handled Yet %d", csi_reportconfig->codebookConfig->codebookType.choice.type1->subType.choice.typeI_SinglePanel->nrOfAntennaPorts.present); + break; } } } - if (0 != UE_info->csi_report_template[UE_id][csi_report_id].nb_of_nzp_csi_report) - AssertFatal(1==0,"Currently configuring only SSB beamreporting."); break; } } @@ -181,12 +436,27 @@ void compute_csi_bitlen (NR_CellGroupConfig_t *secondaryCellGroup, NR_UE_info_t } -uint16_t nr_get_csi_bitlen(const nr_csi_report_t *csi_report) -{ - const CRI_SSBRI_RSRP_bitlen_t *bitlen = &csi_report->CSI_report_bitlen[0]; - return bitlen->cri_ssbri_bitlen * bitlen->nb_ssbri_cri - + bitlen->rsrp_bitlen - + bitlen->diff_rsrp_bitlen * (bitlen->nb_ssbri_cri - 1) * csi_report->nb_of_csi_ssb_report; +uint16_t nr_get_csi_bitlen(int Mod_idP, + int UE_id, + uint8_t csi_report_id) { + + uint16_t csi_bitlen =0; + NR_UE_info_t *UE_info = &RC.nrmac[Mod_idP]->UE_info; + L1_RSRP_bitlen_t * CSI_report_bitlen = NULL; + CSI_Meas_bitlen_t * csi_meas_bitlen = NULL; + + if (NR_CSI_ReportConfig__reportQuantity_PR_ssb_Index_RSRP==UE_info->csi_report_template[UE_id][csi_report_id].reportQuantity_type|| + NR_CSI_ReportConfig__reportQuantity_PR_cri_RSRP==UE_info->csi_report_template[UE_id][csi_report_id].reportQuantity_type){ + CSI_report_bitlen = &(UE_info->csi_report_template[UE_id][csi_report_id].CSI_report_bitlen); //This might need to be moodif for Aperiodic CSI-RS measurements + csi_bitlen+= ((CSI_report_bitlen->cri_ssbri_bitlen * CSI_report_bitlen->nb_ssbri_cri) + + CSI_report_bitlen->rsrp_bitlen +(CSI_report_bitlen->diff_rsrp_bitlen * + (CSI_report_bitlen->nb_ssbri_cri -1 ))); + } else{ + csi_meas_bitlen = &(UE_info->csi_report_template[UE_id][csi_report_id].csi_meas_bitlen); //This might need to be moodif for Aperiodic CSI-RS measurements + csi_bitlen+= (csi_meas_bitlen->cri_bitlen +csi_meas_bitlen->ri_bitlen+csi_meas_bitlen->li_bitlen+csi_meas_bitlen->cqi_bitlen+csi_meas_bitlen->pmi_x1_bitlen+csi_meas_bitlen->pmi_x2_bitlen); + } + + return csi_bitlen; } @@ -246,7 +516,7 @@ void nr_csi_meas_reporting(int Mod_idP, curr_pucch->ul_slot = sched_slot; curr_pucch->resource_indicator = res_index; curr_pucch->csi_bits += - nr_get_csi_bitlen(&UE_info->csi_report_template[UE_id][csi_report_id]); + nr_get_csi_bitlen(Mod_idP,UE_id,csi_report_id); // going through the list of PUCCH resources to find the one indexed by resource_id uint16_t *vrb_map_UL = &RC.nrmac[Mod_idP]->common_channels[0].vrb_map_UL[sched_slot * MAX_BWP_SIZE]; @@ -314,6 +584,375 @@ static void handle_dl_harq(module_id_t mod_id, } } +int checkTargetSSBInFirst64TCIStates_pdschConfig(int ssb_index_t, int Mod_idP, int UE_id) { + NR_UE_info_t *UE_info = &RC.nrmac[Mod_idP]->UE_info; + NR_CellGroupConfig_t *secondaryCellGroup = UE_info->secondaryCellGroup[UE_id] ; + int nb_tci_states = secondaryCellGroup->spCellConfig->spCellConfigDedicated->initialDownlinkBWP->pdsch_Config->choice.setup->tci_StatesToAddModList->list.count; + NR_TCI_State_t *tci =NULL; + int i; + + for(i=0; ispCellConfig->spCellConfigDedicated->initialDownlinkBWP->pdsch_Config->choice.setup->tci_StatesToAddModList->list.array[i]; + + if(tci != NULL) { + if(tci->qcl_Type1.referenceSignal.present == NR_QCL_Info__referenceSignal_PR_ssb) { + if(tci->qcl_Type1.referenceSignal.choice.ssb == ssb_index_t) + return tci->tci_StateId; // returned TCI state ID + } + // if type2 is configured + else if(tci->qcl_Type2 != NULL && tci->qcl_Type2->referenceSignal.present == NR_QCL_Info__referenceSignal_PR_ssb) { + if(tci->qcl_Type2->referenceSignal.choice.ssb == ssb_index_t) + return tci->tci_StateId; // returned TCI state ID + } else LOG_I(MAC,"SSB index is not found in first 64 TCI states of TCI_statestoAddModList[%d]", i); + } + } + + // tci state not identified in first 64 TCI States of PDSCH Config + return -1; +} + +int checkTargetSSBInTCIStates_pdcchConfig(int ssb_index_t, int Mod_idP, int UE_id) { + NR_UE_info_t *UE_info = &RC.nrmac[Mod_idP]->UE_info; + NR_CellGroupConfig_t *secondaryCellGroup = UE_info->secondaryCellGroup[UE_id] ; + int nb_tci_states = secondaryCellGroup->spCellConfig->spCellConfigDedicated->initialDownlinkBWP->pdsch_Config->choice.setup->tci_StatesToAddModList->list.count; + NR_TCI_State_t *tci =NULL; + NR_TCI_StateId_t *tci_id = NULL; + int bwp_id = 1; + NR_BWP_Downlink_t *bwp = secondaryCellGroup->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList->list.array[bwp_id-1]; + NR_ControlResourceSet_t *coreset = bwp->bwp_Dedicated->pdcch_Config->choice.setup->controlResourceSetToAddModList->list.array[bwp_id-1]; + int i; + int flag = 0; + int tci_stateID = -1; + + for(i=0; ispCellConfig->spCellConfigDedicated->initialDownlinkBWP->pdsch_Config->choice.setup->tci_StatesToAddModList->list.array[i]; + + if(tci != NULL && tci->qcl_Type1.referenceSignal.present == NR_QCL_Info__referenceSignal_PR_ssb) { + if(tci->qcl_Type1.referenceSignal.choice.ssb == ssb_index_t) { + flag = 1; + tci_stateID = tci->tci_StateId; + break; + } else if(tci->qcl_Type2 != NULL && tci->qcl_Type2->referenceSignal.present == NR_QCL_Info__referenceSignal_PR_ssb) { + flag = 1; + tci_stateID = tci->tci_StateId; + break; + } + } + + if(flag != 0 && tci_stateID != -1 && coreset != NULL) { + for(i=0; i<64 && itci_StatesPDCCH_ToAddList->list.count; i++) { + tci_id = coreset->tci_StatesPDCCH_ToAddList->list.array[i]; + + if(tci_id != NULL && *tci_id == tci_stateID) + return tci_stateID; + } + } + } + + // Need to implement once configuration is received + return -1; +} + +//returns the measured RSRP value (upper limit) +int get_measured_rsrp(uint8_t index) { + //if index is invalid returning minimum rsrp -140 + if((index >= 0 && index <= 15) || index >= 114) + return MIN_RSRP_VALUE; + + return L1_SSB_CSI_RSRP_measReport_mapping_38133_10_1_6_1_1[index]; +} + +//returns the differential RSRP value (upper limit) +int get_diff_rsrp(uint8_t index, int strongest_rsrp) { + if(strongest_rsrp != -1) { + return strongest_rsrp + diff_rsrp_ssb_csi_meas_10_1_6_1_2[index]; + } else + return MIN_RSRP_VALUE; +} + +//identifies the target SSB Beam index +//keeps the required date for PDCCH and PDSCH TCI state activation/deactivation CE consutruction globally +//handles triggering of PDCCH and PDSCH MAC CEs +void tci_handling(module_id_t Mod_idP, int UE_id, frame_t frame, slot_t slot) { + + int strongest_ssb_rsrp = 0; + int cqi_idx = 0; + int curr_ssb_beam_index = 0; //ToDo: yet to know how to identify the serving ssb beam index + uint8_t target_ssb_beam_index = curr_ssb_beam_index; + uint8_t is_triggering_ssb_beam_switch =0; + uint8_t ssb_idx = 0; + int pdsch_bwp_id =0; + int ssb_index[MAX_NUM_SSB] = {0}; + int ssb_rsrp[MAX_NUM_SSB] = {0}; + uint8_t idx = 0; + int bwp_id = 1; + NR_UE_info_t *UE_info = &RC.nrmac[Mod_idP]->UE_info; + NR_CellGroupConfig_t *secondaryCellGroup = UE_info->secondaryCellGroup[UE_id]; + NR_BWP_Downlink_t *bwp = secondaryCellGroup->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList->list.array[bwp_id-1]; + //bwp indicator + int n_dl_bwp = secondaryCellGroup->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList->list.count; + uint8_t nr_ssbri_cri = 0; + uint8_t nb_of_csi_ssb_report = UE_info->csi_report_template[UE_id][cqi_idx].nb_of_csi_ssb_report; + int better_rsrp_reported = -140-(-0); /*minimum_measured_RSRP_value - minimum_differntail_RSRP_value*///considering the minimum RSRP value as better RSRP initially + uint8_t diff_rsrp_idx = 0; + uint8_t i, j; + NR_UE_sched_ctrl_t *sched_ctrl = &UE_info->UE_sched_ctrl[UE_id]; + NR_mac_stats_t *stats = &UE_info->mac_stats[UE_id]; + + if (n_dl_bwp < 4) + pdsch_bwp_id = bwp_id; + else + pdsch_bwp_id = bwp_id - 1; // as per table 7.3.1.1.2-1 in 38.212 + + /*Example: + CRI_SSBRI: 1 2 3 4| 5 6 7 8| 9 10 1 2| + nb_of_csi_ssb_report = 3 //3 sets as above + nr_ssbri_cri = 4 //each set has 4 elements + storing ssb indexes in ssb_index array as ssb_index[0] = 1 .. ssb_index[4] = 5 + ssb_rsrp[0] = strongest rsrp in first set, ssb_rsrp[4] = strongest rsrp in second set, .. + idx: resource set index + */ + + //for all reported SSB + for (idx = 0; idx < nb_of_csi_ssb_report; idx++) { + nr_ssbri_cri = sched_ctrl->CSI_report[idx].choice.ssb_cri_report.nr_ssbri_cri; + //extracting the ssb indexes + for (ssb_idx = 0; ssb_idx < nr_ssbri_cri; ssb_idx++) { + ssb_index[idx * nb_of_csi_ssb_report + ssb_idx] = sched_ctrl->CSI_report[idx].choice.ssb_cri_report.CRI_SSBRI[ssb_idx]; + } + + //if strongest measured RSRP is configured + strongest_ssb_rsrp = get_measured_rsrp(sched_ctrl->CSI_report[idx].choice.ssb_cri_report.RSRP); + // including ssb rsrp in mac stats + stats->cumul_rsrp += strongest_ssb_rsrp; + stats->num_rsrp_meas++; + ssb_rsrp[idx * nb_of_csi_ssb_report] = strongest_ssb_rsrp; + LOG_D(MAC,"ssb_rsrp = %d\n",strongest_ssb_rsrp); + + //if current ssb rsrp is greater than better rsrp + if(ssb_rsrp[idx * nb_of_csi_ssb_report] > better_rsrp_reported) { + better_rsrp_reported = ssb_rsrp[idx * nb_of_csi_ssb_report]; + target_ssb_beam_index = idx * nb_of_csi_ssb_report; + } + + for(diff_rsrp_idx =1; diff_rsrp_idx < nr_ssbri_cri; diff_rsrp_idx++) { + ssb_rsrp[idx * nb_of_csi_ssb_report + diff_rsrp_idx] = get_diff_rsrp(sched_ctrl->CSI_report[idx].choice.ssb_cri_report.diff_RSRP[diff_rsrp_idx-1], strongest_ssb_rsrp); + + //if current reported rsrp is greater than better rsrp + if(ssb_rsrp[idx * nb_of_csi_ssb_report + diff_rsrp_idx] > better_rsrp_reported) { + better_rsrp_reported = ssb_rsrp[idx * nb_of_csi_ssb_report + diff_rsrp_idx]; + target_ssb_beam_index = idx * nb_of_csi_ssb_report + diff_rsrp_idx; + } + } + } + + + if(ssb_index[target_ssb_beam_index] != ssb_index[curr_ssb_beam_index] && ssb_rsrp[target_ssb_beam_index] > ssb_rsrp[curr_ssb_beam_index]) { + if( ssb_rsrp[target_ssb_beam_index] - ssb_rsrp[curr_ssb_beam_index] > L1_RSRP_HYSTERIS) { + is_triggering_ssb_beam_switch = 1; + LOG_D(MAC, "Triggering ssb beam switching using tci\n"); + } + } + + if(is_triggering_ssb_beam_switch) { + //filling pdcch tci state activativation mac ce structure fields + sched_ctrl->UE_mac_ce_ctrl.pdcch_state_ind.is_scheduled = 1; + //OAI currently focusing on Non CA usecase hence 0 is considered as serving + //cell id + sched_ctrl->UE_mac_ce_ctrl.pdcch_state_ind.servingCellId = 0; //0 for PCell as 38.331 v15.9.0 page 353 //serving cell id for which this MAC CE applies + sched_ctrl->UE_mac_ce_ctrl.pdcch_state_ind.coresetId = 0; //coreset id for which the TCI State id is being indicated + + /* 38.321 v15.8.0 page 66 + TCI State ID: This field indicates the TCI state identified by TCI-StateId as specified in TS 38.331 [5] applicable + to the Control Resource Set identified by CORESET ID field. + If the field of CORESET ID is set to 0, + this field indicates a TCI-StateId for a TCI state of the first 64 TCI-states configured by tci-States-ToAddModList and tciStates-ToReleaseList in the PDSCH-Config in the active BWP. + If the field of CORESET ID is set to the other value than 0, + this field indicates a TCI-StateId configured by tci-StatesPDCCH-ToAddList and tciStatesPDCCH-ToReleaseList in the controlResourceSet identified by the indicated CORESET ID. + The length of the field is 7 bits + */ + if(sched_ctrl->UE_mac_ce_ctrl.pdcch_state_ind.coresetId == 0) { + int tci_state_id = checkTargetSSBInFirst64TCIStates_pdschConfig(ssb_index[target_ssb_beam_index], Mod_idP, UE_id); + + if( tci_state_id != -1) + sched_ctrl->UE_mac_ce_ctrl.pdcch_state_ind.tciStateId = tci_state_id; + else { + //identify the best beam within first 64 TCI States of PDSCH + //Config TCI-states-to-addModList + int flag = 0; + + for(i =0; ssb_index_sorted[i]!=0; i++) { + tci_state_id = checkTargetSSBInFirst64TCIStates_pdschConfig(ssb_index_sorted[i], Mod_idP, UE_id) ; + + if(tci_state_id != -1 && ssb_rsrp_sorted[i] > ssb_rsrp[curr_ssb_beam_index] && ssb_rsrp_sorted[i] - ssb_rsrp[curr_ssb_beam_index] > L1_RSRP_HYSTERIS) { + sched_ctrl->UE_mac_ce_ctrl.pdcch_state_ind.tciStateId = tci_state_id; + flag = 1; + break; + } + } + + if(flag == 0 || ssb_rsrp_sorted[i] < ssb_rsrp[curr_ssb_beam_index] || ssb_rsrp_sorted[i] - ssb_rsrp[curr_ssb_beam_index] < L1_RSRP_HYSTERIS) { + sched_ctrl->UE_mac_ce_ctrl.pdcch_state_ind.is_scheduled = 0; + } + } + } else { + int tci_state_id = checkTargetSSBInTCIStates_pdcchConfig(ssb_index[target_ssb_beam_index], Mod_idP, UE_id); + + if (tci_state_id !=-1) + sched_ctrl->UE_mac_ce_ctrl.pdcch_state_ind.tciStateId = tci_state_id; + else { + //identify the best beam within CORESET/PDCCH + ////Config TCI-states-to-addModList + int flag = 0; + + for(i =0; ssb_index_sorted[i]!=0; i++) { + tci_state_id = checkTargetSSBInTCIStates_pdcchConfig(ssb_index_sorted[i], Mod_idP, UE_id); + + if( tci_state_id != -1 && ssb_rsrp_sorted[i] > ssb_rsrp[curr_ssb_beam_index] && ssb_rsrp_sorted[i] - ssb_rsrp[curr_ssb_beam_index] > L1_RSRP_HYSTERIS) { + sched_ctrl->UE_mac_ce_ctrl.pdcch_state_ind.tciStateId = tci_state_id; + flag = 1; + break; + } + } + + if(flag == 0 || ssb_rsrp_sorted[i] < ssb_rsrp[curr_ssb_beam_index] || ssb_rsrp_sorted[i] - ssb_rsrp[curr_ssb_beam_index] < L1_RSRP_HYSTERIS) { + sched_ctrl->UE_mac_ce_ctrl.pdcch_state_ind.is_scheduled = 0; + } + } + } + + sched_ctrl->UE_mac_ce_ctrl.pdcch_state_ind.tci_present_inDCI = bwp->bwp_Dedicated->pdcch_Config->choice.setup->controlResourceSetToAddModList->list.array[bwp_id-1]->tci_PresentInDCI; + + //filling pdsch tci state activation deactivation mac ce structure fields + if(sched_ctrl->UE_mac_ce_ctrl.pdcch_state_ind.tci_present_inDCI) { + sched_ctrl->UE_mac_ce_ctrl.pdsch_TCI_States_ActDeact.is_scheduled = 1; + /* + Serving Cell ID: This field indicates the identity of the Serving Cell for which the MAC CE applies + Considering only PCell exists. Serving cell index of PCell is always 0, hence configuring 0 + */ + sched_ctrl->UE_mac_ce_ctrl.pdsch_TCI_States_ActDeact.servingCellId = 0; + /* + BWP ID: This field indicates a DL BWP for which the MAC CE applies as the codepoint of the DCI bandwidth + part indicator field as specified in TS 38.212 + */ + sched_ctrl->UE_mac_ce_ctrl.pdsch_TCI_States_ActDeact.bwpId = pdsch_bwp_id; + + /* + * TODO ssb_rsrp_sort() API yet to code to find 8 best beams, rrc configuration + * is required + */ + for(i = 0; i<8; i++) { + sched_ctrl->UE_mac_ce_ctrl.pdsch_TCI_States_ActDeact.tciStateActDeact[i] = i; + } + + sched_ctrl->UE_mac_ce_ctrl.pdsch_TCI_States_ActDeact.highestTciStateActivated = 8; + + for(i = 0, j =0; iUE_mac_ce_ctrl.pdsch_TCI_States_ActDeact.tciStateActDeact[i]) { + sched_ctrl->UE_mac_ce_ctrl.pdsch_TCI_States_ActDeact.codepoint[j] = i; + j++; + } + } + }//tci_presentInDCI + }//is-triggering_beam_switch +}//tci handling + +void reverse_n_bits(uint8_t *value, uint16_t bitlen) { + uint16_t j; + uint8_t i; + for(j = bitlen - 1,i = 0; j > i; j--, i++) { + if(((*value>>j)&1) != ((*value>>i)&1)) { + *value ^= (1<csi_part1.csi_part1_bit_len)/8); + uint8_t *payload = uci_pdu->csi_part1.csi_part1_payload; + NR_CSI_ReportConfig__reportQuantity_PR reportQuantity_type = NR_CSI_ReportConfig__reportQuantity_PR_NOTHING; + NR_UE_info_t *UE_info = &(RC.nrmac[Mod_idP]->UE_info); + NR_UE_sched_ctrl_t *sched_ctrl = &UE_info->UE_sched_ctrl[UE_id]; + uint8_t csi_report_id = 0; + + UE_info->csi_report_template[UE_id][csi_report_id].nb_of_csi_ssb_report = 0; + for ( csi_report_id =0; csi_report_id < csi_MeasConfig->csi_ReportConfigToAddModList->list.count; csi_report_id++ ) { + //Has to implement according to reportSlotConfig type + /*reportQuantity must be considered according to the current scheduled + CSI-ReportConfig if multiple CSI-ReportConfigs present*/ + reportQuantity_type = UE_info->csi_report_template[UE_id][csi_report_id].reportQuantity_type; + LOG_D(PHY,"SFN/SF:%d%d reportQuantity type = %d\n",frame,slot,reportQuantity_type); + + if (NR_CSI_ReportConfig__reportQuantity_PR_ssb_Index_RSRP == reportQuantity_type || + NR_CSI_ReportConfig__reportQuantity_PR_cri_RSRP == reportQuantity_type) { + uint8_t csi_ssb_idx = 0; + uint8_t diff_rsrp_idx = 0; + uint8_t cri_ssbri_bitlen = UE_info->csi_report_template[UE_id][csi_report_id].CSI_report_bitlen.cri_ssbri_bitlen; + + /*! As per the spec 38.212 and table: 6.3.1.1.2-12 in a single UCI sequence we can have multiple CSI_report + * the number of CSI_report will depend on number of CSI resource sets that are configured in CSI-ResourceConfig RRC IE + * From spec 38.331 from the IE CSI-ResourceConfig for SSB RSRP reporting we can configure only one resource set + * From spec 38.214 section 5.2.1.2 For periodic and semi-persistent CSI Resource Settings, the number of CSI-RS Resource Sets configured is limited to S=1 + */ + + /** from 38.214 sec 5.2.1.4.2 + - if the UE is configured with the higher layer parameter groupBasedBeamReporting set to 'disabled', the UE is + not required to update measurements for more than 64 CSI-RS and/or SSB resources, and the UE shall report in + a single report nrofReportedRS (higher layer configured) different CRI or SSBRI for each report setting + + - if the UE is configured with the higher layer parameter groupBasedBeamReporting set to 'enabled', the UE is not + required to update measurements for more than 64 CSI-RS and/or SSB resources, and the UE shall report in a + single reporting instance two different CRI or SSBRI for each report setting, where CSI-RS and/or SSB + resources can be received simultaneously by the UE either with a single spatial domain receive filter, or with + multiple simultaneous spatial domain receive filter + */ + + idx = 0; //Since for SSB RSRP reporting in RRC can configure only one ssb resource set per one report config + sched_ctrl->CSI_report[idx].choice.ssb_cri_report.nr_ssbri_cri = UE_info->csi_report_template[UE_id][csi_report_id].CSI_report_bitlen.nb_ssbri_cri; + + for (csi_ssb_idx = 0; csi_ssb_idx < sched_ctrl->CSI_report[idx].choice.ssb_cri_report.nr_ssbri_cri ; csi_ssb_idx++) { + if(cri_ssbri_bitlen > 1) + reverse_n_bits(payload, cri_ssbri_bitlen); + + if (NR_CSI_ReportConfig__reportQuantity_PR_ssb_Index_RSRP == reportQuantity_type) + sched_ctrl->CSI_report[idx].choice.ssb_cri_report.CRI_SSBRI [csi_ssb_idx] = + *(UE_info->csi_report_template[UE_id][csi_report_id].SSB_Index_list[cri_ssbri_bitlen>0?((*payload)&~(~1<<(cri_ssbri_bitlen-1))):cri_ssbri_bitlen]); + else + sched_ctrl->CSI_report[idx].choice.ssb_cri_report.CRI_SSBRI [csi_ssb_idx] = + *(UE_info->csi_report_template[UE_id][csi_report_id].CSI_Index_list[cri_ssbri_bitlen>0?((*payload)&~(~1<<(cri_ssbri_bitlen-1))):cri_ssbri_bitlen]); + + *payload >>= cri_ssbri_bitlen; + LOG_D(PHY,"SSB_index = %d\n",sched_ctrl->CSI_report[idx].choice.ssb_cri_report.CRI_SSBRI [csi_ssb_idx]); + } + + reverse_n_bits(payload, 7); + sched_ctrl->CSI_report[idx].choice.ssb_cri_report.RSRP = (*payload) & 0x7f; + *payload >>= 7; + + for ( diff_rsrp_idx =0; diff_rsrp_idx < sched_ctrl->CSI_report[idx].choice.ssb_cri_report.nr_ssbri_cri - 1; diff_rsrp_idx++ ) { + reverse_n_bits(payload,4); + sched_ctrl->CSI_report[idx].choice.ssb_cri_report.diff_RSRP[diff_rsrp_idx] = (*payload) & 0x0f; + *payload >>= 4; + } + UE_info->csi_report_template[UE_id][csi_report_id].nb_of_csi_ssb_report++; + LOG_D(MAC,"csi_payload size = %d, rsrp_id = %d\n",payload_size, sched_ctrl->CSI_report[idx].choice.ssb_cri_report.RSRP); + } + } + + if ( !(reportQuantity_type)) + AssertFatal(reportQuantity_type, "reportQuantity is not configured"); + +} + void handle_nr_uci_pucch_0_1(module_id_t mod_id, frame_t frame, sub_frame_t slot, @@ -374,17 +1013,19 @@ void handle_nr_uci_pucch_2_3_4(module_id_t mod_id, frame_t frame, sub_frame_t slot, const nfapi_nr_uci_pucch_pdu_format_2_3_4_t *uci_234) -{ NR_UE_info_t *UE_info = &RC.nrmac[mod_id]->UE_info; - UE_info->active[0] = 1; - UE_info->rnti[0] = uci_234->rnti; - int UE_id = find_nr_UE_id(mod_id, uci_234->rnti); +{ int UE_id = find_nr_UE_id(mod_id, uci_234->rnti); if (UE_id < 0) { LOG_E(MAC, "%s(): unknown RNTI %04x in PUCCH UCI\n", __func__, uci_234->rnti); return; } - //NR_UE_info_t *UE_info = &RC.nrmac[mod_id]->UE_info; + NR_CSI_MeasConfig_t *csi_MeasConfig = RC.nrmac[mod_id]->UE_info.secondaryCellGroup[UE_id]->spCellConfig->spCellConfigDedicated->csi_MeasConfig->choice.setup; + NR_UE_info_t *UE_info = &RC.nrmac[mod_id]->UE_info; NR_UE_sched_ctrl_t *sched_ctrl = &UE_info->UE_sched_ctrl[UE_id]; - + if (NFAPI_MODE == NFAPI_MODE_PNF){ + UE_info->active[0] = 1; + UE_info->rnti[0] = uci_234->rnti; + } + // tpc (power control) sched_ctrl->tpc1 = nr_get_tpc(RC.nrmac[mod_id]->pucch_target_snrx10, uci_234->ul_cqi, @@ -422,6 +1063,15 @@ void handle_nr_uci_pucch_2_3_4(module_id_t mod_id, // handle_dl_harq(mod_id, UE_id, pid, uci_234->harq.harq_crc != 1 && acknack); // } // } + if ((uci_234->pduBitmap >> 2) & 0x01) { + //API to parse the csi report and store it into sched_ctrl + extract_pucch_csi_report (csi_MeasConfig, uci_234, frame, slot, UE_id, mod_id); + //TCI handling function + tci_handling(mod_id, UE_id,frame, slot); + } + if ((uci_234->pduBitmap >> 3) & 0x01) { + //@TODO:Handle CSI Report 2 + } } @@ -762,5 +1412,4 @@ uint16_t compute_pucch_prb_size(uint8_t format, else{ AssertFatal(1==0,"Not yet implemented"); } - } diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c index 94aa4f5159..23d8f7677f 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c @@ -396,7 +396,7 @@ void nr_rx_sdu(const module_id_t gnb_mod_idP, T_BUFFER(sduP, sdu_lenP)); UE_info->mac_stats[UE_id].ulsch_total_bytes_rx += sdu_lenP; - LOG_D(MAC, "[gNB %d][PUSCH %d] CC_id %d %d.%d Received ULSCH sdu from PHY (rnti %x, UE_id %d) ul_cqi %d sduP %p\n", + LOG_D(NR_MAC, "[gNB %d][PUSCH %d] CC_id %d %d.%d Received ULSCH sdu from PHY (rnti %x, UE_id %d) ul_cqi %d sduP %p\n", gnb_mod_idP, harq_pid, CC_idP, @@ -413,7 +413,7 @@ void nr_rx_sdu(const module_id_t gnb_mod_idP, if (timing_advance != 0xffff) UE_scheduling_control->ta_update = timing_advance; UE_scheduling_control->ul_rssi = rssi; - LOG_D(MAC, "[UE %d] PUSCH TPC %d and TA %d\n",UE_id,UE_scheduling_control->tpc0,UE_scheduling_control->ta_update); + LOG_D(NR_MAC, "[UE %d] PUSCH TPC %d and TA %d\n",UE_id,UE_scheduling_control->tpc0,UE_scheduling_control->ta_update); } else{ UE_scheduling_control->tpc0 = 1; @@ -432,7 +432,7 @@ void nr_rx_sdu(const module_id_t gnb_mod_idP, #endif if (sduP != NULL){ - LOG_D(MAC, "Received PDU at MAC gNB \n"); + LOG_D(NR_MAC, "Received PDU at MAC gNB \n"); const uint32_t tb_size = UE_scheduling_control->ul_harq_processes[harq_pid].sched_pusch.tb_size; UE_scheduling_control->sched_ul_bytes -= tb_size; @@ -469,7 +469,7 @@ void nr_rx_sdu(const module_id_t gnb_mod_idP, // random access pusch with TC-RNTI if (ra->rnti != current_rnti) { - LOG_W(MAC, + LOG_W(NR_MAC, "expected TC-RNTI %04x to match current RNTI %04x\n", ra->rnti, current_rnti); @@ -477,19 +477,25 @@ void nr_rx_sdu(const module_id_t gnb_mod_idP, } const int UE_id = add_new_nr_ue(gnb_mod_idP, ra->rnti, ra->secondaryCellGroup); UE_info->UE_beam_index[UE_id] = ra->beam_id; - LOG_I(MAC, + LOG_I(NR_MAC, "[gNB %d][RAPROC] PUSCH with TC_RNTI %x received correctly, " "adding UE MAC Context UE_id %d/RNTI %04x\n", gnb_mod_idP, current_rnti, UE_id, ra->rnti); + + LOG_D(NR_MAC,"[RAPROC] Received Msg3:\n"); + for (int k = 0; k < sdu_lenP; k++) { + LOG_D(NR_MAC,"(%i): 0x%x\n",k,sduP[k]); + } + // re-initialize ta update variables afrer RA procedure completion UE_info->UE_sched_ctrl[UE_id].ta_frame = frameP; free(ra->preambles.preamble_list); ra->state = RA_IDLE; - LOG_I(MAC, + LOG_I(NR_MAC, "reset RA state information for RA-RNTI %04x/index %d\n", ra->rnti, i); @@ -1069,18 +1075,16 @@ void nr_schedule_ulsch(module_id_t module_id, /* PUSCH PTRS */ if (ps->NR_DMRS_UplinkConfig->phaseTrackingRS != NULL) { - // TODO to be fixed from RRC config - uint8_t ptrs_mcs1 = 2; // higher layer parameter in PTRS-UplinkConfig - uint8_t ptrs_mcs2 = 4; // higher layer parameter in PTRS-UplinkConfig - uint8_t ptrs_mcs3 = 10; // higher layer parameter in PTRS-UplinkConfig - uint16_t n_rb0 = 25; // higher layer parameter in PTRS-UplinkConfig - uint16_t n_rb1 = 75; // higher layer parameter in PTRS-UplinkConfig - pusch_pdu->pusch_ptrs.ptrs_time_density = get_L_ptrs(ptrs_mcs1, ptrs_mcs2, ptrs_mcs3, pusch_pdu->mcs_index, pusch_pdu->mcs_table); - pusch_pdu->pusch_ptrs.ptrs_freq_density = get_K_ptrs(n_rb0, n_rb1, pusch_pdu->rb_size); + 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)); - pusch_pdu->pusch_ptrs.ptrs_ports_list[0].ptrs_re_offset = 0; - - pusch_pdu->pdu_bit_map |= PUSCH_PDU_BITMAP_PUSCH_PTRS; // enable PUSCH PTRS + valid_ptrs_setup = set_ul_ptrs_values(ps->NR_DMRS_UplinkConfig->phaseTrackingRS->choice.setup, + 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 @@ -1144,4 +1148,4 @@ void nr_schedule_ulsch(module_id_t module_id, memset(sched_pusch, 0, sizeof(*sched_pusch)); } -} \ No newline at end of file +} diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h index 3502a11580..c1c7278338 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h +++ b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h @@ -73,6 +73,7 @@ void schedule_control_sib1(module_id_t module_id, int time_domain_allocation, uint8_t mcsTableIdx, uint8_t mcs, + uint8_t candidate_idx, int num_total_bytes); void schedule_nr_sib1(module_id_t module_idP, frame_t frameP, sub_frame_t subframeP); @@ -328,7 +329,7 @@ uint16_t compute_pucch_prb_size(uint8_t format, uint8_t n_symb, uint8_t n_re_ctrl); -void compute_csi_bitlen (NR_CellGroupConfig_t *secondaryCellGroup, NR_UE_info_t *UE_info, int UE_id); +void compute_csi_bitlen(NR_CSI_MeasConfig_t *csi_MeasConfig, NR_UE_info_t *UE_info, int UE_id, module_id_t Mod_idP); int get_dlscs(nfapi_nr_config_request_t *cfg); diff --git a/openair2/LAYER2/NR_MAC_gNB/main.c b/openair2/LAYER2/NR_MAC_gNB/main.c index 8dc1303801..33e575d2b9 100644 --- a/openair2/LAYER2/NR_MAC_gNB/main.c +++ b/openair2/LAYER2/NR_MAC_gNB/main.c @@ -96,7 +96,7 @@ void mac_top_init_gNB(void) // These should be out of here later pdcp_layer_init(); - if(IS_SOFTMODEM_NOS1 && !get_softmodem_params()->do_ra) + if(IS_SOFTMODEM_NOS1 && !(get_softmodem_params()->do_ra || get_softmodem_params()->sa) ) nr_DRB_preconfiguration(0x1234); rrc_init_nr_global_param(); diff --git a/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h b/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h index 63587d58a4..ac583b5270 100644 --- a/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h +++ b/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h @@ -246,8 +246,17 @@ typedef struct pdcchStateInd { uint8_t servingCellId; uint8_t coresetId; uint8_t tciStateId; + bool tci_present_inDCI; } pdcchStateInd_t; +typedef struct pucchSpatialRelation { + bool is_scheduled; + uint8_t servingCellId; + uint8_t bwpId; + uint8_t pucchResourceId; + bool s0tos7_actDeact[8]; +} pucchSpatialRelation_t; + typedef struct SPCSIReportingpucch { bool is_scheduled; uint8_t servingCellId; @@ -271,12 +280,14 @@ typedef struct pdschTciStatesActDeact { uint8_t bwpId; uint8_t highestTciStateActivated; bool tciStateActDeact[MAX_TCI_STATES]; + uint8_t codepoint[8]; } pdschTciStatesActDeact_t; typedef struct UE_info { sp_zp_csirs_t sp_zp_csi_rs; csi_rs_im_t csi_im; pdcchStateInd_t pdcch_state_ind; + pucchSpatialRelation_t pucch_spatial_relation; SPCSIReportingpucch_t SP_CSI_reporting_pucch; aperiodicCSI_triggerStateSelection_t aperi_CSI_trigger; pdschTciStatesActDeact_t pdsch_TCI_States_ActDeact; @@ -352,6 +363,84 @@ typedef struct NR_UE_harq { uint32_t tb_size; } NR_UE_harq_t; +//! fixme : need to enhace for the multiple TB CQI report + + +// +/*! As per spec 38.214 section 5.2.1.4.2 + * - if the UE is configured with the higher layer parameter groupBasedBeamReporting set to 'disabled', the UE shall report in + a single report nrofReportedRS (higher layer configured) different CRI or SSBRI for each report setting. + * - if the UE is configured with the higher layer parameter groupBasedBeamReporting set to 'enabled', the UE shall report in a + single reporting instance two different CRI or SSBRI for each report setting, where CSI-RS and/or SSB + resources can be received simultaneously by the UE either with a single spatial domain receive filter, or with + multiple simultaneous spatial domain receive filter +*/ +#define MAX_NR_OF_REPORTED_RS 4 + +typedef enum NR_CSI_Report_Config { + CSI_Report_PR_cri_ri_li_pmi_cqi_report, + CSI_Report_PR_ssb_cri_report +} NR_CSI_Report_Config_PR; +struct CRI_RI_LI_PMI_CQI { + uint8_t cri; + uint8_t ri; + uint8_t li; + uint8_t pmi_x1; + uint8_t pmi_x2; + uint8_t cqi; +}; + +typedef struct CRI_SSB_RSRP { + uint8_t nr_ssbri_cri; + uint8_t CRI_SSBRI[MAX_NR_OF_REPORTED_RS]; + uint8_t RSRP; + uint8_t diff_RSRP[MAX_NR_OF_REPORTED_RS - 1]; +} CRI_SSB_RSRP_t; + +struct CSI_Report { + NR_CSI_Report_Config_PR present; + union Config_CSI_Report { + struct CRI_RI_LI_PMI_CQI cri_ri_li_pmi_cqi_report; + struct CRI_SSB_RSRP ssb_cri_report; + } choice; +}; + +#define MAX_SR_BITLEN 8 + +typedef struct { + uint8_t nb_ssbri_cri; + uint8_t cri_ssbri_bitlen; + uint8_t rsrp_bitlen; + uint8_t diff_rsrp_bitlen; +}L1_RSRP_bitlen_t; + +typedef struct{ + uint8_t cri_bitlen; + uint8_t ri_bitlen; + uint8_t li_bitlen; + uint8_t pmi_x1_bitlen; + uint8_t pmi_x2_bitlen; + uint8_t cqi_bitlen; +} CSI_Meas_bitlen_t; + +typedef struct nr_csi_report { + NR_CSI_ReportConfig__reportQuantity_PR reportQuantity_type; + long periodicity; + uint16_t offset; + long ** SSB_Index_list; + long ** CSI_Index_list; +// uint8_t nb_of_nzp_csi_report; + uint8_t nb_of_csi_ssb_report; + L1_RSRP_bitlen_t CSI_report_bitlen; + CSI_Meas_bitlen_t csi_meas_bitlen; +} nr_csi_report_t; + +/*! As per the spec 38.212 and table: 6.3.1.1.2-12 in a single UCI sequence we can have multiple CSI_report + the number of CSI_report will depend on number of CSI resource sets that are configured in CSI-ResourceConfig RRC IE + From spec 38.331 from the IE CSI-ResourceConfig for SSB RSRP reporting we can configure only one resource set + From spec 38.214 section 5.2.1.2 For periodic and semi-persistent CSI Resource Settings, the number of CSI-RS Resource Sets configured is limited to S=1 + */ +#define MAX_CSI_RESOURCE_SET_IN_CSI_RESOURCE_CONFIG 16 typedef struct NR_UE_old_sched { uint16_t rbSize; int time_domain_allocation; @@ -376,26 +465,8 @@ typedef struct NR_UE_ul_harq { NR_sched_pusch_t sched_pusch; } NR_UE_ul_harq_t; - -typedef struct { - uint8_t nb_ssbri_cri; - uint8_t cri_ssbri_bitlen; - uint8_t rsrp_bitlen; - uint8_t diff_rsrp_bitlen; -}CRI_SSBRI_RSRP_bitlen_t; - - -#define MAX_CSI_RESOURCE_SET_IN_CSI_RESOURCE_CONFIG 16 -typedef struct nr_csi_report { - NR_CSI_ReportConfig__reportQuantity_PR reportQuantity_type; - NR_CSI_ResourceConfig__csi_RS_ResourceSetList_PR CSI_Resource_type; - uint8_t nb_of_nzp_csi_report; - uint8_t nb_of_csi_ssb_report; - CRI_SSBRI_RSRP_bitlen_t CSI_report_bitlen[MAX_CSI_RESOURCE_SET_IN_CSI_RESOURCE_CONFIG]; -} nr_csi_report_t; - - /*! \brief scheduling control information set through an API */ +#define MAX_CSI_REPORTS 48 typedef struct { /// total amount of data awaiting for this UE uint32_t num_total_bytes; @@ -450,6 +521,8 @@ typedef struct { uint8_t tpc0; uint8_t tpc1; uint16_t ul_rssi; + uint8_t current_harq_pid; + struct CSI_Report CSI_report[MAX_CSI_REPORTS]; /// information about every HARQ process NR_UE_harq_t harq_processes[NR_MAX_NB_HARQ_PROCESSES]; /// HARQ processes that are free @@ -487,6 +560,8 @@ typedef struct { int ulsch_total_bytes_scheduled; int ulsch_total_bytes_rx; int ulsch_current_bytes; + int cumul_rsrp; + uint8_t num_rsrp_meas; } NR_mac_stats_t; diff --git a/openair2/LAYER2/nr_pdcp/nr_pdcp_entity.c b/openair2/LAYER2/nr_pdcp/nr_pdcp_entity.c index ffc669a461..eda6888ecd 100644 --- a/openair2/LAYER2/nr_pdcp/nr_pdcp_entity.c +++ b/openair2/LAYER2/nr_pdcp/nr_pdcp_entity.c @@ -21,24 +21,222 @@ #include "nr_pdcp_entity.h" -#include "nr_pdcp_entity_drb_am.h" +#include +#include +#include + #include "nr_pdcp_security_nea2.h" +#include "nr_pdcp_sdu.h" #include "LOG/log.h" -nr_pdcp_entity_t *new_nr_pdcp_entity_srb( - int is_gnb, int rb_id, - void (*deliver_sdu)(void *deliver_sdu_data, struct nr_pdcp_entity_t *entity, - char *buf, int size), - void *deliver_sdu_data, - void (*deliver_pdu)(void *deliver_pdu_data, struct nr_pdcp_entity_t *entity, - char *buf, int size, int sdu_id), - void *deliver_pdu_data) +static void nr_pdcp_entity_recv_pdu(nr_pdcp_entity_t *entity, + char *_buffer, int size) { - abort(); + unsigned char *buffer = (unsigned char *)_buffer; + nr_pdcp_sdu_t *sdu; + int rcvd_sn; + uint32_t rcvd_hfn; + uint32_t rcvd_count; + int header_size; + int integrity_size; + int rx_deliv_sn; + uint32_t rx_deliv_hfn; + + if (size < 1) { + LOG_E(PDCP, "bad PDU received (size = %d)\n", size); + return; + } + + if (!(buffer[0] & 0x80)) { + LOG_E(PDCP, "%s:%d:%s: fatal\n", __FILE__, __LINE__, __FUNCTION__); + exit(1); + } + + if (entity->sn_size == 12) { + rcvd_sn = (((unsigned char)buffer[0] & 0xf) << 8) | + (unsigned char)buffer[1]; + header_size = 2; + } else { + rcvd_sn = (((unsigned char)buffer[0] & 0x3) << 16) | + ((unsigned char)buffer[1] << 8) | + (unsigned char)buffer[2]; + header_size = 3; + } + + integrity_size = 0; + + if (size < header_size + integrity_size + 1) { + LOG_E(PDCP, "bad PDU received (size = %d)\n", size); + return; + } + + rx_deliv_sn = entity->rx_deliv & entity->sn_max; + rx_deliv_hfn = (entity->rx_deliv >> entity->sn_size) & ~entity->sn_max; + + if (rcvd_sn < rx_deliv_sn - entity->window_size) { + rcvd_hfn = rx_deliv_hfn + 1; + } else if (rcvd_sn >= rx_deliv_sn + entity->window_size) { + rcvd_hfn = rx_deliv_hfn - 1; + } else { + rcvd_hfn = rx_deliv_hfn; + } + + rcvd_count = (rcvd_hfn << entity->sn_size) | rcvd_sn; + + if (entity->has_ciphering) + entity->cipher(entity->security_context, + (unsigned char *)buffer+header_size, size-header_size, + entity->rb_id, rcvd_count, entity->is_gnb ? 0 : 1); + + if (rcvd_count < entity->rx_deliv + || nr_pdcp_sdu_in_list(entity->rx_list, rcvd_count)) { + LOG_D(PDCP, "discard NR PDU rcvd_count=%d\n", rcvd_count); + return; + } + + sdu = nr_pdcp_new_sdu(rcvd_count, + (char *)buffer + header_size, + size - header_size - integrity_size); + entity->rx_list = nr_pdcp_sdu_list_add(entity->rx_list, sdu); + entity->rx_size += size-header_size; + + if (rcvd_count >= entity->rx_next) { + entity->rx_next = rcvd_count + 1; + } + + /* TODO(?): out of order delivery */ + + if (rcvd_count == entity->rx_deliv) { + /* deliver all SDUs starting from rx_deliv up to discontinuity or end of list */ + uint32_t count = entity->rx_deliv; + while (entity->rx_list != NULL && count == entity->rx_list->count) { + nr_pdcp_sdu_t *cur = entity->rx_list; + entity->deliver_sdu(entity->deliver_sdu_data, entity, + cur->buffer, cur->size); + entity->rx_list = cur->next; + entity->rx_size -= cur->size; + nr_pdcp_free_sdu(cur); + count++; + } + entity->rx_deliv = count; + } + + if (entity->t_reordering_start != 0 && entity->rx_deliv > entity->rx_reord) { + /* stop and reset t-Reordering */ + entity->t_reordering_start = 0; + } + + if (entity->t_reordering_start == 0 && entity->rx_deliv < entity->rx_next) { + entity->rx_reord = entity->rx_next; + entity->t_reordering_start = entity->t_current; + } } -nr_pdcp_entity_t *new_nr_pdcp_entity_drb_am( +static void nr_pdcp_entity_recv_sdu(nr_pdcp_entity_t *entity, + char *buffer, int size, int sdu_id) +{ + uint32_t count; + int sn; + int header_size; + char buf[size+3+4]; + + count = entity->tx_next; + sn = entity->tx_next & entity->sn_max; + + if (entity->sn_size == 12) { + buf[0] = 0x80 | ((sn >> 8) & 0xf); + buf[1] = sn & 0xff; + header_size = 2; + } else { + buf[0] = 0x80 | ((sn >> 16) & 0x3); + buf[1] = (sn >> 8) & 0xff; + buf[2] = sn & 0xff; + header_size = 3; + } + + memcpy(buf+header_size, buffer, size); + + if (entity->has_ciphering) + entity->cipher(entity->security_context, + (unsigned char *)buf+header_size, size, + entity->rb_id, count, entity->is_gnb ? 1 : 0); + + entity->tx_next++; + + entity->deliver_pdu(entity->deliver_pdu_data, entity, buf, + size+header_size, sdu_id); +} + +static void nr_pdcp_entity_set_integrity_key(nr_pdcp_entity_t *entity, + char *key) +{ + memcpy(entity->integrity_key, key, 16); +} + +static void check_t_reordering(nr_pdcp_entity_t *entity) +{ + uint32_t count; + + if (entity->t_reordering_start == 0 + || entity->t_current <= entity->t_reordering_start + entity->t_reordering) + return; + + /* stop timer */ + entity->t_reordering_start = 0; + + /* deliver all SDUs with count < rx_reord */ + while (entity->rx_list != NULL && entity->rx_list->count < entity->rx_reord) { + nr_pdcp_sdu_t *cur = entity->rx_list; + entity->deliver_sdu(entity->deliver_sdu_data, entity, + cur->buffer, cur->size); + entity->rx_list = cur->next; + entity->rx_size -= cur->size; + nr_pdcp_free_sdu(cur); + } + + /* deliver all SDUs starting from rx_reord up to discontinuity or end of list */ + count = entity->rx_reord; + while (entity->rx_list != NULL && count == entity->rx_list->count) { + nr_pdcp_sdu_t *cur = entity->rx_list; + entity->deliver_sdu(entity->deliver_sdu_data, entity, + cur->buffer, cur->size); + entity->rx_list = cur->next; + entity->rx_size -= cur->size; + nr_pdcp_free_sdu(cur); + count++; + } + + entity->rx_deliv = count; + + if (entity->rx_deliv < entity->rx_next) { + entity->rx_reord = entity->rx_next; + entity->t_reordering_start = entity->t_current; + } +} + +void nr_pdcp_entity_set_time(struct nr_pdcp_entity_t *entity, uint64_t now) +{ + entity->t_current = now; + + check_t_reordering(entity); +} + +void nr_pdcp_entity_delete(nr_pdcp_entity_t *entity) +{ + nr_pdcp_sdu_t *cur = entity->rx_list; + while (cur != NULL) { + nr_pdcp_sdu_t *next = cur->next; + nr_pdcp_free_sdu(cur); + cur = next; + } + if (entity->free_security != NULL) + entity->free_security(entity->security_context); + free(entity); +} + +nr_pdcp_entity_t *new_nr_pdcp_entity( + nr_pdcp_entity_type_t type, int is_gnb, int rb_id, void (*deliver_sdu)(void *deliver_sdu_data, struct nr_pdcp_entity_t *entity, char *buf, int size), @@ -54,52 +252,56 @@ nr_pdcp_entity_t *new_nr_pdcp_entity_drb_am( unsigned char *ciphering_key, unsigned char *integrity_key) { - nr_pdcp_entity_drb_am_t *ret; + nr_pdcp_entity_t *ret; - ret = calloc(1, sizeof(nr_pdcp_entity_drb_am_t)); + ret = calloc(1, sizeof(nr_pdcp_entity_t)); if (ret == NULL) { LOG_E(PDCP, "%s:%d:%s: out of memory\n", __FILE__, __LINE__, __FUNCTION__); exit(1); } - ret->common.recv_pdu = nr_pdcp_entity_drb_am_recv_pdu; - ret->common.recv_sdu = nr_pdcp_entity_drb_am_recv_sdu; - ret->common.set_integrity_key = nr_pdcp_entity_drb_am_set_integrity_key; + ret->type = type; - ret->common.delete = nr_pdcp_entity_drb_am_delete; + ret->recv_pdu = nr_pdcp_entity_recv_pdu; + ret->recv_sdu = nr_pdcp_entity_recv_sdu; + ret->set_integrity_key = nr_pdcp_entity_set_integrity_key; + ret->set_time = nr_pdcp_entity_set_time; - ret->common.deliver_sdu = deliver_sdu; - ret->common.deliver_sdu_data = deliver_sdu_data; + ret->delete = nr_pdcp_entity_delete; - ret->common.deliver_pdu = deliver_pdu; - ret->common.deliver_pdu_data = deliver_pdu_data; + ret->deliver_sdu = deliver_sdu; + ret->deliver_sdu_data = deliver_sdu_data; + + ret->deliver_pdu = deliver_pdu; + ret->deliver_pdu_data = deliver_pdu_data; ret->rb_id = rb_id; ret->sn_size = sn_size; ret->t_reordering = t_reordering; ret->discard_timer = discard_timer; - ret->common.maximum_nr_pdcp_sn = (1 << sn_size) - 1; + ret->sn_max = (1 << sn_size) - 1; + ret->window_size = 1 << (sn_size - 1); if (ciphering_key != NULL && ciphering_algorithm != 0) { if (ciphering_algorithm != 2) { LOG_E(PDCP, "FATAL: only nea2 supported for the moment\n"); exit(1); } - ret->common.has_ciphering = 1; - ret->common.ciphering_algorithm = ciphering_algorithm; - memcpy(ret->common.ciphering_key, ciphering_key, 16); + ret->has_ciphering = 1; + ret->ciphering_algorithm = ciphering_algorithm; + memcpy(ret->ciphering_key, ciphering_key, 16); - ret->common.security_context = nr_pdcp_security_nea2_init(ciphering_key); - ret->common.cipher = nr_pdcp_security_nea2_cipher; - ret->common.free_security = nr_pdcp_security_nea2_free_security; + ret->security_context = nr_pdcp_security_nea2_init(ciphering_key); + ret->cipher = nr_pdcp_security_nea2_cipher; + ret->free_security = nr_pdcp_security_nea2_free_security; } - ret->common.is_gnb = is_gnb; + ret->is_gnb = is_gnb; if (integrity_key != NULL) { printf("%s:%d:%s: TODO\n", __FILE__, __LINE__, __FUNCTION__); exit(1); } - return (nr_pdcp_entity_t *)ret; + return ret; } diff --git a/openair2/LAYER2/nr_pdcp/nr_pdcp_entity.h b/openair2/LAYER2/nr_pdcp/nr_pdcp_entity.h index 58d79835ec..36e7a540c4 100644 --- a/openair2/LAYER2/nr_pdcp/nr_pdcp_entity.h +++ b/openair2/LAYER2/nr_pdcp/nr_pdcp_entity.h @@ -19,18 +19,29 @@ * contact@openairinterface.org */ -#include - #ifndef _NR_PDCP_ENTITY_H_ #define _NR_PDCP_ENTITY_H_ +#include + +#include "nr_pdcp_sdu.h" + +typedef enum { + NR_PDCP_DRB_AM, + NR_PDCP_DRB_UM, + NR_PDCP_SRB +} nr_pdcp_entity_type_t; + typedef struct nr_pdcp_entity_t { + nr_pdcp_entity_type_t type; + /* functions provided by the PDCP module */ void (*recv_pdu)(struct nr_pdcp_entity_t *entity, char *buffer, int size); void (*recv_sdu)(struct nr_pdcp_entity_t *entity, char *buffer, int size, int sdu_id); void (*delete)(struct nr_pdcp_entity_t *entity); void (*set_integrity_key)(struct nr_pdcp_entity_t *entity, char *key); + void (*set_time)(struct nr_pdcp_entity_t *entity, uint64_t now); /* callbacks provided to the PDCP module */ void (*deliver_sdu)(void *deliver_sdu_data, struct nr_pdcp_entity_t *entity, @@ -39,9 +50,28 @@ typedef struct nr_pdcp_entity_t { void (*deliver_pdu)(void *deliver_pdu_data, struct nr_pdcp_entity_t *entity, char *buf, int size, int sdu_id); void *deliver_pdu_data; - int tx_hfn; - int next_nr_pdcp_tx_sn; - int maximum_nr_pdcp_sn; + + /* configuration variables */ + int rb_id; + + int sn_size; /* SN size, in bits */ + int t_reordering; /* unit: ms */ + int discard_timer; /* unit: ms */ + + int sn_max; /* (2^SN_size) - 1 */ + int window_size; /* 2^(SN_size - 1) */ + + /* state variables */ + uint32_t tx_next; + uint32_t rx_next; + uint32_t rx_deliv; + uint32_t rx_reord; + + /* set to the latest know time by the user of the module. Unit: ms */ + uint64_t t_current; + + /* timers (stores the ms of activation, 0 means not active) */ + int t_reordering_start; /* security */ int has_ciphering; @@ -60,18 +90,15 @@ typedef struct nr_pdcp_entity_t { * pdcp entity is for a gnb or an ue */ int is_gnb; + + /* rx management */ + nr_pdcp_sdu_t *rx_list; + int rx_size; + int rx_maxsize; } nr_pdcp_entity_t; -nr_pdcp_entity_t *new_nr_pdcp_entity_srb( - int is_gnb, int rb_id, - void (*deliver_sdu)(void *deliver_sdu_data, struct nr_pdcp_entity_t *entity, - char *buf, int size), - void *deliver_sdu_data, - void (*deliver_pdu)(void *deliver_pdu_data, struct nr_pdcp_entity_t *entity, - char *buf, int size, int sdu_id), - void *deliver_pdu_data); - -nr_pdcp_entity_t *new_nr_pdcp_entity_drb_am( +nr_pdcp_entity_t *new_nr_pdcp_entity( + nr_pdcp_entity_type_t type, int is_gnb, int rb_id, void (*deliver_sdu)(void *deliver_sdu_data, struct nr_pdcp_entity_t *entity, char *buf, int size), diff --git a/openair2/LAYER2/nr_pdcp/nr_pdcp_entity_drb_am.c b/openair2/LAYER2/nr_pdcp/nr_pdcp_entity_drb_am.c deleted file mode 100644 index 62881c184e..0000000000 --- a/openair2/LAYER2/nr_pdcp/nr_pdcp_entity_drb_am.c +++ /dev/null @@ -1,90 +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 - */ - -#include "nr_pdcp_entity_drb_am.h" - -#include -#include -#include -#include "common/utils/LOG/log.h" - -void nr_pdcp_entity_drb_am_recv_pdu(nr_pdcp_entity_t *_entity, char *buffer, int size) -{ - nr_pdcp_entity_drb_am_t *entity = (nr_pdcp_entity_drb_am_t *)_entity; - int sn; - - if (size < 3) abort(); - - if (!(buffer[0] & 0x80)) - LOG_E(PDCP, "%s:%d:%s: fatal\n", __FILE__, __LINE__, __FUNCTION__); - - sn = (((unsigned char)buffer[0] & 0x3) << 16) | - ((unsigned char)buffer[1] << 8) | - (unsigned char)buffer[2]; - - if (entity->common.has_ciphering) - entity->common.cipher(entity->common.security_context, (unsigned char *)buffer+3, size-3, - entity->rb_id, sn, entity->common.is_gnb ? 0 : 1); - - entity->common.deliver_sdu(entity->common.deliver_sdu_data, - (nr_pdcp_entity_t *)entity, buffer+3, size-3); -} - -void nr_pdcp_entity_drb_am_recv_sdu(nr_pdcp_entity_t *_entity, char *buffer, int size, - int sdu_id) -{ - nr_pdcp_entity_drb_am_t *entity = (nr_pdcp_entity_drb_am_t *)_entity; - int sn; - char buf[size+3]; - - sn = entity->common.next_nr_pdcp_tx_sn; - - entity->common.next_nr_pdcp_tx_sn++; - if (entity->common.next_nr_pdcp_tx_sn > entity->common.maximum_nr_pdcp_sn) { - entity->common.next_nr_pdcp_tx_sn = 0; - entity->common.tx_hfn++; - } - - buf[0] = 0x80 | ((sn >> 16) & 0x3); - buf[1] = (sn >> 8) & 0xff; - buf[2] = sn & 0xff; - memcpy(buf+3, buffer, size); - - if (entity->common.has_ciphering) - entity->common.cipher(entity->common.security_context, (unsigned char *)buf+3, size, - entity->rb_id, sn, entity->common.is_gnb ? 1 : 0); - - entity->common.deliver_pdu(entity->common.deliver_pdu_data, - (nr_pdcp_entity_t *)entity, buf, size+3, sdu_id); -} - -void nr_pdcp_entity_drb_am_set_integrity_key(nr_pdcp_entity_t *_entity, char *key) -{ - /* nothing to do */ -} - -void nr_pdcp_entity_drb_am_delete(nr_pdcp_entity_t *_entity) -{ - nr_pdcp_entity_drb_am_t *entity = (nr_pdcp_entity_drb_am_t *)_entity; - if (entity->common.free_security != NULL) - entity->common.free_security(entity->common.security_context); - free(entity); -} diff --git a/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.c b/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.c index f14d25b145..ec48b0adae 100644 --- a/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.c +++ b/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.c @@ -24,6 +24,7 @@ #endif #include "asn1_utils.h" #include "nr_pdcp_ue_manager.h" +#include "nr_pdcp_timer_thread.h" #include "NR_RadioBearerConfig.h" #include "NR_RLC-BearerConfig.h" #include "NR_RLC-Config.h" @@ -41,6 +42,11 @@ static nr_pdcp_ue_manager_t *nr_pdcp_ue_manager; +/* TODO: handle time a bit more properly */ +static uint64_t nr_pdcp_current_time; +static int nr_pdcp_current_time_last_frame; +static int nr_pdcp_current_time_last_subframe; + /* necessary globals for OAI, not used internally */ hash_table_t *pdcp_coll_p; static uint64_t pdcp_optmask; @@ -339,6 +345,8 @@ void pdcp_layer_init(void) nr_pdcp_ue_manager = new_nr_pdcp_ue_manager(1); init_nr_rlc_data_req_queue(); + + nr_pdcp_init_timer_thread(nr_pdcp_ue_manager); } #include "nfapi/oai_integration/vendor_ext.h" @@ -625,11 +633,11 @@ static void add_drb_am(int is_gnb, int rnti, struct NR_DRB_ToAddMod *s, LOG_D(PDCP, "%s:%d:%s: warning DRB %d already exist for ue %d, do nothing\n", __FILE__, __LINE__, __FUNCTION__, drb_id, rnti); } else { - pdcp_drb = new_nr_pdcp_entity_drb_am(is_gnb, drb_id, - deliver_sdu_drb, ue, deliver_pdu_drb, ue, - sn_size_dl, t_reordering, discard_timer, - ciphering_algorithm, integrity_algorithm, - ciphering_key, integrity_key); + pdcp_drb = new_nr_pdcp_entity(NR_PDCP_DRB_AM, is_gnb, drb_id, + deliver_sdu_drb, ue, deliver_pdu_drb, ue, + sn_size_dl, t_reordering, discard_timer, + ciphering_algorithm, integrity_algorithm, + ciphering_key, integrity_key); nr_pdcp_ue_add_drb_pdcp_entity(ue, drb_id, pdcp_drb); LOG_D(PDCP, "%s:%d:%s: added drb %d to ue rnti %x\n", __FILE__, __LINE__, __FUNCTION__, drb_id, rnti); @@ -768,7 +776,7 @@ void nr_DRB_preconfiguration(uint16_t crnti) drb_ToAddMod->pdcp_Config = calloc(1,sizeof(*drb_ToAddMod->pdcp_Config)); drb_ToAddMod->pdcp_Config->drb = calloc(1,sizeof(*drb_ToAddMod->pdcp_Config->drb)); drb_ToAddMod->pdcp_Config->drb->discardTimer = calloc(1,sizeof(*drb_ToAddMod->pdcp_Config->drb->discardTimer)); - *drb_ToAddMod->pdcp_Config->drb->discardTimer=NR_PDCP_Config__drb__discardTimer_ms30; + *drb_ToAddMod->pdcp_Config->drb->discardTimer=NR_PDCP_Config__drb__discardTimer_infinity; drb_ToAddMod->pdcp_Config->drb->pdcp_SN_SizeUL = calloc(1,sizeof(*drb_ToAddMod->pdcp_Config->drb->pdcp_SN_SizeUL)); *drb_ToAddMod->pdcp_Config->drb->pdcp_SN_SizeUL = NR_PDCP_Config__drb__pdcp_SN_SizeUL_len12bits; drb_ToAddMod->pdcp_Config->drb->pdcp_SN_SizeDL = calloc(1,sizeof(*drb_ToAddMod->pdcp_Config->drb->pdcp_SN_SizeDL)); @@ -976,3 +984,14 @@ void pdcp_mbms_run ( const protocol_ctxt_t *const ctxt_pP){ /* nothing to do */ } + +void nr_pdcp_tick(int frame, int subframe) +{ + if (frame != nr_pdcp_current_time_last_frame || + subframe != nr_pdcp_current_time_last_subframe) { + nr_pdcp_current_time_last_frame = frame; + nr_pdcp_current_time_last_subframe = subframe; + nr_pdcp_current_time++; + nr_pdcp_wakeup_timer_thread(nr_pdcp_current_time); + } +} diff --git a/openair2/LAYER2/nr_pdcp/nr_pdcp_sdu.c b/openair2/LAYER2/nr_pdcp/nr_pdcp_sdu.c new file mode 100644 index 0000000000..47d95156e3 --- /dev/null +++ b/openair2/LAYER2/nr_pdcp/nr_pdcp_sdu.c @@ -0,0 +1,78 @@ +/* + * 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_pdcp_sdu.h" + +#include +#include + +nr_pdcp_sdu_t *nr_pdcp_new_sdu(uint32_t count, char *buffer, int size) +{ + nr_pdcp_sdu_t *ret = calloc(1, sizeof(nr_pdcp_sdu_t)); + if (ret == NULL) + exit(1); + ret->count = count; + ret->buffer = malloc(size); + if (ret->buffer == NULL) + exit(1); + memcpy(ret->buffer, buffer, size); + ret->size = size; + return ret; +} + +nr_pdcp_sdu_t *nr_pdcp_sdu_list_add(nr_pdcp_sdu_t *l, nr_pdcp_sdu_t *sdu) +{ + nr_pdcp_sdu_t head; + nr_pdcp_sdu_t *cur; + nr_pdcp_sdu_t *prev; + + head.next = l; + cur = l; + prev = &head; + + /* order is by 'count' */ + while (cur != NULL) { + /* check if 'sdu' is before 'cur' in the list */ + if (sdu->count < cur->count) + break; + prev = cur; + cur = cur->next; + } + prev->next = sdu; + sdu->next = cur; + return head.next; +} + +int nr_pdcp_sdu_in_list(nr_pdcp_sdu_t *l, uint32_t count) +{ + while (l != NULL) { + if (l->count == count) + return 1; + l = l->next; + } + return 0; +} + +void nr_pdcp_free_sdu(nr_pdcp_sdu_t *sdu) +{ + free(sdu->buffer); + free(sdu); +} diff --git a/openair2/LAYER2/nr_pdcp/nr_pdcp_entity_drb_am.h b/openair2/LAYER2/nr_pdcp/nr_pdcp_sdu.h similarity index 58% rename from openair2/LAYER2/nr_pdcp/nr_pdcp_entity_drb_am.h rename to openair2/LAYER2/nr_pdcp/nr_pdcp_sdu.h index d7c42e6a62..3d4e50a4ce 100644 --- a/openair2/LAYER2/nr_pdcp/nr_pdcp_entity_drb_am.h +++ b/openair2/LAYER2/nr_pdcp/nr_pdcp_sdu.h @@ -19,23 +19,21 @@ * contact@openairinterface.org */ -#ifndef _NR_PDCP_ENTITY_DRB_AM_H_ -#define _NR_PDCP_ENTITY_DRB_AM_H_ +#ifndef _NR_PDCP_SDU_H_ +#define _NR_PDCP_SDU_H_ -#include "nr_pdcp_entity.h" +#include -typedef struct { - nr_pdcp_entity_t common; - int rb_id; - int sn_size; /* unit: bits */ - int t_reordering; /* unit: ms */ - int discard_timer; /* unit: ms, -1 means infinity */ -} nr_pdcp_entity_drb_am_t; +typedef struct nr_pdcp_sdu_t { + uint32_t count; + char *buffer; + int size; + struct nr_pdcp_sdu_t *next; +} nr_pdcp_sdu_t; -void nr_pdcp_entity_drb_am_recv_pdu(nr_pdcp_entity_t *entity, char *buffer, int size); -void nr_pdcp_entity_drb_am_recv_sdu(nr_pdcp_entity_t *entity, char *buffer, int size, - int sdu_id); -void nr_pdcp_entity_drb_am_set_integrity_key(nr_pdcp_entity_t *entity, char *key); -void nr_pdcp_entity_drb_am_delete(nr_pdcp_entity_t *entity); +nr_pdcp_sdu_t *nr_pdcp_new_sdu(uint32_t count, char *buffer, int size); +nr_pdcp_sdu_t *nr_pdcp_sdu_list_add(nr_pdcp_sdu_t *l, nr_pdcp_sdu_t *sdu); +int nr_pdcp_sdu_in_list(nr_pdcp_sdu_t *l, uint32_t count); +void nr_pdcp_free_sdu(nr_pdcp_sdu_t *sdu); -#endif /* _NR_PDCP_ENTITY_DRB_AM_H_ */ +#endif /* _NR_PDCP_SDU_H_ */ diff --git a/openair2/LAYER2/nr_pdcp/nr_pdcp_timer_thread.c b/openair2/LAYER2/nr_pdcp/nr_pdcp_timer_thread.c new file mode 100644 index 0000000000..36e9b16024 --- /dev/null +++ b/openair2/LAYER2/nr_pdcp/nr_pdcp_timer_thread.c @@ -0,0 +1,87 @@ +/* + * 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_pdcp_timer_thread.h" + +#include +#include +#include + +#include "LOG/log.h" + +static pthread_mutex_t timer_thread_mutex = PTHREAD_MUTEX_INITIALIZER; +static pthread_cond_t timer_thread_cond = PTHREAD_COND_INITIALIZER; +static volatile uint64_t timer_thread_curtime = 0; + +static void *nr_pdcp_timer_thread(void *_nr_pdcp_ue_manager) +{ + nr_pdcp_ue_manager_t *nr_pdcp_ue_manager = (nr_pdcp_ue_manager_t *)_nr_pdcp_ue_manager; + nr_pdcp_ue_t **ue_list; + int ue_count; + int i; + int j; + uint64_t curtime = 0; + + while (1) { + if (pthread_mutex_lock(&timer_thread_mutex) != 0) abort(); + while (curtime == timer_thread_curtime) + if (pthread_cond_wait(&timer_thread_cond, &timer_thread_mutex) != 0) abort(); + curtime = timer_thread_curtime; + if (pthread_mutex_unlock(&timer_thread_mutex) != 0) abort(); + + nr_pdcp_manager_lock(nr_pdcp_ue_manager); + + ue_list = nr_pdcp_manager_get_ue_list(nr_pdcp_ue_manager); + ue_count = nr_pdcp_manager_get_ue_count(nr_pdcp_ue_manager); + for (i = 0; i < ue_count; i++) { + for (j = 0; j < 2; j++) { + if (ue_list[i]->srb[j] != NULL) + ue_list[i]->srb[j]->set_time(ue_list[i]->srb[j], curtime); + } + for (j = 0; j < 5; j++) { + if (ue_list[i]->drb[j] != NULL) + ue_list[i]->drb[j]->set_time(ue_list[i]->drb[j], curtime); + } + } + + nr_pdcp_manager_unlock(nr_pdcp_ue_manager); + } + + return NULL; +} + +void nr_pdcp_init_timer_thread(nr_pdcp_ue_manager_t *nr_pdcp_ue_manager) +{ + pthread_t t; + + if (pthread_create(&t, NULL, nr_pdcp_timer_thread, nr_pdcp_ue_manager) != 0) { + LOG_E(PDCP, "%s:%d:%s: fatal\n", __FILE__, __LINE__, __FUNCTION__); + exit(1); + } +} + +void nr_pdcp_wakeup_timer_thread(uint64_t time) +{ + if (pthread_mutex_lock(&timer_thread_mutex)) abort(); + timer_thread_curtime = time; + if (pthread_cond_broadcast(&timer_thread_cond)) abort(); + if (pthread_mutex_unlock(&timer_thread_mutex)) abort(); +} diff --git a/openair2/LAYER2/nr_pdcp/nr_pdcp_timer_thread.h b/openair2/LAYER2/nr_pdcp/nr_pdcp_timer_thread.h new file mode 100644 index 0000000000..db8282f940 --- /dev/null +++ b/openair2/LAYER2/nr_pdcp/nr_pdcp_timer_thread.h @@ -0,0 +1,32 @@ +/* + * 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_PDCP_TIMER_THREAD_H_ +#define _NR_PDCP_TIMER_THREAD_H_ + +#include "nr_pdcp_ue_manager.h" + +#include + +void nr_pdcp_init_timer_thread(nr_pdcp_ue_manager_t *nr_pdcp_ue_manager); +void nr_pdcp_wakeup_timer_thread(uint64_t time); + +#endif /* _NR_PDCP_TIMER_THREAD_H_ */ diff --git a/openair2/LAYER2/nr_pdcp/nr_pdcp_ue_manager.c b/openair2/LAYER2/nr_pdcp/nr_pdcp_ue_manager.c index ca51da3d5f..f89a18f94e 100644 --- a/openair2/LAYER2/nr_pdcp/nr_pdcp_ue_manager.c +++ b/openair2/LAYER2/nr_pdcp/nr_pdcp_ue_manager.c @@ -189,6 +189,20 @@ void nr_pdcp_ue_add_drb_pdcp_entity(nr_pdcp_ue_t *ue, int drb_id, nr_pdcp_entity ue->drb[drb_id] = entity; } +/* must be called with lock acquired */ +nr_pdcp_ue_t **nr_pdcp_manager_get_ue_list(nr_pdcp_ue_manager_t *_m) +{ + nr_pdcp_ue_manager_internal_t *m = _m; + return m->ue_list; +} + +/* must be called with lock acquired */ +int nr_pdcp_manager_get_ue_count(nr_pdcp_ue_manager_t *_m) +{ + nr_pdcp_ue_manager_internal_t *m = _m; + return m->ue_count; +} + int nr_pdcp_get_first_rnti(nr_pdcp_ue_manager_t *_m) { nr_pdcp_ue_manager_internal_t *m = _m; diff --git a/openair2/LAYER2/nr_pdcp/nr_pdcp_ue_manager.h b/openair2/LAYER2/nr_pdcp/nr_pdcp_ue_manager.h index 0de2f024b3..3329f856b7 100644 --- a/openair2/LAYER2/nr_pdcp/nr_pdcp_ue_manager.h +++ b/openair2/LAYER2/nr_pdcp/nr_pdcp_ue_manager.h @@ -46,6 +46,9 @@ void nr_pdcp_manager_unlock(nr_pdcp_ue_manager_t *m); nr_pdcp_ue_t *nr_pdcp_manager_get_ue(nr_pdcp_ue_manager_t *m, int rnti); void nr_pdcp_manager_remove_ue(nr_pdcp_ue_manager_t *m, int rnti); +nr_pdcp_ue_t **nr_pdcp_manager_get_ue_list(nr_pdcp_ue_manager_t *_m); +int nr_pdcp_manager_get_ue_count(nr_pdcp_ue_manager_t *_m); + /***********************************************************************/ /* ue functions */ /***********************************************************************/ diff --git a/openair2/NR_PHY_INTERFACE/NR_IF_Module.c b/openair2/NR_PHY_INTERFACE/NR_IF_Module.c index 2e0abda556..5a090d4ffd 100644 --- a/openair2/NR_PHY_INTERFACE/NR_IF_Module.c +++ b/openair2/NR_PHY_INTERFACE/NR_IF_Module.c @@ -43,7 +43,6 @@ NR_IF_Module_t *if_inst[MAX_IF_MODULES]; NR_Sched_Rsp_t Sched_INFO[MAX_IF_MODULES][MAX_NUM_CCs]; - extern int oai_nfapi_harq_indication(nfapi_harq_indication_t *harq_ind); extern int oai_nfapi_crc_indication(nfapi_crc_indication_t *crc_ind); extern int oai_nfapi_cqi_indication(nfapi_cqi_indication_t *cqi_ind); @@ -54,14 +53,7 @@ extern uint16_t sf_ahead; extern uint16_t sl_ahead; 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) { - //LOG_D(PHY,"UL_info->crc_ind.crc_indication_body.number_of_crcs:%d CRC_IND:SFN/SF:%d\n", UL_info->crc_ind.crc_indication_body.number_of_crcs, NFAPI_SFNSF2DEC(UL_info->crc_ind.sfn_sf)); - oai_nfapi_nr_rach_indication(&UL_info->rach_ind); - UL_info->rach_ind.number_of_pdus = 0; - } - } - else { + if (UL_info->rach_ind.number_of_pdus>0) { LOG_I(MAC,"UL_info[Frame %d, Slot %d] Calling initiate_ra_proc RACH:SFN/SLOT:%d/%d\n",UL_info->frame,UL_info->slot, UL_info->rach_ind.sfn,UL_info->rach_ind.slot); int npdus = UL_info->rach_ind.number_of_pdus; @@ -82,19 +74,10 @@ void handle_nr_rach(NR_UL_IND_t *UL_info) { } } } -} void handle_nr_uci(NR_UL_IND_t *UL_info) -{ - if(NFAPI_MODE == NFAPI_MODE_PNF) { - if (UL_info->uci_ind.num_ucis>0) { - //LOG_D(PHY,"UL_info->crc_ind.crc_indication_body.number_of_crcs:%d CRC_IND:SFN/SF:%d\n", UL_info->crc_ind.crc_indication_body.number_of_crcs, NFAPI_SFNSF2DEC(UL_info->crc_ind.sfn_sf)); - //oai_nfapi_nr_uci_indication(&UL_info->uci_ind); - UL_info->uci_ind.num_ucis = 0; - } - } - else { +{ const module_id_t mod_id = UL_info->module_id; const frame_t frame = UL_info->frame; const sub_frame_t slot = UL_info->slot; @@ -112,6 +95,7 @@ void handle_nr_uci(NR_UL_IND_t *UL_info) handle_nr_uci_pucch_0_1(mod_id, frame, slot, uci_pdu); break; } + case NFAPI_NR_UCI_FORMAT_2_3_4_PDU_TYPE: { const nfapi_nr_uci_pucch_pdu_format_2_3_4_t *uci_pdu = &uci_list[i].pucch_pdu_format_2_3_4; handle_nr_uci_pucch_2_3_4(mod_id, frame, slot, uci_pdu); @@ -126,24 +110,10 @@ void handle_nr_uci(NR_UL_IND_t *UL_info) // NOTE: we just assume it is BWP ID 1, to be revised for multiple BWPs RC.nrmac[mod_id]->pucch_index_used[1][slot] = 0; } -} + void handle_nr_ulsch(NR_UL_IND_t *UL_info) -{ - if(NFAPI_MODE == NFAPI_MODE_PNF) { - if (UL_info->crc_ind.number_crcs>0) { - //LOG_D(PHY,"UL_info->crc_ind.crc_indication_body.number_of_crcs:%d CRC_IND:SFN/SF:%d\n", UL_info->crc_ind.crc_indication_body.number_of_crcs, NFAPI_SFNSF2DEC(UL_info->crc_ind.sfn_sf)); - oai_nfapi_nr_crc_indication(&UL_info->crc_ind); - UL_info->crc_ind.number_crcs = 0; - } - - if (UL_info->rx_ind.number_of_pdus>0) { - //LOG_D(PHY,"UL_info->rx_ind.number_of_pdus:%d RX_IND:SFN/SF:%d\n", UL_info->rx_ind.rx_indication_body.number_of_pdus, NFAPI_SFNSF2DEC(UL_info->rx_ind.sfn_sf)); - oai_nfapi_nr_rx_data_indication(&UL_info->rx_ind); - UL_info->rx_ind.number_of_pdus = 0; - } - } - else { +{ if (UL_info->rx_ind.number_of_pdus > 0 && UL_info->crc_ind.number_crcs > 0) { for (int i = 0; i < UL_info->rx_ind.number_of_pdus; i++) { for (int j = 0; j < UL_info->crc_ind.number_crcs; j++) { @@ -169,16 +139,17 @@ void handle_nr_ulsch(NR_UL_IND_t *UL_info) crc->tb_crc_status); /* if CRC passes, pass PDU, otherwise pass NULL as error indication */ - nr_rx_sdu(UL_info->module_id, - UL_info->CC_id, - UL_info->rx_ind.sfn, - UL_info->rx_ind.slot, - rx->rnti, - crc->tb_crc_status ? NULL : rx->pdu, - rx->pdu_length, - rx->timing_advance, - rx->ul_cqi, - rx->rssi); + //Gokul + // nr_rx_sdu(UL_info->module_id, + // UL_info->CC_id, + // UL_info->rx_ind.sfn, + // UL_info->rx_ind.slot, + // rx->rnti, + // crc->tb_crc_status ? NULL : rx->pdu, + // rx->pdu_length, + // rx->timing_advance, + // rx->ul_cqi, + // rx->rssi); //handle_nr_ul_harq(UL_info->module_id, UL_info->frame, UL_info->slot, crc); break; } // for (j=0;jcrc_ind.number_crcs;j++) @@ -198,11 +169,11 @@ void handle_nr_ulsch(NR_UL_IND_t *UL_info) UL_info->crc_ind.number_crcs, UL_info->rx_ind.sfn, UL_info->rx_ind.slot); - } } } void NR_UL_indication(NR_UL_IND_t *UL_info) { + //printf("Inside NR UL Indication. \n"); AssertFatal(UL_info!=NULL,"UL_INFO is null\n"); #ifdef DUMP_FAPI dump_ul(UL_info); @@ -274,10 +245,7 @@ void NR_UL_indication(NR_UL_IND_t *UL_info) { ifi->NR_Schedule_response(sched_info); } - LOG_D(PHY,"NR_Schedule_response: SFN_SF:%d%d dl_pdus:%d\n", - sched_info->frame, - sched_info->slot, - sched_info->DL_req->dl_tti_request_body.nPDUs); + } } } diff --git a/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c b/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c index edaef6d1ce..51d279b7d1 100644 --- a/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c +++ b/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c @@ -62,7 +62,7 @@ int handle_bcch_bch(module_id_t module_id, int cc_id, unsigned int gNB_index, ui // L2 Abstraction Layer int handle_bcch_dlsch(module_id_t module_id, int cc_id, unsigned int gNB_index, uint32_t sibs_mask, uint8_t *pduP, uint32_t pdu_len){ - return nr_ue_decode_sib1(module_id, cc_id, gNB_index, sibs_mask, pduP, pdu_len); + return nr_ue_decode_BCCH_DL_SCH(module_id, cc_id, gNB_index, sibs_mask, pduP, pdu_len); } // L2 Abstraction Layer @@ -90,7 +90,7 @@ int nr_ue_ul_indication(nr_uplink_indication_t *ul_info){ ret = nr_ue_scheduler(NULL, ul_info); - if (is_nr_UL_slot(mac->scc, ul_info->slot_tx) && get_softmodem_params()->do_ra) + if (is_nr_UL_slot(mac->scc, ul_info->slot_tx, mac->frame_type) && get_softmodem_params()->do_ra) nr_ue_prach_scheduler(module_id, ul_info->frame_tx, ul_info->slot_tx, ul_info->thread_id); switch(ret){ diff --git a/openair2/RRC/LTE/rrc_eNB_S1AP.c b/openair2/RRC/LTE/rrc_eNB_S1AP.c index d34b4164a2..0e6d5b580f 100644 --- a/openair2/RRC/LTE/rrc_eNB_S1AP.c +++ b/openair2/RRC/LTE/rrc_eNB_S1AP.c @@ -782,21 +782,37 @@ rrc_eNB_send_S1AP_NAS_FIRST_REQ( S1AP_NAS_FIRST_REQ (message_p).ue_identity.presenceMask |= UE_IDENTITIES_gummei; if (r_mme->plmn_Identity != NULL) { - if ((r_mme->plmn_Identity->mcc != NULL) && (r_mme->plmn_Identity->mcc->list.count > 0)) { - /* Use first indicated PLMN MCC if it is defined */ - S1AP_NAS_FIRST_REQ (message_p).ue_identity.gummei.mcc = *r_mme->plmn_Identity->mcc->list.array[selected_plmn_identity]; + if ((r_mme->plmn_Identity->mcc != NULL) && (r_mme->plmn_Identity->mcc->list.count == 3)) + { + S1AP_NAS_FIRST_REQ (message_p).ue_identity.gummei.mcc = (*r_mme->plmn_Identity->mcc->list.array[0] & 0xf) * 100 + + (*r_mme->plmn_Identity->mcc->list.array[1] & 0xf) * 10 + + (*r_mme->plmn_Identity->mcc->list.array[2] & 0xf); LOG_I(S1AP, "[eNB %d] Build S1AP_NAS_FIRST_REQ adding in s_TMSI: GUMMEI MCC %u ue %x\n", ctxt_pP->module_id, S1AP_NAS_FIRST_REQ (message_p).ue_identity.gummei.mcc, ue_context_pP->ue_context.rnti); } - - if (r_mme->plmn_Identity->mnc.list.count > 0) { - /* Use first indicated PLMN MNC if it is defined */ - S1AP_NAS_FIRST_REQ (message_p).ue_identity.gummei.mnc = *r_mme->plmn_Identity->mnc.list.array[selected_plmn_identity]; - LOG_I(S1AP, "[eNB %d] Build S1AP_NAS_FIRST_REQ adding in s_TMSI: GUMMEI MNC %u ue %x\n", + if(r_mme->plmn_Identity->mnc.list.count == 3) + { + S1AP_NAS_FIRST_REQ (message_p).ue_identity.gummei.mnc = (*r_mme->plmn_Identity->mnc.list.array[0] & 0xf) * 100 + + (*r_mme->plmn_Identity->mnc.list.array[1] & 0xf) * 10 + + (*r_mme->plmn_Identity->mnc.list.array[2] & 0xf); + S1AP_NAS_FIRST_REQ (message_p).ue_identity.gummei.mnc_len = 3; + LOG_I(S1AP, "[eNB %d] Build S1AP_NAS_FIRST_REQ adding in s_TMSI: GUMMEI MNC %u %udigit ue %x\n", ctxt_pP->module_id, S1AP_NAS_FIRST_REQ (message_p).ue_identity.gummei.mnc, + S1AP_NAS_FIRST_REQ (message_p).ue_identity.gummei.mnc_len, + ue_context_pP->ue_context.rnti); + } + else if(r_mme->plmn_Identity->mnc.list.count == 2) + { + S1AP_NAS_FIRST_REQ (message_p).ue_identity.gummei.mnc = (*r_mme->plmn_Identity->mnc.list.array[0] & 0xf) * 10 + + (*r_mme->plmn_Identity->mnc.list.array[1] & 0xf); + S1AP_NAS_FIRST_REQ (message_p).ue_identity.gummei.mnc_len = 2; + LOG_I(S1AP, "[eNB %d] Build S1AP_NAS_FIRST_REQ adding in s_TMSI: GUMMEI MNC %u %udigit ue %x\n", + ctxt_pP->module_id, + S1AP_NAS_FIRST_REQ (message_p).ue_identity.gummei.mnc, + S1AP_NAS_FIRST_REQ (message_p).ue_identity.gummei.mnc_len, ue_context_pP->ue_context.rnti); } } else { // end if plmn_Identity != NULL diff --git a/openair2/RRC/NR/nr_rrc_proto.h b/openair2/RRC/NR/nr_rrc_proto.h index 6d876a0eef..5aafbaee4c 100644 --- a/openair2/RRC/NR/nr_rrc_proto.h +++ b/openair2/RRC/NR/nr_rrc_proto.h @@ -79,17 +79,19 @@ void fill_default_coresetZero(NR_ControlResourceSet_t *coreset0, NR_ServingCellC void fill_default_searchSpaceZero(NR_SearchSpace_t *ss0); void fill_default_secondaryCellGroup(NR_ServingCellConfigCommon_t *servingcellconfigcommon, - NR_CellGroupConfig_t *secondaryCellGroup, - int scg_id, - int servCellIndex, - int n_physical_antenna_ports, - int initial_csi_index); + NR_ServingCellConfig_t *servingcellconfigdedicated, + NR_CellGroupConfig_t *secondaryCellGroup, + int scg_id, + int servCellIndex, + int n_physical_antenna_ports, + int initial_csi_index); void fill_default_reconfig(NR_ServingCellConfigCommon_t *servingcellconfigcommon, - NR_RRCReconfiguration_IEs_t *reconfig, - NR_CellGroupConfig_t *secondaryCellGroup, - int n_physical_antenna_ports, - int initial_csi_index); + NR_ServingCellConfig_t *servingcellconfigdedicated, + NR_RRCReconfiguration_IEs_t *reconfig, + NR_CellGroupConfig_t *secondaryCellGroup, + int n_physical_antenna_ports, + int initial_csi_index); void fill_default_rbconfig(NR_RadioBearerConfig_t *rbconfig, int eps_bearer_id, int rb_id, diff --git a/openair2/RRC/NR/nr_rrc_types.h b/openair2/RRC/NR/nr_rrc_types.h index 02495591a9..61f90e3572 100644 --- a/openair2/RRC/NR/nr_rrc_types.h +++ b/openair2/RRC/NR/nr_rrc_types.h @@ -32,11 +32,11 @@ #define RRC_TYPES_NR_H_ typedef enum Rrc_State_NR_e { - RRC_STATE_INACTIVE_NR=0, - RRC_STATE_IDLE_NR, + RRC_STATE_IDLE_NR=0, + RRC_STATE_INACTIVE_NR, RRC_STATE_CONNECTED_NR, - RRC_STATE_FIRST_NR = RRC_STATE_INACTIVE_NR, + RRC_STATE_FIRST_NR = RRC_STATE_IDLE_NR, RRC_STATE_LAST_NR = RRC_STATE_CONNECTED_NR, } Rrc_State_NR_t; diff --git a/openair2/RRC/NR/rrc_gNB.c b/openair2/RRC/NR/rrc_gNB.c index 6d430d7223..802337257b 100755 --- a/openair2/RRC/NR/rrc_gNB.c +++ b/openair2/RRC/NR/rrc_gNB.c @@ -277,6 +277,8 @@ static void init_NR_SI(gNB_RRC_INST *rrc, gNB_RrcConfigurationReq *configuration parse_CG_ConfigInfo(rrc,CG_ConfigInfo,NULL); } else { struct rrc_gNB_ue_context_s *ue_context_p = rrc_gNB_allocate_new_UE_context(rrc); + ue_context_p->ue_context.spCellConfig = calloc(1, sizeof(struct NR_SpCellConfig)); + ue_context_p->ue_context.spCellConfig->spCellConfigDedicated = configuration->scd; LOG_I(NR_RRC,"Adding new user (%p)\n",ue_context_p); rrc_add_nsa_user(rrc,ue_context_p,NULL); } @@ -631,7 +633,7 @@ rrc_gNB_generate_defaultRRCReconfiguration( DRB_config->pdcp_Config = calloc(1, sizeof(*DRB_config->pdcp_Config)); DRB_config->pdcp_Config->drb = calloc(1,sizeof(*DRB_config->pdcp_Config->drb)); DRB_config->pdcp_Config->drb->discardTimer = calloc(1, sizeof(*DRB_config->pdcp_Config->drb->discardTimer)); - *DRB_config->pdcp_Config->drb->discardTimer = NR_PDCP_Config__drb__discardTimer_ms30; + *DRB_config->pdcp_Config->drb->discardTimer = NR_PDCP_Config__drb__discardTimer_infinity; DRB_config->pdcp_Config->drb->pdcp_SN_SizeUL = calloc(1, sizeof(*DRB_config->pdcp_Config->drb->pdcp_SN_SizeUL)); *DRB_config->pdcp_Config->drb->pdcp_SN_SizeUL = NR_PDCP_Config__drb__pdcp_SN_SizeUL_len18bits; DRB_config->pdcp_Config->drb->pdcp_SN_SizeDL = calloc(1, sizeof(*DRB_config->pdcp_Config->drb->pdcp_SN_SizeDL)); diff --git a/openair2/RRC/NR/rrc_gNB_nsa.c b/openair2/RRC/NR/rrc_gNB_nsa.c index 5ea02c7832..e9741aaf78 100644 --- a/openair2/RRC/NR/rrc_gNB_nsa.c +++ b/openair2/RRC/NR/rrc_gNB_nsa.c @@ -238,11 +238,21 @@ void rrc_add_nsa_user(gNB_RRC_INST *rrc,struct rrc_gNB_ue_context_s *ue_context_ cipher_algo, NR_SecurityConfig__keyToUse_secondary); } - fill_default_reconfig(carrier->servingcellconfigcommon, + if (ue_context_p->ue_context.spCellConfig) { + fill_default_reconfig(carrier->servingcellconfigcommon, + ue_context_p->ue_context.spCellConfig->spCellConfigDedicated, reconfig_ies, ue_context_p->ue_context.secondaryCellGroup, carrier->pdsch_AntennaPorts, carrier->initial_csi_index[rrc->Nb_ue]); + } else { + fill_default_reconfig(carrier->servingcellconfigcommon, + NULL, + reconfig_ies, + ue_context_p->ue_context.secondaryCellGroup, + carrier->pdsch_AntennaPorts, + carrier->initial_csi_index[rrc->Nb_ue]); + } ue_context_p->ue_id_rnti = ue_context_p->ue_context.secondaryCellGroup->spCellConfig->reconfigurationWithSync->newUE_Identity; NR_CG_Config_t *CG_Config = calloc(1,sizeof(*CG_Config)); memset((void *)CG_Config,0,sizeof(*CG_Config)); @@ -327,7 +337,7 @@ void rrc_add_nsa_user(gNB_RRC_INST *rrc,struct rrc_gNB_ue_context_s *ue_context_ 1024); X2AP_ENDC_SGNB_ADDITION_REQ_ACK(msg).rrc_buffer_size = (enc_rval.encoded+7)>>3; itti_send_msg_to_task(TASK_X2AP, ENB_MODULE_ID_TO_INSTANCE(0), msg); //Check right id instead of hardcoding - } else if (get_softmodem_params()->do_ra) { + } else if (get_softmodem_params()->do_ra || get_softmodem_params()->sa) { PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, rrc->module_id, GNB_FLAG_YES, ue_context_p->ue_id_rnti, 0, 0,rrc->module_id); } diff --git a/openair2/RRC/NR/rrc_gNB_reconfig.c b/openair2/RRC/NR/rrc_gNB_reconfig.c index ab3f192276..8f3993229e 100644 --- a/openair2/RRC/NR/rrc_gNB_reconfig.c +++ b/openair2/RRC/NR/rrc_gNB_reconfig.c @@ -31,6 +31,7 @@ #define RRC_GNB_NSA_C #include "NR_ServingCellConfigCommon.h" +#include "NR_ServingCellConfig.h" #include "NR_RRCReconfiguration.h" #include "NR_RRCReconfiguration-IEs.h" #include "NR_CellGroupConfig.h" @@ -135,7 +136,7 @@ void fill_default_searchSpaceZero(NR_SearchSpace_t *ss0) { // FIXME: update values from TS38.213 Section 10.1 Table 10.1-1: CCE aggregation levels and maximum number of PDCCH candidates per CCE aggregation level for CSS sets configured by searchSpaceSIB1 ss0->nrofCandidates->aggregationLevel1 = NR_SearchSpace__nrofCandidates__aggregationLevel1_n0; ss0->nrofCandidates->aggregationLevel2 = NR_SearchSpace__nrofCandidates__aggregationLevel2_n0; - ss0->nrofCandidates->aggregationLevel4 = NR_SearchSpace__nrofCandidates__aggregationLevel4_n1; + ss0->nrofCandidates->aggregationLevel4 = NR_SearchSpace__nrofCandidates__aggregationLevel4_n2; ss0->nrofCandidates->aggregationLevel8 = NR_SearchSpace__nrofCandidates__aggregationLevel8_n0; ss0->nrofCandidates->aggregationLevel16 = NR_SearchSpace__nrofCandidates__aggregationLevel16_n0; @@ -143,6 +144,7 @@ void fill_default_searchSpaceZero(NR_SearchSpace_t *ss0) { } void fill_default_secondaryCellGroup(NR_ServingCellConfigCommon_t *servingcellconfigcommon, + NR_ServingCellConfig_t *servingcellconfigdedicated, NR_CellGroupConfig_t *secondaryCellGroup, int scg_id, int servCellIndex, @@ -172,7 +174,7 @@ void fill_default_secondaryCellGroup(NR_ServingCellConfigCommon_t *servingcellco secondaryCellGroup->cellGroupId = scg_id; NR_RLC_BearerConfig_t *RLC_BearerConfig = calloc(1,sizeof(*RLC_BearerConfig)); nr_rlc_bearer_init(RLC_BearerConfig); - if (get_softmodem_params()->do_ra) + if (get_softmodem_params()->do_ra || get_softmodem_params()->sa) nr_drb_config(RLC_BearerConfig->rlc_Config, NR_RLC_Config_PR_um_Bi_Directional); else nr_drb_config(RLC_BearerConfig->rlc_Config, NR_RLC_Config_PR_am); @@ -285,7 +287,11 @@ void fill_default_secondaryCellGroup(NR_ServingCellConfigCommon_t *servingcellco secondaryCellGroup->spCellConfig->rlf_TimersAndConstants->choice.setup->ext1 = calloc(1,sizeof(*secondaryCellGroup->spCellConfig->rlf_TimersAndConstants->choice.setup->ext1)); secondaryCellGroup->spCellConfig->rlf_TimersAndConstants->choice.setup->ext1->t311 = NR_RLF_TimersAndConstants__ext1__t311_ms30000; secondaryCellGroup->spCellConfig->rlmInSyncOutOfSyncThreshold = NULL; - secondaryCellGroup->spCellConfig->spCellConfigDedicated = calloc(1,sizeof(*secondaryCellGroup->spCellConfig->spCellConfigDedicated)); + if (servingcellconfigdedicated) { + secondaryCellGroup->spCellConfig->spCellConfigDedicated = servingcellconfigdedicated; + } else { + secondaryCellGroup->spCellConfig->spCellConfigDedicated = calloc(1,sizeof(*secondaryCellGroup->spCellConfig->spCellConfigDedicated)); + } secondaryCellGroup->spCellConfig->spCellConfigDedicated->tdd_UL_DL_ConfigurationDedicated = NULL; secondaryCellGroup->spCellConfig->spCellConfigDedicated->initialDownlinkBWP = calloc(1,sizeof(*secondaryCellGroup->spCellConfig->spCellConfigDedicated->initialDownlinkBWP)); secondaryCellGroup->spCellConfig->spCellConfigDedicated->initialDownlinkBWP->pdcch_Config=NULL; @@ -460,9 +466,15 @@ void fill_default_secondaryCellGroup(NR_ServingCellConfigCommon_t *servingcellco #endif secondaryCellGroup->spCellConfig->spCellConfigDedicated->downlinkBWP_ToReleaseList= NULL; - secondaryCellGroup->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList = calloc(1,sizeof(*secondaryCellGroup->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList)); + + NR_BWP_Downlink_t *bwp = NULL; + if (servingcellconfigdedicated) { + bwp=servingcellconfigdedicated->downlinkBWP_ToAddModList->list.array[0]; + } else { + secondaryCellGroup->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList = calloc(1,sizeof(*secondaryCellGroup->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList)); - NR_BWP_Downlink_t *bwp=calloc(1,sizeof(*bwp)); + bwp=calloc(1,sizeof(*bwp)); + } bwp->bwp_Id=1; bwp->bwp_Common=calloc(1,sizeof(*bwp->bwp_Common)); // copy common BWP size from initial BWP except for bandwdith @@ -577,8 +589,9 @@ void fill_default_secondaryCellGroup(NR_ServingCellConfigCommon_t *servingcellco ASN_SEQUENCE_ADD(&bwp->bwp_Common->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList->list,pdschi); } - bwp->bwp_Dedicated=calloc(1,sizeof(*bwp->bwp_Dedicated)); - + if (!servingcellconfigdedicated) { + bwp->bwp_Dedicated=calloc(1,sizeof(*bwp->bwp_Dedicated)); + } bwp->bwp_Dedicated->pdcch_Config=calloc(1,sizeof(*bwp->bwp_Dedicated->pdcch_Config)); bwp->bwp_Dedicated->pdcch_Config->present = NR_SetupRelease_PDCCH_Config_PR_setup; bwp->bwp_Dedicated->pdcch_Config->choice.setup = calloc(1,sizeof(*bwp->bwp_Dedicated->pdcch_Config->choice.setup)); @@ -626,113 +639,30 @@ void fill_default_secondaryCellGroup(NR_ServingCellConfigCommon_t *servingcellco bwp->bwp_Dedicated->pdcch_Config->choice.setup->searchSpacesToReleaseList = NULL; - bwp->bwp_Dedicated->pdsch_Config = calloc(1,sizeof(*bwp->bwp_Dedicated->pdsch_Config)); + if (!servingcellconfigdedicated) { + bwp->bwp_Dedicated->pdsch_Config = calloc(1,sizeof(*bwp->bwp_Dedicated->pdsch_Config)); bwp->bwp_Dedicated->pdsch_Config->present = NR_SetupRelease_PDSCH_Config_PR_setup; bwp->bwp_Dedicated->pdsch_Config->choice.setup = calloc(1,sizeof(*bwp->bwp_Dedicated->pdsch_Config->choice.setup)); - bwp->bwp_Dedicated->pdsch_Config->choice.setup->dataScramblingIdentityPDSCH = NULL; bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA = calloc(1,sizeof(*bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA)); bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->present= NR_SetupRelease_DMRS_DownlinkConfig_PR_setup; - bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup = calloc(1,sizeof(*bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup)); + bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup = calloc(1,sizeof(*bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup)); + } + bwp->bwp_Dedicated->pdsch_Config->choice.setup->dataScramblingIdentityPDSCH = NULL; bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->dmrs_Type=NULL; bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->maxLength=NULL; bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->scramblingID0=NULL; bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->scramblingID1=NULL; - bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->phaseTrackingRS=NULL; - + if (!servingcellconfigdedicated) { + bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->phaseTrackingRS=NULL; + } bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->dmrs_AdditionalPosition = calloc(1,sizeof(*bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->dmrs_AdditionalPosition)); *bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->dmrs_AdditionalPosition = NR_DMRS_DownlinkConfig__dmrs_AdditionalPosition_pos0; - //bwp->bwp_Dedicated->pdsch_Config->choice.setup->tci_StatesToAddModList=NULL; bwp->bwp_Dedicated->pdsch_Config->choice.setup->tci_StatesToAddModList=calloc(1,sizeof(*bwp->bwp_Dedicated->pdsch_Config->choice.setup->tci_StatesToAddModList)); -#if 0 - bwp->bwp_Dedicated->pdsch_Config->choice.setup->tci_StatesToAddModList=calloc(1,sizeof(*bwp->bwp_Dedicated->pdsch_Config->choice.setup->tci_StatesToAddModList)); - - NR_TCI_State_t*tcid0=calloc(1,sizeof(*tcid0)); - tcid0->tci_StateId=0; - tcid0->qcl_Type1.cell=NULL; - tcid0->qcl_Type1.bwp_Id=calloc(1,sizeof(*tcid0->qcl_Type1.bwp_Id)); - *tcid0->qcl_Type1.bwp_Id=1; - tcid0->qcl_Type1.referenceSignal.present = NR_QCL_Info__referenceSignal_PR_csi_rs; - tcid0->qcl_Type1.referenceSignal.choice.csi_rs = 2; - tcid0->qcl_Type1.qcl_Type=NR_QCL_Info__qcl_Type_typeA; - ASN_SEQUENCE_ADD(&bwp->bwp_Dedicated->pdsch_Config->choice.setup->tci_StatesToAddModList->list,tcid0); - - NR_TCI_State_t*tcid1=calloc(1,sizeof(*tcid1)); - tcid1->tci_StateId=0; - tcid1->qcl_Type1.cell=NULL; - tcid1->qcl_Type1.bwp_Id=calloc(1,sizeof(*tcid1->qcl_Type1.bwp_Id)); - *tcid1->qcl_Type1.bwp_Id=1; - tcid1->qcl_Type1.referenceSignal.present = NR_QCL_Info__referenceSignal_PR_csi_rs; - tcid1->qcl_Type1.referenceSignal.choice.csi_rs = 6; - tcid1->qcl_Type1.qcl_Type=NR_QCL_Info__qcl_Type_typeA; - ASN_SEQUENCE_ADD(&bwp->bwp_Dedicated->pdsch_Config->choice.setup->tci_StatesToAddModList->list,tcid1); - - NR_TCI_State_t*tcid2=calloc(1,sizeof(*tcid2)); - tcid2->tci_StateId=2; - tcid2->qcl_Type1.cell=NULL; - tcid2->qcl_Type1.bwp_Id=calloc(1,sizeof(*tcid2->qcl_Type1.bwp_Id)); - *tcid2->qcl_Type1.bwp_Id=1; - tcid2->qcl_Type1.referenceSignal.present = NR_QCL_Info__referenceSignal_PR_csi_rs; - tcid2->qcl_Type1.referenceSignal.choice.csi_rs = 10; - tcid2->qcl_Type1.qcl_Type=NR_QCL_Info__qcl_Type_typeA; - ASN_SEQUENCE_ADD(&bwp->bwp_Dedicated->pdsch_Config->choice.setup->tci_StatesToAddModList->list,tcid2); - - NR_TCI_State_t*tcid3=calloc(1,sizeof(*tcid3)); - tcid3->tci_StateId=3; - tcid3->qcl_Type1.cell=NULL; - tcid3->qcl_Type1.bwp_Id=calloc(1,sizeof(*tcid3->qcl_Type1.bwp_Id)); - *tcid3->qcl_Type1.bwp_Id=1; - tcid3->qcl_Type1.referenceSignal.present = NR_QCL_Info__referenceSignal_PR_csi_rs; - tcid3->qcl_Type1.referenceSignal.choice.csi_rs = 14; - tcid3->qcl_Type1.qcl_Type=NR_QCL_Info__qcl_Type_typeA; - ASN_SEQUENCE_ADD(&bwp->bwp_Dedicated->pdsch_Config->choice.setup->tci_StatesToAddModList->list,tcid3); - - NR_TCI_State_t*tcid4=calloc(1,sizeof(*tcid4)); - tcid4->tci_StateId=4; - tcid4->qcl_Type1.cell=NULL; - tcid4->qcl_Type1.bwp_Id=calloc(1,sizeof(*tcid4->qcl_Type1.bwp_Id)); - *tcid4->qcl_Type1.bwp_Id=1; - tcid4->qcl_Type1.referenceSignal.present = NR_QCL_Info__referenceSignal_PR_csi_rs; - tcid4->qcl_Type1.referenceSignal.choice.csi_rs = 18; - tcid4->qcl_Type1.qcl_Type=NR_QCL_Info__qcl_Type_typeA; - ASN_SEQUENCE_ADD(&bwp->bwp_Dedicated->pdsch_Config->choice.setup->tci_StatesToAddModList->list,tcid4); - - NR_TCI_State_t*tcid5=calloc(1,sizeof(*tcid5)); - tcid5->tci_StateId=5; - tcid5->qcl_Type1.cell=NULL; - tcid5->qcl_Type1.bwp_Id=calloc(1,sizeof(*tcid5->qcl_Type1.bwp_Id)); - *tcid5->qcl_Type1.bwp_Id=1; - tcid5->qcl_Type1.referenceSignal.present = NR_QCL_Info__referenceSignal_PR_csi_rs; - tcid5->qcl_Type1.referenceSignal.choice.csi_rs = 22; - tcid5->qcl_Type1.qcl_Type=NR_QCL_Info__qcl_Type_typeA; - ASN_SEQUENCE_ADD(&bwp->bwp_Dedicated->pdsch_Config->choice.setup->tci_StatesToAddModList->list,tcid5); - - NR_TCI_State_t*tcid6=calloc(1,sizeof(*tcid6)); - tcid6->tci_StateId=6; - tcid6->qcl_Type1.cell=NULL; - tcid6->qcl_Type1.bwp_Id=calloc(1,sizeof(*tcid6->qcl_Type1.bwp_Id)); - *tcid6->qcl_Type1.bwp_Id=1; - tcid6->qcl_Type1.referenceSignal.present = NR_QCL_Info__referenceSignal_PR_csi_rs; - tcid6->qcl_Type1.referenceSignal.choice.csi_rs = 26; - tcid6->qcl_Type1.qcl_Type=NR_QCL_Info__qcl_Type_typeA; - ASN_SEQUENCE_ADD(&bwp->bwp_Dedicated->pdsch_Config->choice.setup->tci_StatesToAddModList->list,tcid6); - - NR_TCI_State_t*tcid7=calloc(1,sizeof(*tcid7)); - tcid7->tci_StateId=7; - tcid7->qcl_Type1.cell=NULL; - tcid7->qcl_Type1.bwp_Id=calloc(1,sizeof(*tcid7->qcl_Type1.bwp_Id)); - *tcid7->qcl_Type1.bwp_Id=1; - tcid7->qcl_Type1.referenceSignal.present = NR_QCL_Info__referenceSignal_PR_csi_rs; - tcid7->qcl_Type1.referenceSignal.choice.csi_rs = 30; - tcid7->qcl_Type1.qcl_Type=NR_QCL_Info__qcl_Type_typeA; - ASN_SEQUENCE_ADD(&bwp->bwp_Dedicated->pdsch_Config->choice.setup->tci_StatesToAddModList->list,tcid7); -#endif - - n_ssb = 0; NR_TCI_State_t *tcid[64]; for (int i=0;i<64;i++) { @@ -828,8 +758,9 @@ void fill_default_secondaryCellGroup(NR_ServingCellConfigCommon_t *servingcellco *bwp->bwp_Dedicated->radioLinkMonitoringConfig->choice.setup->beamFailureDetectionTimer = NR_RadioLinkMonitoringConfig__beamFailureDetectionTimer_pbfd2; #endif - ASN_SEQUENCE_ADD(&secondaryCellGroup->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList->list,bwp); - + if (!servingcellconfigdedicated) { + ASN_SEQUENCE_ADD(&secondaryCellGroup->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList->list,bwp); + } secondaryCellGroup->spCellConfig->spCellConfigDedicated->firstActiveDownlinkBWP_Id=calloc(1,sizeof(*secondaryCellGroup->spCellConfig->spCellConfigDedicated->firstActiveDownlinkBWP_Id)); *secondaryCellGroup->spCellConfig->spCellConfigDedicated->firstActiveDownlinkBWP_Id=1; @@ -837,26 +768,38 @@ void fill_default_secondaryCellGroup(NR_ServingCellConfigCommon_t *servingcellco secondaryCellGroup->spCellConfig->spCellConfigDedicated->defaultDownlinkBWP_Id = NULL; secondaryCellGroup->spCellConfig->spCellConfigDedicated->defaultDownlinkBWP_Id = calloc(1, sizeof(*secondaryCellGroup->spCellConfig->spCellConfigDedicated->defaultDownlinkBWP_Id)); *secondaryCellGroup->spCellConfig->spCellConfigDedicated->defaultDownlinkBWP_Id = 1; - secondaryCellGroup->spCellConfig->spCellConfigDedicated->uplinkConfig=calloc(1,sizeof(*secondaryCellGroup->spCellConfig->spCellConfigDedicated->uplinkConfig)); + + if (!servingcellconfigdedicated) { + secondaryCellGroup->spCellConfig->spCellConfigDedicated->uplinkConfig=calloc(1,sizeof(*secondaryCellGroup->spCellConfig->spCellConfigDedicated->uplinkConfig)); + } NR_BWP_UplinkDedicated_t *initialUplinkBWP = calloc(1,sizeof(*initialUplinkBWP)); secondaryCellGroup->spCellConfig->spCellConfigDedicated->uplinkConfig->initialUplinkBWP = initialUplinkBWP; initialUplinkBWP->pucch_Config = NULL; initialUplinkBWP->pusch_Config = calloc(1,sizeof(*initialUplinkBWP->pusch_Config)); initialUplinkBWP->pusch_Config->present = NR_SetupRelease_PUSCH_Config_PR_setup; - NR_PUSCH_Config_t *pusch_Config = calloc(1,sizeof(*pusch_Config)); + NR_PUSCH_Config_t *pusch_Config = NULL; + if (servingcellconfigdedicated) { + pusch_Config = servingcellconfigdedicated->uplinkConfig->uplinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pusch_Config->choice.setup; + } else { + pusch_Config = calloc(1,sizeof(*pusch_Config)); + } initialUplinkBWP->pusch_Config->choice.setup = pusch_Config; pusch_Config->txConfig=calloc(1,sizeof(*pusch_Config->txConfig)); *pusch_Config->txConfig= NR_PUSCH_Config__txConfig_codebook; pusch_Config->dmrs_UplinkForPUSCH_MappingTypeA = NULL; - pusch_Config->dmrs_UplinkForPUSCH_MappingTypeB = calloc(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(1,sizeof(*pusch_Config->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup)); + if (!servingcellconfigdedicated) { + pusch_Config->dmrs_UplinkForPUSCH_MappingTypeB = calloc(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(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->dmrs_Type = NULL; NR_DMRS_UplinkConfig->dmrs_AdditionalPosition = calloc(1,sizeof(*NR_DMRS_UplinkConfig->dmrs_AdditionalPosition)); *NR_DMRS_UplinkConfig->dmrs_AdditionalPosition = NR_DMRS_UplinkConfig__dmrs_AdditionalPosition_pos0; - NR_DMRS_UplinkConfig->phaseTrackingRS=NULL; + if (!servingcellconfigdedicated) { + NR_DMRS_UplinkConfig->phaseTrackingRS=NULL; + } NR_DMRS_UplinkConfig->maxLength=NULL; NR_DMRS_UplinkConfig->transformPrecodingDisabled = calloc(1,sizeof(*NR_DMRS_UplinkConfig->transformPrecodingDisabled)); NR_DMRS_UplinkConfig->transformPrecodingDisabled->scramblingID0 = NULL; @@ -903,7 +846,7 @@ void fill_default_secondaryCellGroup(NR_ServingCellConfigCommon_t *servingcellco pusch_Config->tp_pi2BPSK=NULL; /*------------------------------TRANSFORM PRECODING- -----------------------------------------------------------------------*/ - + uint8_t transform_precoding = NR_PUSCH_Config__transformPrecoder_disabled; // TBD: configure this from .conf file, Dedicated params cannot yet be configured in .conf file. @@ -918,20 +861,20 @@ void fill_default_secondaryCellGroup(NR_ServingCellConfigCommon_t *servingcellco if (servingcellconfigcommon->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->msg3_transformPrecoder != NULL) transform_precoding = NR_PUSCH_Config__transformPrecoder_enabled; } - else + else transform_precoding = *pusch_Config->transformPrecoder; - - + + if (transform_precoding == NR_PUSCH_Config__transformPrecoder_enabled ) { /* Enable DMRS uplink config for transform precoding enabled */ NR_DMRS_UplinkConfig->transformPrecodingEnabled = calloc(1,sizeof(*NR_DMRS_UplinkConfig->transformPrecodingEnabled)); NR_DMRS_UplinkConfig->transformPrecodingEnabled->nPUSCH_Identity = NULL; - NR_DMRS_UplinkConfig->transformPrecodingEnabled->sequenceGroupHopping = NULL; + NR_DMRS_UplinkConfig->transformPrecodingEnabled->sequenceGroupHopping = NULL; NR_DMRS_UplinkConfig->transformPrecodingEnabled->sequenceHopping = NULL; - NR_DMRS_UplinkConfig->transformPrecodingEnabled->ext1 = NULL; + NR_DMRS_UplinkConfig->transformPrecodingEnabled->ext1 = NULL; LOG_I(RRC,"TRANSFORM PRECODING ENABLED......\n"); - + } /*----------------------------------------------------------------------------------------------------------------------------*/ @@ -992,8 +935,13 @@ void fill_default_secondaryCellGroup(NR_ServingCellConfigCommon_t *servingcellco ASN_SEQUENCE_ADD(&srs_Config->srs_ResourceToAddModList->list,srs_res0); secondaryCellGroup->spCellConfig->spCellConfigDedicated->uplinkConfig->uplinkBWP_ToReleaseList = NULL; - secondaryCellGroup->spCellConfig->spCellConfigDedicated->uplinkConfig->uplinkBWP_ToAddModList = calloc(1,sizeof(*secondaryCellGroup->spCellConfig->spCellConfigDedicated->uplinkConfig->uplinkBWP_ToAddModList)); - NR_BWP_Uplink_t *ubwp = calloc(1,sizeof(*ubwp)); + NR_BWP_Uplink_t *ubwp = NULL; + if (servingcellconfigdedicated) { + ubwp = servingcellconfigdedicated->uplinkConfig->uplinkBWP_ToAddModList->list.array[0]; + } else { + secondaryCellGroup->spCellConfig->spCellConfigDedicated->uplinkConfig->uplinkBWP_ToAddModList = calloc(1,sizeof(*secondaryCellGroup->spCellConfig->spCellConfigDedicated->uplinkConfig->uplinkBWP_ToAddModList)); + ubwp = calloc(1,sizeof(*ubwp)); + } ubwp->bwp_Id=1; ubwp->bwp_Common = calloc(1,sizeof(*ubwp->bwp_Common)); // copy bwp_Common from Initial UL BWP except for bandwidth @@ -1006,7 +954,9 @@ void fill_default_secondaryCellGroup(NR_ServingCellConfigCommon_t *servingcellco ubwp->bwp_Common->pusch_ConfigCommon = servingcellconfigcommon->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon; ubwp->bwp_Common->pucch_ConfigCommon = servingcellconfigcommon->uplinkConfigCommon->initialUplinkBWP->pucch_ConfigCommon; - ubwp->bwp_Dedicated = calloc(1,sizeof(*ubwp->bwp_Dedicated)); + if (!servingcellconfigdedicated) { + ubwp->bwp_Dedicated = calloc(1,sizeof(*ubwp->bwp_Dedicated)); + } ubwp->bwp_Dedicated->pucch_Config = calloc(1,sizeof(*ubwp->bwp_Dedicated->pucch_Config)); ubwp->bwp_Dedicated->pucch_Config->present = NR_SetupRelease_PUCCH_Config_PR_setup; NR_PUCCH_Config_t *pucch_Config = calloc(1,sizeof(*pucch_Config)); @@ -1136,11 +1086,12 @@ void fill_default_secondaryCellGroup(NR_ServingCellConfigCommon_t *servingcellco ASN_SEQUENCE_ADD(&pucch_Config->pucch_PowerControl->p0_Set->list,p00); pucch_Config->pucch_PowerControl->pathlossReferenceRSs = NULL; - // copy pusch_Config from dedicated initialBWP - ubwp->bwp_Dedicated->pusch_Config = calloc(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; - + if (!servingcellconfigdedicated) { + // copy pusch_Config from dedicated initialBWP + ubwp->bwp_Dedicated->pusch_Config = calloc(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; + } ubwp->bwp_Dedicated->configuredGrantConfig = NULL; ubwp->bwp_Dedicated->srs_Config = calloc(1,sizeof(*ubwp->bwp_Dedicated->srs_Config)); ubwp->bwp_Dedicated->srs_Config->present = NR_SetupRelease_SRS_Config_PR_setup; @@ -1148,7 +1099,9 @@ void fill_default_secondaryCellGroup(NR_ServingCellConfigCommon_t *servingcellco ubwp->bwp_Dedicated->beamFailureRecoveryConfig = NULL; - ASN_SEQUENCE_ADD(&secondaryCellGroup->spCellConfig->spCellConfigDedicated->uplinkConfig->uplinkBWP_ToAddModList->list,ubwp); + if (!servingcellconfigdedicated) { + ASN_SEQUENCE_ADD(&secondaryCellGroup->spCellConfig->spCellConfigDedicated->uplinkConfig->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 = 1; @@ -1300,7 +1253,9 @@ void fill_default_secondaryCellGroup(NR_ServingCellConfigCommon_t *servingcellco secondaryCellGroup->spCellConfig->spCellConfigDedicated->servingCellMO=NULL; } + void fill_default_reconfig(NR_ServingCellConfigCommon_t *servingcellconfigcommon, + NR_ServingCellConfig_t *servingcellconfigdedicated, NR_RRCReconfiguration_IEs_t *reconfig, NR_CellGroupConfig_t *secondaryCellGroup, int n_physical_antenna_ports, @@ -1311,7 +1266,7 @@ void fill_default_reconfig(NR_ServingCellConfigCommon_t *servingcellconfigcommon // radioBearerConfig reconfig->radioBearerConfig=NULL; // secondaryCellGroup - fill_default_secondaryCellGroup(servingcellconfigcommon,secondaryCellGroup,1,1,n_physical_antenna_ports,initial_csi_index); + fill_default_secondaryCellGroup(servingcellconfigcommon,servingcellconfigdedicated,secondaryCellGroup,1,1,n_physical_antenna_ports,initial_csi_index); xer_fprint(stdout, &asn_DEF_NR_CellGroupConfig, (const void*)secondaryCellGroup); char scg_buffer[1024]; @@ -1347,7 +1302,7 @@ void fill_default_rbconfig(NR_RadioBearerConfig_t *rbconfig, drb_ToAddMod->pdcp_Config = calloc(1,sizeof(*drb_ToAddMod->pdcp_Config)); drb_ToAddMod->pdcp_Config->drb = calloc(1,sizeof(*drb_ToAddMod->pdcp_Config->drb)); drb_ToAddMod->pdcp_Config->drb->discardTimer = calloc(1,sizeof(*drb_ToAddMod->pdcp_Config->drb->discardTimer)); - *drb_ToAddMod->pdcp_Config->drb->discardTimer=NR_PDCP_Config__drb__discardTimer_ms30; + *drb_ToAddMod->pdcp_Config->drb->discardTimer=NR_PDCP_Config__drb__discardTimer_infinity; drb_ToAddMod->pdcp_Config->drb->pdcp_SN_SizeUL = calloc(1,sizeof(*drb_ToAddMod->pdcp_Config->drb->pdcp_SN_SizeUL)); *drb_ToAddMod->pdcp_Config->drb->pdcp_SN_SizeUL = NR_PDCP_Config__drb__pdcp_SN_SizeUL_len18bits; drb_ToAddMod->pdcp_Config->drb->pdcp_SN_SizeDL = calloc(1,sizeof(*drb_ToAddMod->pdcp_Config->drb->pdcp_SN_SizeDL)); diff --git a/openair2/RRC/NR_UE/L2_interface_ue.c b/openair2/RRC/NR_UE/L2_interface_ue.c index 5ad6746696..e21859ded8 100644 --- a/openair2/RRC/NR_UE/L2_interface_ue.c +++ b/openair2/RRC/NR_UE/L2_interface_ue.c @@ -33,6 +33,7 @@ #include "rrc_defs.h" #include "rrc_proto.h" #include "assertions.h" +#include "rrc_vars.h" typedef uint32_t channel_t; @@ -50,7 +51,7 @@ nr_mac_rrc_data_ind_ue( AssertFatal( nr_rrc_ue_decode_NR_BCCH_BCH_Message(module_id, gNB_index, (uint8_t*)pduP, pdu_len) == 0, "UE decode BCCH-BCH error!\n"); break; case NR_BCCH_DL_SCH: - AssertFatal( nr_rrc_ue_decode_NR_SIB1_Message(module_id, gNB_index, (uint8_t*)pduP, pdu_len) == 0, "UE decode BCCH-DLSCH error!\n"); + AssertFatal( nr_rrc_ue_decode_NR_BCCH_DL_SCH_Message(module_id, gNB_index, (uint8_t*)pduP, pdu_len, 0, 0) == 0, "UE decode BCCH-DL-SCH error!\n"); break; default: break; @@ -59,13 +60,36 @@ nr_mac_rrc_data_ind_ue( return(0); } -int8_t mac_rrc_nr_data_req_ue(const module_id_t Mod_idP, +int8_t nr_mac_rrc_data_req_ue(const module_id_t Mod_idP, const int CC_id, + const uint8_t gNB_id, const frame_t frameP, const rb_id_t Srb_id, - uint8_t *const buffer_pP ){ + uint8_t *buffer_pP){ - // todo + switch(Srb_id){ + + case CCCH: + + // TODO: Enable timer T300 + //NR_UE_rrc_inst[Mod_idP].Info[gNB_id].T300_active = 1; + //NR_UE_rrc_inst[Mod_idP].Info[gNB_id].T300_cnt = 0; + + LOG_D(NR_RRC, "nr_mac_rrc_data_req_ue: Payload size = %i\n", NR_UE_rrc_inst[Mod_idP].Srb0[gNB_id].Tx_buffer.payload_size); + memcpy(buffer_pP, (uint8_t*)NR_UE_rrc_inst[Mod_idP].Srb0[gNB_id].Tx_buffer.Payload, NR_UE_rrc_inst[Mod_idP].Srb0[gNB_id].Tx_buffer.payload_size); + for(int i = 0; imodule_id].MBMS_flag < 3) // see -Q option if (AMF_MODE_ENABLED) { - rrc_ue_generate_RRCSetupRequest( ctxt_pP, gNB_index ); + nr_rrc_ue_generate_RRCSetupRequest( ctxt_pP->module_id, gNB_index ); } if (NR_UE_rrc_inst[ctxt_pP->module_id].Info[gNB_index].State == NR_RRC_IDLE) { @@ -1029,205 +1041,120 @@ int nr_decode_SI( const protocol_ctxt_t *const ctxt_pP, const uint8_t gNB_index return 0; } -int nr_decode_SIB1( const protocol_ctxt_t *const ctxt_pP, const uint8_t gNB_index, const uint8_t rsrq, const uint8_t rsrp ) { - NR_SIB1_t *sib1 = NR_UE_rrc_inst[ctxt_pP->module_id].sib1[gNB_index]; - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_RRC_UE_DECODE_SIB1, VCD_FUNCTION_IN ); - LOG_I( RRC, "[UE %d] : Dumping SIB 1\n", ctxt_pP->module_id ); - const int n = sib1->cellAccessRelatedInfo.plmn_IdentityList.list.count; - for (int i = 0; i < n; ++i) { - NR_PLMN_Identity_t *PLMN_identity = sib1->cellAccessRelatedInfo.plmn_IdentityList.list.array[i]->plmn_IdentityList.list.array[0]; - int mccdigits = PLMN_identity->mcc->list.count; - int mncdigits = PLMN_identity->mnc.list.count; +int8_t check_requested_SI_List(module_id_t module_id, BIT_STRING_t requested_SI_List, NR_SIB1_t sib1) { - int mcc; - if (mccdigits == 2) { - mcc = *PLMN_identity->mcc->list.array[0]*10 + *PLMN_identity->mcc->list.array[1]; - } else { - mcc = *PLMN_identity->mcc->list.array[0]*100 + *PLMN_identity->mcc->list.array[1]*10 + *PLMN_identity->mcc->list.array[2]; + if(sib1.si_SchedulingInfo) { + + bool SIB_to_request[32] = {}; + + LOG_D(RRC, "SIBs broadcasting: "); + for(int i = 0; i < sib1.si_SchedulingInfo->schedulingInfoList.list.array[0]->sib_MappingInfo.list.count; i++) { + printf("SIB%li ", sib1.si_SchedulingInfo->schedulingInfoList.list.array[0]->sib_MappingInfo.list.array[i]->type + 2); } + printf("\n"); - int mnc; - if (mncdigits == 2) { - mnc = *PLMN_identity->mnc.list.array[0]*10 + *PLMN_identity->mnc.list.array[1]; - } else { - mnc = *PLMN_identity->mnc.list.array[0]*100 + *PLMN_identity->mnc.list.array[1]*10 + *PLMN_identity->mnc.list.array[2]; - } + LOG_D(RRC, "SIBs needed by UE: "); + for(int j = 0; j < 8*requested_SI_List.size; j++) { + if( ((requested_SI_List.buf[j/8]>>(j%8))&1) == 1) { - LOG_I( RRC, "PLMN %d MCC %0*d, MNC %0*d\n", i + 1, mccdigits, mcc, mncdigits, mnc); - // search internal table for provider name - int plmn_ind = 0; + printf("SIB%i ", j + 2); - while (plmn_data[plmn_ind].mcc > 0) { - if ((plmn_data[plmn_ind].mcc == mcc) && (plmn_data[plmn_ind].mnc == mnc)) { - LOG_I( RRC, "Found %s (name from internal table)\n", plmn_data[plmn_ind].oper_short ); - break; - } - - plmn_ind++; - } - } - LOG_I( RRC, "TAC 0x%04x\n", - ((sib1->cellAccessRelatedInfo.plmn_IdentityList.list.array[0]->trackingAreaCode->size == 2)?((sib1->cellAccessRelatedInfo.plmn_IdentityList.list.array[0]->trackingAreaCode->buf[0]<<8) + sib1->cellAccessRelatedInfo.plmn_IdentityList.list.array[0]->trackingAreaCode->buf[1]):0)); - LOG_I( RRC, "cellReservedForOperatorUse : raw:%ld decoded:%s\n", sib1->cellAccessRelatedInfo.plmn_IdentityList.list.array[0]->cellReservedForOperatorUse, - nr_SIBreserved(sib1->cellAccessRelatedInfo.plmn_IdentityList.list.array[0]->cellReservedForOperatorUse) ); - - LOG_I( RRC, "cellAccessRelatedInfo.cellIdentity : raw:%"PRIu32" decoded:%02x.%02x.%02x.%02x\n", - BIT_STRING_to_uint32( &sib1->cellAccessRelatedInfo.plmn_IdentityList.list.array[0]->cellIdentity ), - sib1->cellAccessRelatedInfo.plmn_IdentityList.list.array[0]->cellIdentity.buf[0], - sib1->cellAccessRelatedInfo.plmn_IdentityList.list.array[0]->cellIdentity.buf[1], - sib1->cellAccessRelatedInfo.plmn_IdentityList.list.array[0]->cellIdentity.buf[2], - sib1->cellAccessRelatedInfo.plmn_IdentityList.list.array[0]->cellIdentity.buf[3] >> sib1->cellAccessRelatedInfo.plmn_IdentityList.list.array[0]->cellIdentity.bits_unused); - //LOG_I( RRC, "cellAccessRelatedInfo.cellBarred : raw:%ld decoded:%s\n", sib1->cellAccessRelatedInfo.cellBarred, SIBbarred(sib1->cellAccessRelatedInfo.cellBarred) ); - //LOG_I( RRC, "cellAccessRelatedInfo.intraFreqReselection : raw:%ld decoded:%s\n", sib1->cellAccessRelatedInfo.intraFreqReselection, SIBallowed(sib1->cellAccessRelatedInfo.intraFreqReselection) ); - //LOG_I( RRC, "cellAccessRelatedInfo.csg_Indication : %d\n", sib1->cellAccessRelatedInfo.csg_Indication ); - - //if (sib1->cellAccessRelatedInfo.csg_Identity) - // LOG_I( RRC, "cellAccessRelatedInfo.csg_Identity : %"PRIu32"\n", BIT_STRING_to_uint32(sib1->cellAccessRelatedInfo.csg_Identity) ); - //else - // LOG_I( RRC, "cellAccessRelatedInfo.csg_Identity : not defined\n" ); - - LOG_I( RRC, "cellSelectionInfo.q_RxLevMin : %ld\n", sib1->cellSelectionInfo->q_RxLevMin ); - - if (sib1->cellSelectionInfo->q_RxLevMinOffset) - LOG_I( RRC, "cellSelectionInfo.q_RxLevMinOffset : %ld\n", *sib1->cellSelectionInfo->q_RxLevMinOffset ); - else - LOG_I( RRC, "cellSelectionInfo.q_RxLevMinOffset : not defined\n" ); - - //if (sib1->p_Max) - // LOG_I( RRC, "p_Max : %ld\n", *sib1->p_Max ); - //else - // LOG_I( RRC, "p_Max : not defined\n" ); - - //LOG_I( RRC, "freqBandIndicator : %ld\n", sib1->freqBandIndicator ); - - if (sib1->si_SchedulingInfo->schedulingInfoList.list.count > 0) { - for (int i=0; isi_SchedulingInfo->schedulingInfoList.list.count; i++) { - LOG_I( RRC, "si_Periodicity[%d] : %s\n", i, SIBPeriod[min(sib1->si_SchedulingInfo->schedulingInfoList.list.array[i]->si_Periodicity,7)]); - - if (sib1->si_SchedulingInfo->schedulingInfoList.list.array[i]->sib_MappingInfo.list.count > 0) { - char temp[32 * sizeof(SIBType[0])] = {0}; // maxSIB==32 - - for (int j=0; jsi_SchedulingInfo->schedulingInfoList.list.array[i]->sib_MappingInfo.list.count; j++) { - sprintf( temp + j*sizeof(SIBType[0]), "%*s ", (int)sizeof(SIBType[0])-1, SIBType[min(sib1->si_SchedulingInfo->schedulingInfoList.list.array[i]->sib_MappingInfo.list.array[0]->type,11)] ); + SIB_to_request[j] = true; + for(int i = 0; i < sib1.si_SchedulingInfo->schedulingInfoList.list.array[0]->sib_MappingInfo.list.count; i++) { + if(sib1.si_SchedulingInfo->schedulingInfoList.list.array[0]->sib_MappingInfo.list.array[i]->type == j) { + SIB_to_request[j] = false; + break; + } } - LOG_I( RRC, "siSchedulingInfoSIBType[%d] : %s\n", i, temp ); + } + } + printf("\n"); + + LOG_D(RRC, "SIBs to request by UE: "); + bool do_ra = false; + for(int j = 0; j < 8*requested_SI_List.size; j++) { + if(SIB_to_request[j]) { + printf("SIB%i ", j + 2); + do_ra = true; + } + } + printf("\n"); + + if(do_ra) { + + NR_UE_rrc_inst[module_id].ra_trigger = REQUEST_FOR_OTHER_SI; + get_softmodem_params()->do_ra = 1; + + if(sib1.si_SchedulingInfo->si_RequestConfig) { + LOG_D(RRC, "Trigger contention-free RA procedure (ra_trigger = %i)\n", NR_UE_rrc_inst[module_id].ra_trigger); } else { - LOG_I( RRC, "mapping list %d is null\n", i ); + LOG_D(RRC, "Trigger contention-based RA procedure (ra_trigger = %i)\n", NR_UE_rrc_inst[module_id].ra_trigger); } + } - } else { - LOG_E( RRC, "siSchedulingInfoPeriod[0] : PROBLEM!!!\n" ); - return -1; + } - if (sib1->servingCellConfigCommon->tdd_UL_DL_ConfigurationCommon) { - //TODO - } - - LOG_I( RRC, "siWindowLength : %s\n", siWindowLength[min(sib1->si_SchedulingInfo->si_WindowLength,8)] ); - //LOG_I( RRC, "systemInfoValueTag : %ld\n", sib1->systemInfoValueTag ); - NR_UE_rrc_inst[ctxt_pP->module_id].Info[gNB_index].SIperiod = siPeriod_int[sib1->si_SchedulingInfo->schedulingInfoList.list.array[0]->si_Periodicity]; - NR_UE_rrc_inst[ctxt_pP->module_id].Info[gNB_index].SIwindowsize = siWindowLength_int[sib1->si_SchedulingInfo->si_WindowLength]; - LOG_I( RRC, "[FRAME unknown][RRC_UE][MOD %02"PRIu8"][][--- MAC_CONFIG_REQ (SIB1 params gNB %"PRIu8") --->][MAC_UE][MOD %02"PRIu8"][]\n", - ctxt_pP->module_id, gNB_index, ctxt_pP->module_id ); - //rrc_mac_config_req_ue - LOG_I(RRC,"Setting SIStatus bit 0 to 1\n"); - NR_UE_rrc_inst[ctxt_pP->module_id].Info[gNB_index].SIStatus = 1; - //NR_UE_rrc_inst[ctxt_pP->module_id].Info[gNB_index].SIB1systemInfoValueTag = sib1->systemInfoValueTag; - - if (AMF_MODE_ENABLED) { - int cell_valid = 0; - - //if (sib1->cellAccessRelatedInfo.cellBarred == LTE_SystemInformationBlockType1__cellAccessRelatedInfo__cellBarred_notBarred) { - /* Cell is not barred */ - int plmn; - int plmn_number; - plmn_number = sib1->cellAccessRelatedInfo.plmn_IdentityList.list.count; - - /* Compare requested PLMN and PLMNs from SIB1*/ - for (plmn = 0; plmn < plmn_number; plmn++) { - NR_PLMN_Identity_t *plmn_Identity; - plmn_Identity = sib1->cellAccessRelatedInfo.plmn_IdentityList.list.array[plmn]->plmn_IdentityList.list.array[0]; - - if ( - ( - (plmn_Identity->mcc == NULL) - || - ( - (NR_UE_rrc_inst[ctxt_pP->module_id].plmnID.MCCdigit1 == *(plmn_Identity->mcc->list.array[0])) && - (NR_UE_rrc_inst[ctxt_pP->module_id].plmnID.MCCdigit2 == *(plmn_Identity->mcc->list.array[1])) && - (NR_UE_rrc_inst[ctxt_pP->module_id].plmnID.MCCdigit3 == *(plmn_Identity->mcc->list.array[2])) - ) - ) - && - (NR_UE_rrc_inst[ctxt_pP->module_id].plmnID.MNCdigit1 == *(plmn_Identity->mnc.list.array[0])) - && - (NR_UE_rrc_inst[ctxt_pP->module_id].plmnID.MNCdigit2 == *(plmn_Identity->mnc.list.array[1])) - && - ( - ((NR_UE_rrc_inst[ctxt_pP->module_id].plmnID.MNCdigit3 == 0xf) && (plmn_Identity->mnc.list.count == 2)) - || - (NR_UE_rrc_inst[ctxt_pP->module_id].plmnID.MNCdigit3 == *(plmn_Identity->mnc.list.array[2])) - ) - ) { - /* PLMN match, send a confirmation to NAS */ - MessageDef *msg_p; - msg_p = itti_alloc_new_message(TASK_RRC_NRUE, 0, NAS_CELL_SELECTION_CNF); - NAS_CELL_SELECTION_CNF (msg_p).errCode = AS_SUCCESS; - NAS_CELL_SELECTION_CNF (msg_p).cellID = BIT_STRING_to_uint32(&sib1->cellAccessRelatedInfo.plmn_IdentityList.list.array[0]->cellIdentity); - NAS_CELL_SELECTION_CNF (msg_p).tac = BIT_STRING_to_uint16(sib1->cellAccessRelatedInfo.plmn_IdentityList.list.array[0]->trackingAreaCode); - NAS_CELL_SELECTION_CNF (msg_p).rat = 0xFF; - NAS_CELL_SELECTION_CNF (msg_p).rsrq = rsrq; - NAS_CELL_SELECTION_CNF (msg_p).rsrp = rsrp; - itti_send_msg_to_task(TASK_NAS_UE, ctxt_pP->instance, msg_p); - cell_valid = 1; - NR_UE_rrc_inst[ctxt_pP->module_id].selected_plmn_identity = plmn + 1; - break; - } - } - //} - - if (cell_valid == 0) { - /* Cell can not be used, ask PHY to try the next one */ - MessageDef *msg_p; - msg_p = itti_alloc_new_message(TASK_RRC_NRUE, 0, PHY_FIND_NEXT_CELL_REQ); - itti_send_msg_to_task(TASK_PHY_UE, ctxt_pP->instance, msg_p); - LOG_E(RRC, - "Synched with a cell, but PLMN doesn't match our SIM " - "(selected_plmn_identity %ld), the message PHY_FIND_NEXT_CELL_REQ " - "is sent but lost in current UE implementation!\n", - NR_UE_rrc_inst[ctxt_pP->module_id].selected_plmn_identity); - } - } - - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_RRC_UE_DECODE_SIB1, VCD_FUNCTION_OUT ); return 0; } -int nr_decode_BCCH_DLSCH_Message( - const protocol_ctxt_t *const ctxt_pP, - const uint8_t gNB_index, - uint8_t *const Sdu, - const uint8_t Sdu_len, - const uint8_t rsrq, - const uint8_t rsrp ) { +int8_t nr_rrc_ue_generate_ra_msg(module_id_t module_id, uint8_t gNB_index) { + + switch(NR_UE_rrc_inst[module_id].ra_trigger){ + case INITIAL_ACCESS_FROM_RRC_IDLE: + // After SIB1 is received, prepare RRCConnectionRequest + nr_rrc_ue_generate_RRCSetupRequest(module_id,gNB_index); + break; + case RRC_CONNECTION_REESTABLISHMENT: + AssertFatal(1==0, "ra_trigger not implemented yet!\n"); + break; + case DURING_HANDOVER: + AssertFatal(1==0, "ra_trigger not implemented yet!\n"); + break; + case NON_SYNCHRONISED: + AssertFatal(1==0, "ra_trigger not implemented yet!\n"); + break; + case TRANSITION_FROM_RRC_INACTIVE: + AssertFatal(1==0, "ra_trigger not implemented yet!\n"); + break; + case TO_ESTABLISH_TA: + AssertFatal(1==0, "ra_trigger not implemented yet!\n"); + break; + case REQUEST_FOR_OTHER_SI: + AssertFatal(1==0, "ra_trigger not implemented yet!\n"); + break; + case BEAM_FAILURE_RECOVERY: + AssertFatal(1==0, "ra_trigger not implemented yet!\n"); + break; + default: + AssertFatal(1==0, "Invalid ra_trigger value!\n"); + break; + } + + return 0; +} + +int8_t nr_rrc_ue_decode_NR_BCCH_DL_SCH_Message( + module_id_t module_id, + const uint8_t gNB_index, + uint8_t *const Sdu, + const uint8_t Sdu_len, + const uint8_t rsrq, + const uint8_t rsrp) { + NR_BCCH_DL_SCH_Message_t *bcch_message = NULL; - NR_SIB1_t *sib1 = NR_UE_rrc_inst[ctxt_pP->module_id].sib1[gNB_index]; + NR_SIB1_t *sib1 = NR_UE_rrc_inst[module_id].sib1[gNB_index]; VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_UE_DECODE_BCCH, VCD_FUNCTION_IN ); - if (((NR_UE_rrc_inst[ctxt_pP->module_id].Info[gNB_index].SIStatus&1) == 1) && // SIB1 received - (NR_UE_rrc_inst[ctxt_pP->module_id].Info[gNB_index].SIcnt == sib1->si_SchedulingInfo->schedulingInfoList.list.count)) { + if (((NR_UE_rrc_inst[module_id].Info[gNB_index].SIStatus&1) == 1) && // SIB1 received + (NR_UE_rrc_inst[module_id].Info[gNB_index].SIcnt == sib1->si_SchedulingInfo->schedulingInfoList.list.count)) { // to prevent memory bloating VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_UE_DECODE_BCCH, VCD_FUNCTION_OUT ); return 0; } - nr_rrc_set_sub_state( ctxt_pP->module_id, RRC_SUB_STATE_IDLE_RECEIVING_SIB_NR ); - - if ( LOG_DEBUGFLAG(DEBUG_ASN1) ) { - xer_fprint(stdout, &asn_DEF_NR_BCCH_DL_SCH_Message,(void *)bcch_message ); - } + nr_rrc_set_sub_state( module_id, RRC_SUB_STATE_IDLE_RECEIVING_SIB_NR ); asn_dec_rval_t dec_rval = uper_decode_complete( NULL, &asn_DEF_NR_BCCH_DL_SCH_Message, @@ -1235,11 +1162,15 @@ int nr_decode_BCCH_DLSCH_Message( (const void *)Sdu, Sdu_len ); + if ( LOG_DEBUGFLAG(DEBUG_ASN1) ) { + xer_fprint(stdout, &asn_DEF_NR_BCCH_DL_SCH_Message,(void *)bcch_message ); + } + if ((dec_rval.code != RC_OK) && (dec_rval.consumed == 0)) { - LOG_E( RRC, "[UE %"PRIu8"] Failed to decode BCCH_DLSCH_MESSAGE (%zu bits)\n", - ctxt_pP->module_id, + LOG_E( NR_RRC, "[UE %"PRIu8"] Failed to decode BCCH_DLSCH_MESSAGE (%zu bits)\n", + module_id, dec_rval.consumed ); - log_dump(RRC, Sdu, Sdu_len, LOG_DUMP_CHAR," Received bytes:\n" ); + log_dump(NR_RRC, Sdu, Sdu_len, LOG_DUMP_CHAR," Received bytes:\n" ); // free the memory SEQUENCE_free( &asn_DEF_LTE_BCCH_DL_SCH_Message, (void *)bcch_message, 1 ); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_UE_DECODE_BCCH, VCD_FUNCTION_OUT ); @@ -1249,35 +1180,53 @@ int nr_decode_BCCH_DLSCH_Message( if (bcch_message->message.present == NR_BCCH_DL_SCH_MessageType_PR_c1) { switch (bcch_message->message.choice.c1->present) { case NR_BCCH_DL_SCH_MessageType__c1_PR_systemInformationBlockType1: - if ((ctxt_pP->frame % 2) == 0) { - // even frame - if ((NR_UE_rrc_inst[ctxt_pP->module_id].Info[gNB_index].SIStatus&1) == 0) { - NR_SIB1_t *sib1 = NR_UE_rrc_inst[ctxt_pP->module_id].sib1[gNB_index]; - memcpy( (void *)sib1, - (void *)bcch_message->message.choice.c1->choice.systemInformationBlockType1, - sizeof(NR_SIB1_t) ); - LOG_D( RRC, "[UE %"PRIu8"] Decoding First SIB1\n", ctxt_pP->module_id ); - nr_decode_SIB1( ctxt_pP, gNB_index, rsrq, rsrp ); + if ((NR_UE_rrc_inst[module_id].Info[gNB_index].SIStatus&1) == 0) { + NR_SIB1_t *sib1 = NR_UE_rrc_inst[module_id].sib1[gNB_index]; + if(sib1 != NULL){ + SEQUENCE_free(&asn_DEF_NR_SIB1, (void *)sib1, 1 ); + } + + sib1 = bcch_message->message.choice.c1->choice.systemInformationBlockType1; + if (*(int64_t*)sib1 != 1) { + NR_UE_rrc_inst[module_id].sib1[gNB_index] = sib1; + if( g_log->log_component[NR_RRC].level >= OAILOG_DEBUG ) { + xer_fprint(stdout, &asn_DEF_NR_SIB1, (const void *) NR_UE_rrc_inst[module_id].sib1[gNB_index]); + } + LOG_I(NR_RRC, "SIB1 decoded\n"); + + // FIXME: improve condition for the RA trigger + // Check for on-demand not broadcasted SI + check_requested_SI_List(module_id, NR_UE_rrc_inst[module_id].requested_SI_List, *sib1); + if( nr_rrc_get_state(module_id) == RRC_STATE_IDLE_NR ) { + NR_UE_rrc_inst[module_id].ra_trigger = INITIAL_ACCESS_FROM_RRC_IDLE; + // TODO: remove flag after full RA procedures implemented + get_softmodem_params()->do_ra = 1; + } + nr_rrc_ue_generate_ra_msg(module_id,gNB_index); + } else { + LOG_E(NR_RRC, "SIB1 not decoded\n"); } } - break; case NR_BCCH_DL_SCH_MessageType__c1_PR_systemInformation: - if ((NR_UE_rrc_inst[ctxt_pP->module_id].Info[gNB_index].SIStatus&1) == 1) { + if ((NR_UE_rrc_inst[module_id].Info[gNB_index].SIStatus&1) == 1) { + LOG_W(NR_RRC, "Decoding SI not implemented yet\n"); + // TODO: Decode SI + /* // SIB1 with schedulingInfoList is available - NR_SystemInformation_t *si = NR_UE_rrc_inst[ctxt_pP->module_id].si[gNB_index]; + NR_SystemInformation_t *si = NR_UE_rrc_inst[module_id].si[gNB_index]; + memcpy( si, bcch_message->message.choice.c1->choice.systemInformation, sizeof(NR_SystemInformation_t) ); - LOG_I( RRC, "[UE %"PRIu8"] Decoding SI for frameP %"PRIu32"\n", - ctxt_pP->module_id, - ctxt_pP->frame ); + LOG_I(NR_RRC, "[UE %"PRIu8"] Decoding SI\n", module_id); nr_decode_SI( ctxt_pP, gNB_index ); - //if (nfapi_mode == 3) - //UE_mac_inst[ctxt_pP->module_id].SI_Decoded = 1; - } + if (nfapi_mode == 3) + UE_mac_inst[ctxt_pP->module_id].SI_Decoded = 1; + */ + } break; case NR_BCCH_DL_SCH_MessageType__c1_PR_NOTHING: @@ -1286,10 +1235,10 @@ int nr_decode_BCCH_DLSCH_Message( } } - if (nr_rrc_get_sub_state(ctxt_pP->module_id) == RRC_SUB_STATE_IDLE_SIB_COMPLETE_NR) { + if (nr_rrc_get_sub_state(module_id) == RRC_SUB_STATE_IDLE_SIB_COMPLETE_NR) { //if ( (NR_UE_rrc_inst[ctxt_pP->module_id].initialNasMsg.data != NULL) || (!AMF_MODE_ENABLED)) { - rrc_ue_generate_RRCSetupRequest(ctxt_pP, 0); - nr_rrc_set_sub_state( ctxt_pP->module_id, RRC_SUB_STATE_IDLE_CONNECTING ); + nr_rrc_ue_generate_RRCSetupRequest(module_id, 0); + nr_rrc_set_sub_state( module_id, RRC_SUB_STATE_IDLE_CONNECTING ); //} } @@ -1489,41 +1438,6 @@ int8_t nr_rrc_ue_decode_ccch( const protocol_ctxt_t *const ctxt_pP, const NR_SRB return rval; } -/*brief decode SIB1 message*/ -int8_t nr_rrc_ue_decode_NR_SIB1_Message(module_id_t module_id, uint8_t gNB_index, uint8_t *const bufferP, const uint8_t buffer_len) { - - NR_BCCH_DL_SCH_Message_t *bcch_message = NULL; - - asn_dec_rval_t dec_rval = uper_decode_complete(NULL, - &asn_DEF_NR_BCCH_DL_SCH_Message, - (void **)&bcch_message, - (const void *)bufferP, - buffer_len); - - if ((dec_rval.code != RC_OK) || (dec_rval.consumed == 0)) { - LOG_D(RRC,"NR_BCCH_DL_SCH decode error\n"); - SEQUENCE_free( &asn_DEF_NR_BCCH_DL_SCH_Message, (void *)bcch_message, 1 ); - return -1; - } - else { - NR_SIB1_t *sib1 = NR_UE_rrc_inst[module_id].sib1[gNB_index]; - if(sib1 != NULL){ - SEQUENCE_free(&asn_DEF_NR_BCCH_BCH_Message, (void *)sib1, 1 ); - } - sib1 = bcch_message->message.choice.c1->choice.systemInformationBlockType1; - if (*(int64_t*)sib1 != 1) { - LOG_I(RRC, "SIB1 decoded\n"); - if( g_log->log_component[RRC].level >= OAILOG_DEBUG ) - xer_fprint(stdout, &asn_DEF_NR_SIB1, (const void*)sib1); - } - else - LOG_E(PHY, "sib1 is starting by 8 times 0\n"); - } - - return 0; -} - - // from NR SRB3 int8_t nr_rrc_ue_decode_NR_DL_DCCH_Message( const module_id_t module_id, @@ -1784,10 +1698,10 @@ nr_rrc_ue_process_securityModeCommand( } //----------------------------------------------------------------------------- -void rrc_ue_generate_RRCSetupRequest( const protocol_ctxt_t *const ctxt_pP, const uint8_t gNB_index ) { +void nr_rrc_ue_generate_RRCSetupRequest(module_id_t module_id, const uint8_t gNB_index) { uint8_t i=0,rv[6]; - if(NR_UE_rrc_inst[ctxt_pP->module_id].Srb0[gNB_index].Tx_buffer.payload_size ==0) { + if(NR_UE_rrc_inst[module_id].Srb0[gNB_index].Tx_buffer.payload_size ==0) { // Get RRCConnectionRequest, fill random for now // Generate random byte stream for contention resolution for (i=0; i<6; i++) { @@ -1801,16 +1715,16 @@ void rrc_ue_generate_RRCSetupRequest( const protocol_ctxt_t *const ctxt_pP, cons } LOG_T(NR_RRC,"\n"); - NR_UE_rrc_inst[ctxt_pP->module_id].Srb0[gNB_index].Tx_buffer.payload_size = - do_RRCSetupRequest( - ctxt_pP->module_id, - (uint8_t *)NR_UE_rrc_inst[ctxt_pP->module_id].Srb0[gNB_index].Tx_buffer.Payload, - rv); - LOG_I(NR_RRC,"[UE %d] : Frame %d, Logical Channel UL-CCCH (SRB0), Generating RRCSetupRequest (bytes %d, eNB %d)\n", - ctxt_pP->module_id, ctxt_pP->frame, NR_UE_rrc_inst[ctxt_pP->module_id].Srb0[gNB_index].Tx_buffer.payload_size, gNB_index); + NR_UE_rrc_inst[module_id].Srb0[gNB_index].Tx_buffer.payload_size = + do_RRCSetupRequest( + module_id, + (uint8_t *)NR_UE_rrc_inst[module_id].Srb0[gNB_index].Tx_buffer.Payload, + rv); + LOG_I(NR_RRC,"[UE %d] : Logical Channel UL-CCCH (SRB0), Generating RRCSetupRequest (bytes %d, gNB %d)\n", + module_id, NR_UE_rrc_inst[module_id].Srb0[gNB_index].Tx_buffer.payload_size, gNB_index); - for (i=0; imodule_id].Srb0[gNB_index].Tx_buffer.payload_size; i++) { - LOG_T(NR_RRC,"%x.",NR_UE_rrc_inst[ctxt_pP->module_id].Srb0[gNB_index].Tx_buffer.Payload[i]); + for (i=0; imcc, instance_p->mnc, instance_p->mnc_digit_length ASN_SEQUENCE_ADD(&servedCellMember->servedNRCellInfo.nrModeInfo.choice.tdd.nRFreqInfo.freqBandListNr, freq_band); switch (instance_p->N_RB_DL[i]) { + case 24: + servedCellMember->servedNRCellInfo.nrModeInfo.choice.tdd.nR_TxBW.nRNRB = X2AP_NRNRB_nrb24; + break; case 32: servedCellMember->servedNRCellInfo.nrModeInfo.choice.tdd.nR_TxBW.nRNRB = X2AP_NRNRB_nrb32; break; diff --git a/openair2/X2AP/x2ap_eNB_handler.c b/openair2/X2AP/x2ap_eNB_handler.c index f0e0fa9c23..1fb28ea05b 100644 --- a/openair2/X2AP/x2ap_eNB_handler.c +++ b/openair2/X2AP/x2ap_eNB_handler.c @@ -536,6 +536,14 @@ int x2ap_eNB_handle_x2_setup_response(instance_t instance, return -1; } + if((x2ap_eNB_data->state == X2AP_ENB_STATE_CONNECTED) || + (x2ap_eNB_data->state == X2AP_ENB_STATE_READY)) + + { + X2AP_ERROR("Received Unexpexted X2 Setup Response Message\n"); + return -1; + } + X2AP_DEBUG("Received a new X2 setup response\n"); X2AP_FIND_PROTOCOLIE_BY_ID(X2AP_X2SetupResponse_IEs_t, ie, x2SetupResponse, @@ -662,6 +670,14 @@ int x2ap_eNB_handle_x2_setup_failure(instance_t instance, return -1; } + if((x2ap_eNB_data->state == X2AP_ENB_STATE_CONNECTED) || + (x2ap_eNB_data->state == X2AP_ENB_STATE_READY)) + + { + X2AP_ERROR("Received Unexpexted X2 Setup Failure Message\n"); + return -1; + } + X2AP_DEBUG("Received a new X2 setup failure\n"); X2AP_FIND_PROTOCOLIE_BY_ID(X2AP_X2SetupFailure_IEs_t, ie, x2SetupFailure, @@ -730,6 +746,7 @@ int x2ap_eNB_handle_handover_preparation (instance_t instance, X2AP_ProtocolIE_ID_id_Old_eNB_UE_X2AP_ID, true); if (ie == NULL ) { X2AP_ERROR("%s %d: ie is a NULL pointer \n",__FILE__,__LINE__); + itti_free(ITTI_MSG_ORIGIN_ID(msg), msg); return -1; } @@ -750,7 +767,11 @@ int x2ap_eNB_handle_handover_preparation (instance_t instance, //measResultListEUTRA.list.array[ncell_index]->physCellId; X2AP_FIND_PROTOCOLIE_BY_ID(X2AP_HandoverRequest_IEs_t, ie, x2HandoverRequest, X2AP_ProtocolIE_ID_id_GUMMEI_ID, true); - + if (ie == NULL ) { + X2AP_ERROR("%s %d: ie is a NULL pointer \n",__FILE__,__LINE__); + itti_free(ITTI_MSG_ORIGIN_ID(msg), msg); + return -1; + } TBCD_TO_MCC_MNC(&ie->value.choice.ECGI.pLMN_Identity, X2AP_HANDOVER_REQ(msg).ue_gummei.mcc, X2AP_HANDOVER_REQ(msg).ue_gummei.mnc, X2AP_HANDOVER_REQ(msg).ue_gummei.mnc_len); OCTET_STRING_TO_INT8(&ie->value.choice.GUMMEI.mME_Code, X2AP_HANDOVER_REQ(msg).ue_gummei.mme_code); @@ -761,6 +782,7 @@ int x2ap_eNB_handle_handover_preparation (instance_t instance, if (ie == NULL ) { X2AP_ERROR("%s %d: ie is a NULL pointer \n",__FILE__,__LINE__); + itti_free(ITTI_MSG_ORIGIN_ID(msg), msg); return -1; } @@ -872,6 +894,7 @@ int x2ap_eNB_handle_handover_response (instance_t instance, if (ie == NULL ) { X2AP_ERROR("%s %d: ie is a NULL pointer \n",__FILE__,__LINE__); + itti_free(ITTI_MSG_ORIGIN_ID(msg), msg); return -1; } @@ -882,6 +905,7 @@ int x2ap_eNB_handle_handover_response (instance_t instance, if (ie == NULL ) { X2AP_ERROR("%s %d: ie is a NULL pointer \n",__FILE__,__LINE__); + itti_free(ITTI_MSG_ORIGIN_ID(msg), msg); return -1; } @@ -912,6 +936,7 @@ int x2ap_eNB_handle_handover_response (instance_t instance, if (ie == NULL ) { X2AP_ERROR("%s %d: ie is a NULL pointer \n", __FILE__, __LINE__); + itti_free(ITTI_MSG_ORIGIN_ID(msg), msg); return -1; }else{ if (ie->value.choice.E_RABs_Admitted_List.list.count > 0) { @@ -959,6 +984,12 @@ int x2ap_eNB_handle_handover_response (instance_t instance, X2AP_FIND_PROTOCOLIE_BY_ID(X2AP_HandoverRequestAcknowledge_IEs_t, ie, x2HandoverRequestAck, X2AP_ProtocolIE_ID_id_TargeteNBtoSource_eNBTransparentContainer, true); + if (ie == NULL ) { + X2AP_ERROR("%s %d: ie is a NULL pointer \n",__FILE__,__LINE__); + itti_free(ITTI_MSG_ORIGIN_ID(msg), msg); + return -1; + } + X2AP_TargeteNBtoSource_eNBTransparentContainer_t *c = &ie->value.choice.TargeteNBtoSource_eNBTransparentContainer; if (c->size > 1024 /* TODO: this is the size of rrc_buffer in struct x2ap_handover_req_ack_s */) @@ -1012,6 +1043,7 @@ int x2ap_eNB_handle_ue_context_release (instance_t instance, if (ie == NULL ) { X2AP_ERROR("%s %d: ie is a NULL pointer \n",__FILE__,__LINE__); + itti_free(ITTI_MSG_ORIGIN_ID(msg), msg); return -1; } @@ -1022,6 +1054,7 @@ int x2ap_eNB_handle_ue_context_release (instance_t instance, if (ie == NULL ) { X2AP_ERROR("%s %d: ie is a NULL pointer \n",__FILE__,__LINE__); + itti_free(ITTI_MSG_ORIGIN_ID(msg), msg); return -1; } diff --git a/openair3/GTPV1-U/gtpv1u_eNB.c b/openair3/GTPV1-U/gtpv1u_eNB.c index 4769380d18..847002ab44 100644 --- a/openair3/GTPV1-U/gtpv1u_eNB.c +++ b/openair3/GTPV1-U/gtpv1u_eNB.c @@ -1211,7 +1211,7 @@ int gtpv1u_eNB_init(void) { //gtpv1u_data_g.udp_data; RC.gtpv1u_data_g->seq_num = 0; RC.gtpv1u_data_g->restart_counter = 0; - + RC.gtpv1u_data_g->enb_ip_address_for_S1u_S12_S4_up = 0; /* Initializing GTPv1-U stack */ if ((rc = nwGtpv1uInitialize(&RC.gtpv1u_data_g->gtpv1u_stack, GTPU_STACK_ENB)) != NW_GTPV1U_OK) { LOG_E(GTPU, "Failed to setup nwGtpv1u stack %x\n", rc); diff --git a/openair3/NAS/COMMON/EMM/MSG/AttachAccept.c b/openair3/NAS/COMMON/EMM/MSG/AttachAccept.c index 8ac43cf7b1..637d930226 100644 --- a/openair3/NAS/COMMON/EMM/MSG/AttachAccept.c +++ b/openair3/NAS/COMMON/EMM/MSG/AttachAccept.c @@ -190,7 +190,6 @@ int decode_attach_accept(attach_accept_msg *attach_accept, uint8_t *buffer, uint default: errorCodeDecoder = TLV_DECODE_UNEXPECTED_IEI; LOG_TRACE(WARNING, "DECODE_UNEXPECTED_IEI %x (4 bits)", ieiDecoded); - AssertFatal(0, " "); return TLV_DECODE_UNEXPECTED_IEI; } } diff --git a/openair3/NAS/COMMON/IES/SupportedCodecList.c b/openair3/NAS/COMMON/IES/SupportedCodecList.c index 3a69eee366..15a2fecaa0 100644 --- a/openair3/NAS/COMMON/IES/SupportedCodecList.c +++ b/openair3/NAS/COMMON/IES/SupportedCodecList.c @@ -43,13 +43,17 @@ int decode_supported_codec_list(SupportedCodecList *supportedcodeclist, uint8_t CHECK_LENGTH_DECODER(len - decoded, ielen); supportedcodeclist->systemidentification = *(buffer + decoded); decoded++; + ielen--; supportedcodeclist->lengthofbitmap = *(buffer + decoded); decoded++; + ielen--; //IES_DECODE_U16(supportedcodeclist->codecbitmap, *(buffer + decoded)); IES_DECODE_U16(buffer, decoded, supportedcodeclist->codecbitmap); + ielen=ielen -2; #if defined (NAS_DEBUG) dump_supported_codec_list_xml(supportedcodeclist, iei); #endif + decoded = decoded + ielen; return decoded; } int encode_supported_codec_list(SupportedCodecList *supportedcodeclist, uint8_t iei, uint8_t *buffer, uint32_t len) diff --git a/openair3/NAS/UE/EMM/SAP/emm_as.c b/openair3/NAS/UE/EMM/SAP/emm_as.c index 99a3763dea..10b118eac0 100644 --- a/openair3/NAS/UE/EMM/SAP/emm_as.c +++ b/openair3/NAS/UE/EMM/SAP/emm_as.c @@ -443,14 +443,14 @@ static int _emm_as_data_ind(nas_user_t *user, const emm_as_data_t *msg, int *emm EPS_MOBILITY_MANAGEMENT_MESSAGE) { /* Process EMM data */ rc = _emm_as_recv(user, plain_msg, bytes, emm_cause); + free(plain_msg); } else if (header.protocol_discriminator == EPS_SESSION_MANAGEMENT_MESSAGE) { const OctetString data = {bytes, (uint8_t *)plain_msg}; /* Foward ESM data to EPS session management */ rc = lowerlayer_data_ind(user, &data); + free(plain_msg); } - - free(plain_msg); } } else { /* Process successfull lower layer transfer indication */ diff --git a/openair3/NAS/UE/EMM/SecurityModeControl.c b/openair3/NAS/UE/EMM/SecurityModeControl.c index 67bfaf784e..b27270fadc 100644 --- a/openair3/NAS/UE/EMM/SecurityModeControl.c +++ b/openair3/NAS/UE/EMM/SecurityModeControl.c @@ -296,16 +296,16 @@ int emm_proc_security_mode_command(nas_user_t *user, int native_ksi, int ksi, else { /* Setup EMM cause code */ emm_cause = EMM_CAUSE_SECURITY_MODE_REJECTED; - - /* Release security mode control internal data */ - if (security_data->kenb.value) { - free(security_data->kenb.value); - security_data->kenb.value = NULL; - security_data->kenb.length = 0; - } } } + /* Release security mode control internal data */ + if (security_data->kenb.value) { + free(security_data->kenb.value); + security_data->kenb.value = NULL; + security_data->kenb.length = 0; + } + /* Setup EMM procedure handler to be executed upon receiving * lower layer notification */ rc = emm_proc_lowerlayer_initialize(user->lowerlayer_data, NULL, NULL, NULL, NULL); diff --git a/openair3/S1AP/s1ap_common.h b/openair3/S1AP/s1ap_common.h index 77d03f4ae4..efac0201a3 100644 --- a/openair3/S1AP/s1ap_common.h +++ b/openair3/S1AP/s1ap_common.h @@ -106,7 +106,12 @@ extern int asn1_xer_print; if (ie == NULL ) { \ S1AP_ERROR("S1AP_FIND_PROTOCOLIE_BY_ID: %s %d: ie is NULL\n",__FILE__,__LINE__);\ } \ - if (mandatory) DevAssert(ie != NULL); \ + if (mandatory) { \ + if (ie == NULL) { \ + S1AP_ERROR("S1AP_FIND_PROTOCOLIE_BY_ID: %s %d: ie is NULL\n",__FILE__,__LINE__);\ + return -1; \ + } \ + } \ } while(0) /** \brief Function callback prototype. **/ diff --git a/openair3/S1AP/s1ap_eNB.c b/openair3/S1AP/s1ap_eNB.c index 31ea3359da..e528c9e53e 100644 --- a/openair3/S1AP/s1ap_eNB.c +++ b/openair3/S1AP/s1ap_eNB.c @@ -73,6 +73,42 @@ void s1ap_eNB_handle_register_eNB(instance_t instance, s1ap_register_enb_req_t * void s1ap_eNB_handle_sctp_association_resp(instance_t instance, sctp_new_association_resp_t *sctp_new_association_resp); +static int s1ap_sctp_req(s1ap_eNB_instance_t *instance_p, + s1ap_eNB_mme_data_t *s1ap_mme_data_p); +void s1ap_eNB_timer_expired(instance_t instance, + timer_has_expired_t *msg_p); + +int s1ap_timer_setup( + uint32_t interval_sec, + uint32_t interval_us, + task_id_t task_id, + int32_t instance, + uint32_t timer_kind, + timer_type_t type, + void *timer_arg, + long *timer_id) +{ + uint32_t *timeoutArg=NULL; + int ret=0; + timeoutArg=malloc(sizeof(uint32_t)); + *timeoutArg=timer_kind; + ret=timer_setup(interval_sec, + interval_us, + task_id, + instance, + type, + (void*)timeoutArg, + timer_id); + return ret; +} + +int s1ap_timer_remove(long timer_id) +{ + int ret; + ret=timer_remove(timer_id); + return ret; +} + uint32_t s1ap_generate_eNB_id(void) { char *out; char hostname[50]; @@ -98,7 +134,7 @@ static void s1ap_eNB_register_mme(s1ap_eNB_instance_t *instance_p, MessageDef *message_p = NULL; sctp_new_association_req_t *sctp_new_association_req_p = NULL; s1ap_eNB_mme_data_t *s1ap_mme_data_p = NULL; - struct s1ap_eNB_mme_data_s *mme = NULL; +// struct s1ap_eNB_mme_data_s *mme = NULL; DevAssert(instance_p != NULL); DevAssert(mme_ip_address != NULL); message_p = itti_alloc_new_message(TASK_S1AP, 0, SCTP_NEW_ASSOCIATION_REQ); @@ -114,51 +150,32 @@ static void s1ap_eNB_register_mme(s1ap_eNB_instance_t *instance_p, local_ip_addr, sizeof(*local_ip_addr)); S1AP_INFO("[eNB %ld] check the mme registration state\n",instance_p->instance); - mme = NULL; + /* Create new MME descriptor */ + s1ap_mme_data_p = calloc(1, sizeof(*s1ap_mme_data_p)); + DevAssert(s1ap_mme_data_p != NULL); + s1ap_mme_data_p->cnx_id = s1ap_eNB_fetch_add_global_cnx_id(); + sctp_new_association_req_p->ulp_cnx_id = s1ap_mme_data_p->cnx_id; + s1ap_mme_data_p->assoc_id = -1; + s1ap_mme_data_p->broadcast_plmn_num = broadcast_plmn_num; + memcpy(&s1ap_mme_data_p->mme_s1_ip, + mme_ip_address, + sizeof(*mme_ip_address)); + s1ap_mme_data_p->mme_port = mme_port; + for (int i = 0; i < broadcast_plmn_num; ++i) + s1ap_mme_data_p->broadcast_plmn_index[i] = broadcast_plmn_index[i]; - if ( mme == NULL ) { - /* Create new MME descriptor */ - s1ap_mme_data_p = calloc(1, sizeof(*s1ap_mme_data_p)); - DevAssert(s1ap_mme_data_p != NULL); - s1ap_mme_data_p->cnx_id = s1ap_eNB_fetch_add_global_cnx_id(); - sctp_new_association_req_p->ulp_cnx_id = s1ap_mme_data_p->cnx_id; - s1ap_mme_data_p->assoc_id = -1; - s1ap_mme_data_p->broadcast_plmn_num = broadcast_plmn_num; - memcpy(&s1ap_mme_data_p->mme_s1_ip, - mme_ip_address, - sizeof(*mme_ip_address)); - s1ap_mme_data_p->mme_port = mme_port; - for (int i = 0; i < broadcast_plmn_num; ++i) - s1ap_mme_data_p->broadcast_plmn_index[i] = broadcast_plmn_index[i]; - - s1ap_mme_data_p->s1ap_eNB_instance = instance_p; - STAILQ_INIT(&s1ap_mme_data_p->served_gummei); - /* Insert the new descriptor in list of known MME - * but not yet associated. - */ - RB_INSERT(s1ap_mme_map, &instance_p->s1ap_mme_head, s1ap_mme_data_p); - s1ap_mme_data_p->state = S1AP_ENB_STATE_WAITING; - instance_p->s1ap_mme_nb ++; - instance_p->s1ap_mme_pending_nb ++; - } else if (mme->state == S1AP_ENB_STATE_WAITING) { - instance_p->s1ap_mme_pending_nb ++; - sctp_new_association_req_p->ulp_cnx_id = mme->cnx_id; - S1AP_INFO("[eNB %ld] MME already registered, retrive the data (state %d, cnx %d, mme_nb %d, mme_pending_nb %d)\n", - instance_p->instance, - mme->state, mme->cnx_id, - instance_p->s1ap_mme_nb, instance_p->s1ap_mme_pending_nb); - /*s1ap_mme_data_p->cnx_id = mme->cnx_id; - sctp_new_association_req_p->ulp_cnx_id = mme->cnx_id; - - s1ap_mme_data_p->assoc_id = -1; - s1ap_mme_data_p->s1ap_eNB_instance = instance_p; - */ - } else { - S1AP_WARN("[eNB %ld] MME already registered but not in the waiting state, retrive the data (state %d, cnx %d, mme_nb %d, mme_pending_nb %d)\n", - instance_p->instance, - mme->state, mme->cnx_id, - instance_p->s1ap_mme_nb, instance_p->s1ap_mme_pending_nb); - } + s1ap_mme_data_p->s1ap_eNB_instance = instance_p; + STAILQ_INIT(&s1ap_mme_data_p->served_gummei); + /* Insert the new descriptor in list of known MME + * but not yet associated. + */ + RB_INSERT(s1ap_mme_map, &instance_p->s1ap_mme_head, s1ap_mme_data_p); + s1ap_mme_data_p->state = S1AP_ENB_STATE_DISCONNECTED; + memcpy( &(s1ap_mme_data_p->mme_ip_address), mme_ip_address, sizeof(net_ip_address_t) ); + s1ap_mme_data_p->overload_state = S1AP_NO_OVERLOAD; + s1ap_mme_data_p->sctp_req_cnt++; + s1ap_mme_data_p->timer_id = S1AP_TIMERID_INIT; + instance_p->s1ap_mme_pending_nb ++; itti_send_msg_to_task(TASK_SCTP, instance_p->instance, message_p); } @@ -196,10 +213,10 @@ void s1ap_eNB_handle_register_eNB(instance_t instance, s1ap_register_enb_req_t * new_instance->eNB_id = s1ap_register_eNB->eNB_id; new_instance->cell_type = s1ap_register_eNB->cell_type; new_instance->tac = s1ap_register_eNB->tac; - + memcpy(&new_instance->eNB_s1_ip, - &s1ap_register_eNB->enb_ip_address, - sizeof(s1ap_register_eNB->enb_ip_address)); + &s1ap_register_eNB->enb_ip_address, + sizeof(s1ap_register_eNB->enb_ip_address)); for (int i = 0; i < s1ap_register_eNB->num_plmn; i++) { new_instance->mcc[i] = s1ap_register_eNB->mcc[i]; @@ -207,6 +224,15 @@ void s1ap_eNB_handle_register_eNB(instance_t instance, s1ap_register_enb_req_t * new_instance->mnc_digit_length[i] = s1ap_register_eNB->mnc_digit_length[i]; } + memcpy( &(new_instance->enb_ip_address), &(s1ap_register_eNB->enb_ip_address), sizeof(net_ip_address_t) ); + new_instance->s1_setuprsp_wait_timer = s1ap_register_eNB->s1_setuprsp_wait_timer; + new_instance->s1_setupreq_wait_timer = s1ap_register_eNB->s1_setupreq_wait_timer; + new_instance->s1_setupreq_count = s1ap_register_eNB->s1_setupreq_count; + new_instance->sctp_req_timer = s1ap_register_eNB->sctp_req_timer; + new_instance->sctp_req_count = s1ap_register_eNB->sctp_req_count; + new_instance->sctp_in_streams = s1ap_register_eNB->sctp_in_streams; + new_instance->sctp_out_streams = s1ap_register_eNB->sctp_out_streams; + new_instance->num_plmn = s1ap_register_eNB->num_plmn; new_instance->default_drx = s1ap_register_eNB->default_drx; /* Add the new instance to the list of eNB (meaningfull in virtual mode) */ @@ -217,8 +243,12 @@ void s1ap_eNB_handle_register_eNB(instance_t instance, s1ap_register_enb_req_t * s1ap_register_eNB->eNB_id); } - DevCheck(s1ap_register_eNB->nb_mme <= S1AP_MAX_NB_MME_IP_ADDRESS, - S1AP_MAX_NB_MME_IP_ADDRESS, s1ap_register_eNB->nb_mme, 0); + if( s1ap_register_eNB->nb_mme > S1AP_MAX_NB_MME_IP_ADDRESS ) + { + S1AP_ERROR("Invalid MME number = %d\n ", s1ap_register_eNB->nb_mme); + s1ap_register_eNB->nb_mme = S1AP_MAX_NB_MME_IP_ADDRESS; + } + new_instance->s1ap_mme_nb = s1ap_register_eNB->nb_mme; /* Trying to connect to provided list of MME ip address */ for (index = 0; index < s1ap_register_eNB->nb_mme; index++) { @@ -250,28 +280,131 @@ void s1ap_eNB_handle_register_eNB(instance_t instance, s1ap_register_enb_req_t * void s1ap_eNB_handle_sctp_association_resp(instance_t instance, sctp_new_association_resp_t *sctp_new_association_resp) { s1ap_eNB_instance_t *instance_p; s1ap_eNB_mme_data_t *s1ap_mme_data_p; + s1ap_eNB_ue_context_t *ue_p = NULL; + MessageDef *message_p = NULL; + uint32_t timer_kind = 0; + struct plmn_identity_s* plmnInfo; + struct served_group_id_s* groupInfo; + struct served_gummei_s* gummeiInfo; + struct mme_code_s* mmeCode; + int8_t cnt = 0; + unsigned enb_s1ap_id[NUMBER_OF_UE_MAX]; DevAssert(sctp_new_association_resp != NULL); instance_p = s1ap_eNB_get_instance(instance); DevAssert(instance_p != NULL); s1ap_mme_data_p = s1ap_eNB_get_MME(instance_p, -1, sctp_new_association_resp->ulp_cnx_id); DevAssert(s1ap_mme_data_p != NULL); - - if (sctp_new_association_resp->sctp_state != SCTP_STATE_ESTABLISHED) { - S1AP_WARN("Received unsuccessful result for SCTP association (%u), instance %ld, cnx_id %u\n", - sctp_new_association_resp->sctp_state, - instance, - sctp_new_association_resp->ulp_cnx_id); - s1ap_handle_s1_setup_message(s1ap_mme_data_p, sctp_new_association_resp->sctp_state == SCTP_STATE_SHUTDOWN); - return; + memset(enb_s1ap_id, 0, sizeof(enb_s1ap_id) ); + if( s1ap_mme_data_p->timer_id != S1AP_TIMERID_INIT ) { + s1ap_timer_remove( s1ap_mme_data_p->timer_id ); + s1ap_mme_data_p->timer_id = S1AP_TIMERID_INIT; } + + if( sctp_new_association_resp->sctp_state != SCTP_STATE_ESTABLISHED ) { + RB_FOREACH(ue_p, s1ap_ue_map, &instance_p->s1ap_ue_head) { + if( ue_p->mme_ref == s1ap_mme_data_p ) { + if(cnt < NUMBER_OF_UE_MAX) { + enb_s1ap_id[cnt] = ue_p->eNB_ue_s1ap_id; + cnt++; + + message_p = NULL; + message_p = itti_alloc_new_message(TASK_S1AP, 0, S1AP_UE_CONTEXT_RELEASE_COMMAND); + + if( message_p != NULL ) { + S1AP_UE_CONTEXT_RELEASE_COMMAND(message_p).eNB_ue_s1ap_id = ue_p->eNB_ue_s1ap_id; + + if( itti_send_msg_to_task(TASK_RRC_ENB, ue_p->eNB_instance->instance, message_p) < 0 ) { + S1AP_ERROR("UE Context Release Command Transmission Failure: eNB_ue_s1ap_id=%u\n", ue_p->eNB_ue_s1ap_id); + } + } else { + S1AP_ERROR("Invalid message_p : eNB_ue_s1ap_id=%u\n", ue_p->eNB_ue_s1ap_id); + } + }else{ + S1AP_ERROR("s1ap_eNB_handle_sctp_association_resp: cnt %d > max\n", cnt); + } + } + } + for( ; cnt > 0 ; ) { + cnt--; + struct s1ap_eNB_ue_context_s *ue_context_p = NULL; + struct s1ap_eNB_ue_context_s *s1ap_ue_context_p = NULL; + ue_context_p = s1ap_eNB_get_ue_context(instance_p, (uint32_t)enb_s1ap_id[cnt]); + if (ue_context_p != NULL) { + s1ap_ue_context_p = RB_REMOVE(s1ap_ue_map, &instance_p->s1ap_ue_head, ue_context_p); + s1ap_eNB_free_ue_context(s1ap_ue_context_p); + } + } + s1ap_mme_data_p->mme_name = 0; + s1ap_mme_data_p->overload_state = S1AP_NO_OVERLOAD; + s1ap_mme_data_p->nextstream = 0; + s1ap_mme_data_p->in_streams = 0; + s1ap_mme_data_p->out_streams = 0; + s1ap_mme_data_p->assoc_id = -1; + + while (!STAILQ_EMPTY(&s1ap_mme_data_p->served_gummei)) { + gummeiInfo = STAILQ_FIRST(&s1ap_mme_data_p->served_gummei); + STAILQ_REMOVE_HEAD(&s1ap_mme_data_p->served_gummei, next); - /* Update parameters */ - s1ap_mme_data_p->assoc_id = sctp_new_association_resp->assoc_id; - s1ap_mme_data_p->in_streams = sctp_new_association_resp->in_streams; - s1ap_mme_data_p->out_streams = sctp_new_association_resp->out_streams; - /* Prepare new S1 Setup Request */ - s1ap_eNB_generate_s1_setup_request(instance_p, s1ap_mme_data_p); + while (!STAILQ_EMPTY(&gummeiInfo->served_plmns)) { + plmnInfo = STAILQ_FIRST(&gummeiInfo->served_plmns); + STAILQ_REMOVE_HEAD(&gummeiInfo->served_plmns, next); + free(plmnInfo); + } + while (!STAILQ_EMPTY(&gummeiInfo->served_group_ids)) { + groupInfo = STAILQ_FIRST(&gummeiInfo->served_group_ids); + STAILQ_REMOVE_HEAD(&gummeiInfo->served_group_ids, next); + free(groupInfo); + } + while (!STAILQ_EMPTY(&gummeiInfo->mme_codes)) { + mmeCode = STAILQ_FIRST(&gummeiInfo->mme_codes); + STAILQ_REMOVE_HEAD(&gummeiInfo->mme_codes, next); + free(mmeCode); + } + free(gummeiInfo); + } + + STAILQ_INIT(&s1ap_mme_data_p->served_gummei); + + if( s1ap_mme_data_p->state == S1AP_ENB_STATE_DISCONNECTED ) { + if( (s1ap_mme_data_p->sctp_req_cnt <= instance_p->sctp_req_count) || + (instance_p->sctp_req_count == 0xffff) ) { + timer_kind = s1ap_mme_data_p->cnx_id; + timer_kind = timer_kind | S1AP_MMEIND; + timer_kind = timer_kind | SCTP_REQ_WAIT; + + if( s1ap_timer_setup( instance_p->sctp_req_timer, 0, TASK_S1AP, instance_p->instance, + timer_kind, S1AP_TIMER_ONE_SHOT, NULL, &s1ap_mme_data_p->timer_id) < 0 ) { + S1AP_ERROR("Timer Start NG(SCTP retransmission wait timer) : MME=%d\n",s1ap_mme_data_p->cnx_id); + s1ap_sctp_req( instance_p, s1ap_mme_data_p ); + } + } else { + S1AP_ERROR("Retransmission count exceeded of SCTP : MME=%d\n",s1ap_mme_data_p->cnx_id); + } + } else { + S1AP_ERROR("SCTP disconnection reception : MME = %d\n",s1ap_mme_data_p->cnx_id); + + if( (s1ap_mme_data_p->sctp_req_cnt <= instance_p->sctp_req_count) || + (instance_p->sctp_req_count == 0xffff) ) { + s1ap_sctp_req( instance_p, s1ap_mme_data_p ); + } else { + S1AP_ERROR("Retransmission count exceeded of SCTP : MME=%d\n",s1ap_mme_data_p->cnx_id); + } + s1ap_mme_data_p->state = S1AP_ENB_STATE_DISCONNECTED; + } + } else { + /* Update parameters */ + s1ap_mme_data_p->assoc_id = sctp_new_association_resp->assoc_id; + s1ap_mme_data_p->in_streams = sctp_new_association_resp->in_streams; + s1ap_mme_data_p->out_streams = sctp_new_association_resp->out_streams; + /* Prepare new S1 Setup Request */ + s1ap_mme_data_p->s1_setupreq_cnt = 0; + s1ap_mme_data_p->sctp_req_cnt = 0; + if (s1ap_eNB_generate_s1_setup_request(instance_p, s1ap_mme_data_p) == -1) { + S1AP_ERROR("s1ap eNB generate s1 setup request failed\n"); + return; + } + } } static @@ -282,13 +415,94 @@ void s1ap_eNB_handle_sctp_data_ind(sctp_data_ind_t *sctp_data_ind) { mme_test_s1_notify_sctp_data_ind(sctp_data_ind->assoc_id, sctp_data_ind->stream, sctp_data_ind->buffer, sctp_data_ind->buffer_length); #else - s1ap_eNB_handle_message(sctp_data_ind->assoc_id, sctp_data_ind->stream, - sctp_data_ind->buffer, sctp_data_ind->buffer_length); + if (s1ap_eNB_handle_message(sctp_data_ind->assoc_id, sctp_data_ind->stream, + sctp_data_ind->buffer, sctp_data_ind->buffer_length) == -1) { + S1AP_ERROR("Failed to handle s1ap eNB message\n"); + } #endif result = itti_free(TASK_UNKNOWN, sctp_data_ind->buffer); AssertFatal (result == EXIT_SUCCESS, "Failed to free memory (%d)!\n", result); } +void s1ap_eNB_timer_expired( + instance_t instance, + timer_has_expired_t *msg_p) +{ + uint32_t timer_kind = 0; + int16_t line_ind = 0; + s1ap_eNB_mme_data_t *mme_desc_p = NULL; + uint32_t timer_ind = 0; + s1ap_eNB_instance_t *instance_p = NULL; + long timer_id = S1AP_TIMERID_INIT; + + instance_p = s1ap_eNB_get_instance(instance); + if(msg_p->arg!=NULL){ + timer_kind = *((uint32_t*)msg_p->arg); + free(msg_p->arg); + }else{ + S1AP_ERROR("s1 timer timer_kind is NULL\n"); + return; + } + line_ind = (int16_t)(timer_kind & S1AP_LINEIND); + timer_id = msg_p->timer_id; + + if( (timer_kind & S1AP_MMEIND) == S1AP_MMEIND ) { + mme_desc_p = s1ap_eNB_get_MME(instance_p, -1, line_ind); + if(mme_desc_p != NULL) { + if( timer_id == mme_desc_p->timer_id ) { + mme_desc_p->timer_id = S1AP_TIMERID_INIT; + timer_ind = timer_kind & S1AP_TIMERIND; + + switch(timer_ind) + { + case S1_SETRSP_WAIT: + { + if( (instance_p->s1_setupreq_count >= mme_desc_p->s1_setupreq_cnt) || + (instance_p->s1_setupreq_count == 0xffff) ) { + s1ap_eNB_generate_s1_setup_request( instance_p, mme_desc_p ); + } else { + S1AP_ERROR("Retransmission count exceeded of S1 SETUP REQUEST : MME=%d\n",line_ind); + } + break; + } + case S1_SETREQ_WAIT: + { + if( (instance_p->s1_setupreq_count >= mme_desc_p->s1_setupreq_cnt) || + (instance_p->s1_setupreq_count == 0xffff) ) { + s1ap_eNB_generate_s1_setup_request( instance_p, mme_desc_p ); + } else { + S1AP_ERROR("Retransmission count exceeded of S1 SETUP REQUEST : MME=%d\n",line_ind); + } + break; + } + case SCTP_REQ_WAIT: + { + if( (instance_p->sctp_req_count >= mme_desc_p->sctp_req_cnt) || + (instance_p->sctp_req_count == 0xffff) ) { + s1ap_sctp_req( instance_p, mme_desc_p ); + } else { + S1AP_ERROR("Retransmission count exceeded of SCTP : MME=%d\n",line_ind); + } + break; + } + default: + { + S1AP_WARN("Invalid Timer indication\n"); + break; + } + } + } else { + S1AP_DEBUG("Unmatch timer id\n"); + return; + } + } else { + S1AP_WARN("Not applicable MME detected : connection id = %d\n", line_ind); + return; + } + } + return; +} + void s1ap_eNB_init(void) { S1AP_DEBUG("Starting S1AP layer\n"); s1ap_eNB_prepare_internal_data(); @@ -412,6 +626,13 @@ void *s1ap_eNB_process_itti_msg(void *notUsed) { } break; + case TIMER_HAS_EXPIRED: + { + s1ap_eNB_timer_expired(ITTI_MSG_DESTINATION_INSTANCE(received_msg), + &received_msg->ittiMsg.timer_has_expired); + } + break; + default: S1AP_ERROR("Received unhandled message: %d:%s\n", ITTI_MSG_ID(received_msg), ITTI_MSG_NAME(received_msg)); @@ -452,6 +673,7 @@ static int s1ap_eNB_generate_s1_setup_request( uint8_t *buffer = NULL; uint32_t len = 0; int ret = 0; + uint32_t timer_kind = 0; DevAssert(instance_p != NULL); DevAssert(s1ap_mme_data_p != NULL); s1ap_mme_data_p->state = S1AP_ENB_STATE_WAITING; @@ -526,6 +748,17 @@ static int s1ap_eNB_generate_s1_setup_request( return -1; } + timer_kind = s1ap_mme_data_p->cnx_id; + timer_kind = timer_kind | S1AP_MMEIND; + timer_kind = timer_kind | S1_SETRSP_WAIT; + + if( s1ap_timer_setup(instance_p->s1_setuprsp_wait_timer, 0, TASK_S1AP, instance_p->instance, timer_kind, S1AP_TIMER_ONE_SHOT, + NULL, &s1ap_mme_data_p->timer_id) < 0 ) + { + S1AP_ERROR("Timer Start NG(S1 Setup Response) : MME=%d\n",s1ap_mme_data_p->cnx_id); + } + s1ap_mme_data_p->s1_setupreq_cnt++; + /* Non UE-Associated signalling -> stream = 0 */ s1ap_eNB_itti_send_sctp_data_req(instance_p->instance, s1ap_mme_data_p->assoc_id, buffer, len, 0); return ret; @@ -534,3 +767,55 @@ static int s1ap_eNB_generate_s1_setup_request( +static int s1ap_sctp_req(s1ap_eNB_instance_t *instance_p, + s1ap_eNB_mme_data_t *s1ap_mme_data_p) +{ + MessageDef *message_p = NULL; + sctp_new_association_req_t *sctp_new_association_req_p = NULL; + + if( instance_p == NULL ) + { + S1AP_ERROR("Invalid instance_p\n"); + return -1; + } + + message_p = itti_alloc_new_message(TASK_S1AP, 0, SCTP_NEW_ASSOCIATION_REQ); + sctp_new_association_req_p = &message_p->ittiMsg.sctp_new_association_req; + sctp_new_association_req_p->port = S1AP_PORT_NUMBER; + sctp_new_association_req_p->ppid = S1AP_SCTP_PPID; + sctp_new_association_req_p->in_streams = instance_p->sctp_in_streams; + sctp_new_association_req_p->out_streams = instance_p->sctp_out_streams; + sctp_new_association_req_p->ulp_cnx_id = s1ap_mme_data_p->cnx_id; + + if( s1ap_mme_data_p->mme_ip_address.ipv4 != 0 ) { + memcpy(&sctp_new_association_req_p->remote_address, + &s1ap_mme_data_p->mme_ip_address, + sizeof(net_ip_address_t)); + if( instance_p->enb_ip_address.ipv4 != 0 ) { + memcpy(&sctp_new_association_req_p->local_address, + &instance_p->enb_ip_address, + sizeof(net_ip_address_t)); + } else { + S1AP_ERROR("Invalid IP Address Format V4(MME):V6\n"); + return -1; + } + } else { + memcpy(&sctp_new_association_req_p->remote_address, + &s1ap_mme_data_p->mme_ip_address, + sizeof(net_ip_address_t)); + if( instance_p->enb_ip_address.ipv6 != 0 ) { + memcpy(&sctp_new_association_req_p->local_address, + &instance_p->enb_ip_address, + sizeof(net_ip_address_t)); + } else { + S1AP_ERROR("Invalid IP Address Format V6(MME):V4\n"); + return -1; + } + } + + itti_send_msg_to_task(TASK_SCTP, instance_p->instance, message_p); + + s1ap_mme_data_p->sctp_req_cnt++; + + return 0; +} diff --git a/openair3/S1AP/s1ap_eNB.h b/openair3/S1AP/s1ap_eNB.h index 2abbc53ec9..2183587214 100644 --- a/openair3/S1AP/s1ap_eNB.h +++ b/openair3/S1AP/s1ap_eNB.h @@ -30,6 +30,22 @@ #ifndef S1AP_ENB_H_ #define S1AP_ENB_H_ +#define S1AP_MMEIND 0x80000000 +#define S1AP_UEIND 0x00000000 +#define S1_SETRSP_WAIT 0x00010000 +#define S1_SETREQ_WAIT 0x00020000 +#define SCTP_REQ_WAIT 0x00030000 +#define S1AP_LINEIND 0x0000ffff +#define S1AP_TIMERIND 0x00ff0000 + +#define S1AP_TIMERID_INIT 0xffffffffffffffff + +typedef enum s1ap_timer_type_s { + S1AP_TIMER_PERIODIC, + S1AP_TIMER_ONE_SHOT, + S1AP_TIMER_TYPE_MAX, +} s1ap_timer_type_t; + typedef struct s1ap_eNB_config_s { // MME related params unsigned char mme_enabled; ///< MME enabled ? @@ -43,6 +59,7 @@ void *s1ap_eNB_process_itti_msg(void*); void s1ap_eNB_init(void); void *s1ap_eNB_task(void *arg); +int s1ap_timer_remove(long timer_id); uint32_t s1ap_generate_eNB_id(void); #endif /* S1AP_ENB_H_ */ diff --git a/openair3/S1AP/s1ap_eNB_decoder.c b/openair3/S1AP/s1ap_eNB_decoder.c index 4635946a05..14e4b49238 100644 --- a/openair3/S1AP/s1ap_eNB_decoder.c +++ b/openair3/S1AP/s1ap_eNB_decoder.c @@ -89,8 +89,6 @@ static int s1ap_eNB_decode_initiating_message(S1AP_S1AP_PDU_t *pdu) { default: S1AP_ERROR("Unknown procedure ID (%d) for initiating message\n", (int)pdu->choice.initiatingMessage.procedureCode); - AssertFatal( 0, "Unknown procedure ID (%d) for initiating message\n", - (int)pdu->choice.initiatingMessage.procedureCode); return -1; } diff --git a/openair3/S1AP/s1ap_eNB_defs.h b/openair3/S1AP/s1ap_eNB_defs.h index d8a8da8001..ed0909d66e 100644 --- a/openair3/S1AP/s1ap_eNB_defs.h +++ b/openair3/S1AP/s1ap_eNB_defs.h @@ -165,6 +165,12 @@ typedef struct s1ap_eNB_mme_data_s { /* Only meaningfull in virtual mode */ struct s1ap_eNB_instance_s *s1ap_eNB_instance; + + uint32_t nb_calls; + net_ip_address_t mme_ip_address; + long timer_id; + uint16_t s1_setupreq_cnt; + uint16_t sctp_req_cnt; } s1ap_eNB_mme_data_t; typedef struct s1ap_eNB_instance_s { @@ -217,6 +223,14 @@ typedef struct s1ap_eNB_instance_s { /* Default Paging DRX of the eNB as defined in TS 36.304 */ paging_drx_t default_drx; + net_ip_address_t enb_ip_address; + uint16_t s1_setuprsp_wait_timer; + uint16_t s1_setupreq_wait_timer; + uint16_t s1_setupreq_count; + uint16_t sctp_req_timer; + uint16_t sctp_req_count; + uint16_t sctp_in_streams; + uint16_t sctp_out_streams; } s1ap_eNB_instance_t; typedef struct { diff --git a/openair3/S1AP/s1ap_eNB_handlers.c b/openair3/S1AP/s1ap_eNB_handlers.c index 370d34868b..9ee3287b94 100644 --- a/openair3/S1AP/s1ap_eNB_handlers.c +++ b/openair3/S1AP/s1ap_eNB_handlers.c @@ -38,6 +38,9 @@ #include "s1ap_eNB_defs.h" #include "s1ap_eNB_handlers.h" #include "s1ap_eNB_decoder.h" +#include "s1ap_eNB_encoder.h" + +#include "s1ap_eNB_itti_messaging.h" #include "s1ap_eNB_ue_context.h" #include "s1ap_eNB_trace.h" @@ -109,6 +112,20 @@ int s1ap_eNB_handle_s1_ENDC_e_rab_modification_confirm(uint32_t as uint32_t stream, S1AP_S1AP_PDU_t *pdu); +static int s1ap_eNB_snd_s1_setup_request( + s1ap_eNB_instance_t *instance_p, + s1ap_eNB_mme_data_t *s1ap_mme_data_p); + +int s1ap_timer_setup( + uint32_t interval_sec, + uint32_t interval_us, + task_id_t task_id, + int32_t instance, + uint32_t timer_kind, + timer_type_t type, + void *timer_arg, + long *timer_id); + /* Handlers matrix. Only eNB related procedure present here */ s1ap_message_decoded_callback messages_callback[][3] = { { 0, 0, 0 }, /* HandoverPreparation */ @@ -260,6 +277,10 @@ int s1ap_eNB_handle_s1_setup_failure(uint32_t assoc_id, S1AP_S1SetupFailure_t *container; S1AP_S1SetupFailureIEs_t *ie; s1ap_eNB_mme_data_t *mme_desc_p; + uint32_t interval_sec = 0; + uint32_t timer_kind = 0; + s1ap_eNB_instance_t *instance_p; + DevAssert(pdu != NULL); container = &pdu->choice.unsuccessfulOutcome.value.choice.S1SetupFailure; @@ -270,7 +291,7 @@ int s1ap_eNB_handle_s1_setup_failure(uint32_t assoc_id, } if ((mme_desc_p = s1ap_eNB_get_MME(NULL, assoc_id, 0)) == NULL) { - S1AP_ERROR("[SCTP %d] Received S1 setup response for non existing " + S1AP_ERROR("[SCTP %d] Received S1 setup failure for non existing " "MME context\n", assoc_id); return -1; } @@ -278,6 +299,10 @@ int s1ap_eNB_handle_s1_setup_failure(uint32_t assoc_id, S1AP_FIND_PROTOCOLIE_BY_ID(S1AP_S1SetupFailureIEs_t, ie, container, S1AP_ProtocolIE_ID_id_Cause,true); + if(ie == NULL) { + return -1; + } + if ((ie->value.choice.Cause.present == S1AP_Cause_PR_misc) && (ie->value.choice.Cause.choice.misc == S1AP_CauseMisc_unspecified)) { S1AP_WARN("Received s1 setup failure for MME... MME is not ready\n"); @@ -285,8 +310,56 @@ int s1ap_eNB_handle_s1_setup_failure(uint32_t assoc_id, S1AP_ERROR("Received s1 setup failure for MME... please check your parameters\n"); } - mme_desc_p->state = S1AP_ENB_STATE_WAITING; - s1ap_handle_s1_setup_message(mme_desc_p, 0); + if( mme_desc_p->timer_id != S1AP_TIMERID_INIT ) { + s1ap_timer_remove( mme_desc_p->timer_id ); + mme_desc_p->timer_id = S1AP_TIMERID_INIT; + } + instance_p = mme_desc_p->s1ap_eNB_instance; + if( ( instance_p->s1_setupreq_count >= mme_desc_p->s1_setupreq_cnt) || + ( instance_p->s1_setupreq_count == 0xffff) ) { + S1AP_FIND_PROTOCOLIE_BY_ID(S1AP_S1SetupFailureIEs_t, ie, container, + S1AP_ProtocolIE_ID_id_TimeToWait, false); + if( ie != NULL ) { + switch(ie->value.choice.TimeToWait) + { + case S1AP_TimeToWait_v1s: + interval_sec = 1; + break; + case S1AP_TimeToWait_v2s: + interval_sec = 2; + break; + case S1AP_TimeToWait_v5s: + interval_sec = 5; + break; + case S1AP_TimeToWait_v10s: + interval_sec = 10; + break; + case S1AP_TimeToWait_v20s: + interval_sec = 20; + break; + case S1AP_TimeToWait_v60s: + interval_sec = 60; + break; + default: + interval_sec = instance_p->s1_setupreq_wait_timer; + break; + } + } else { + interval_sec = instance_p->s1_setupreq_wait_timer; + } + + timer_kind = mme_desc_p->cnx_id; + timer_kind = timer_kind | S1AP_MMEIND; + timer_kind = timer_kind | S1_SETREQ_WAIT; + + if( s1ap_timer_setup(interval_sec, 0, TASK_S1AP, instance_p->instance, timer_kind, S1AP_TIMER_ONE_SHOT, + NULL, &mme_desc_p->timer_id) < 0 ) { + S1AP_ERROR("Timer Start NG(S1 Setup Request) : MME=%d\n",mme_desc_p->cnx_id); + s1ap_eNB_snd_s1_setup_request( instance_p, mme_desc_p ); + } + } else { + S1AP_ERROR("Retransmission count exceeded of S1 SETUP REQUEST : MME=%d\n",mme_desc_p->cnx_id); + } return 0; } @@ -314,9 +387,27 @@ int s1ap_eNB_handle_s1_setup_response(uint32_t assoc_id, return -1; } + /* Set the capacity of this MME */ + S1AP_FIND_PROTOCOLIE_BY_ID(S1AP_S1SetupResponseIEs_t, ie, container, + S1AP_ProtocolIE_ID_id_RelativeMMECapacity, true); + if(ie == NULL) { + return -1; + } + mme_desc_p->relative_mme_capacity = ie->value.choice.RelativeMMECapacity; + S1AP_FIND_PROTOCOLIE_BY_ID(S1AP_S1SetupResponseIEs_t, ie, container, S1AP_ProtocolIE_ID_id_ServedGUMMEIs, true); + if(ie == NULL) { + return -1; + } + if( mme_desc_p->timer_id != S1AP_TIMERID_INIT ) + { + s1ap_timer_remove( mme_desc_p->timer_id ); + mme_desc_p->timer_id = S1AP_TIMERID_INIT; + } + mme_desc_p->s1_setupreq_cnt = 0; + mme_desc_p->sctp_req_cnt = 0; /* The list of served gummei can contain at most 8 elements. * LTE related gummei is the first element in the list, i.e with an id of 0. */ @@ -368,13 +459,7 @@ int s1ap_eNB_handle_s1_setup_response(uint32_t assoc_id, STAILQ_INSERT_TAIL(&mme_desc_p->served_gummei, new_gummei_p, next); } - - /* Set the capacity of this MME */ - S1AP_FIND_PROTOCOLIE_BY_ID(S1AP_S1SetupResponseIEs_t, ie, container, - S1AP_ProtocolIE_ID_id_RelativeMMECapacity, true); - - mme_desc_p->relative_mme_capacity = ie->value.choice.RelativeMMECapacity; - + /* Optionaly set the mme name */ S1AP_FIND_PROTOCOLIE_BY_ID(S1AP_S1SetupResponseIEs_t, ie, container, S1AP_ProtocolIE_ID_id_MMEname, false); @@ -392,7 +477,6 @@ int s1ap_eNB_handle_s1_setup_response(uint32_t assoc_id, */ mme_desc_p->state = S1AP_ENB_STATE_CONNECTED; mme_desc_p->s1ap_eNB_instance->s1ap_mme_associated_nb ++; - s1ap_handle_s1_setup_message(mme_desc_p, 0); return 0; } @@ -725,6 +809,9 @@ int s1ap_eNB_handle_error_indication(uint32_t assoc_id, S1AP_ProtocolIE_ID_id_CriticalityDiagnostics, false); if (ie) { + if( ie->value.choice.CriticalityDiagnostics.procedureCode ) { + S1AP_WARN("Received S1 Error indication CriticalityDiagnostics procedureCode = %ld\n", *ie->value.choice.CriticalityDiagnostics.procedureCode); + } // TODO continue } @@ -807,9 +894,11 @@ int s1ap_eNB_handle_initial_context_request(uint32_t assoc_id, &(S1AP_INITIAL_CONTEXT_SETUP_REQ(message_p).ue_ambr.br_dl)); /* id-E-RABToBeSetupListCtxtSUReq */ } else { + itti_free(ITTI_MSG_ORIGIN_ID(message_p), message_p); return -1; } + S1AP_FIND_PROTOCOLIE_BY_ID(S1AP_InitialContextSetupRequestIEs_t, ie, container, S1AP_ProtocolIE_ID_id_E_RABToBeSetupListCtxtSUReq, true); @@ -852,6 +941,7 @@ int s1ap_eNB_handle_initial_context_request(uint32_t assoc_id, item_p->e_RABlevelQoSParameters.allocationRetentionPriority.pre_emptionVulnerability; } /* for i... */ } else {/* ie != NULL */ + itti_free(ITTI_MSG_ORIGIN_ID(message_p), message_p); return -1; } @@ -865,6 +955,7 @@ int s1ap_eNB_handle_initial_context_request(uint32_t assoc_id, S1AP_INITIAL_CONTEXT_SETUP_REQ(message_p).security_capabilities.integrity_algorithms = BIT_STRING_to_uint16(&ie->value.choice.UESecurityCapabilities.integrityProtectionAlgorithms); } else {/* ie != NULL */ + itti_free(ITTI_MSG_ORIGIN_ID(message_p), message_p); return -1; } @@ -876,9 +967,10 @@ int s1ap_eNB_handle_initial_context_request(uint32_t assoc_id, memcpy(&S1AP_INITIAL_CONTEXT_SETUP_REQ(message_p).security_key, ie->value.choice.SecurityKey.buf, ie->value.choice.SecurityKey.size); } else {/* ie != NULL */ + itti_free(ITTI_MSG_ORIGIN_ID(message_p), message_p); return -1; } - + /* id-NRUESecurityCapabilities */ S1AP_FIND_PROTOCOLIE_BY_ID(S1AP_InitialContextSetupRequestIEs_t, ie, container, S1AP_ProtocolIE_ID_id_NRUESecurityCapabilities, false); @@ -891,7 +983,7 @@ int s1ap_eNB_handle_initial_context_request(uint32_t assoc_id, S1AP_INITIAL_CONTEXT_SETUP_REQ(message_p).nr_security_capabilities.encryption_algorithms = 0; S1AP_INITIAL_CONTEXT_SETUP_REQ(message_p).nr_security_capabilities.integrity_algorithms = 0; } - + itti_send_msg_to_task(TASK_RRC_ENB, ue_desc_p->eNB_instance->instance, message_p); return 0; @@ -918,6 +1010,13 @@ int s1ap_eNB_handle_ue_context_release_command(uint32_t assoc_id, return -1; } + S1AP_FIND_PROTOCOLIE_BY_ID(S1AP_UEContextReleaseCommand_IEs_t, ie, container, + S1AP_ProtocolIE_ID_id_Cause, true); + if( ie == NULL ) { + S1AP_ERROR( "Mandatory Element Nothing : UEContextReleaseCommand(Cause)\n" ); + return -1; + } + S1AP_FIND_PROTOCOLIE_BY_ID(S1AP_UEContextReleaseCommand_IEs_t, ie, container, S1AP_ProtocolIE_ID_id_UE_S1AP_IDs, true); @@ -965,9 +1064,26 @@ int s1ap_eNB_handle_ue_context_release_command(uint32_t assoc_id, //#warning "TODO mapping mme_ue_s1ap_id enb_ue_s1ap_id?" case S1AP_UE_S1AP_IDs_PR_mME_UE_S1AP_ID: - mme_ue_s1ap_id = ie->value.choice.UE_S1AP_IDs.choice.uE_S1AP_ID_pair.mME_UE_S1AP_ID; - S1AP_ERROR("TO DO mapping mme_ue_s1ap_id enb_ue_s1ap_id"); - (void)mme_ue_s1ap_id; /* TODO: remove - it's to remove gcc warning about unused var */ + mme_ue_s1ap_id = ie->value.choice.UE_S1AP_IDs.choice.mME_UE_S1AP_ID; + + RB_FOREACH(ue_desc_p, s1ap_ue_map, &mme_desc_p->s1ap_eNB_instance->s1ap_ue_head) + { + if( ue_desc_p->mme_ue_s1ap_id == mme_ue_s1ap_id ) + { + enb_ue_s1ap_id = ue_desc_p->eNB_ue_s1ap_id; + + message_p = itti_alloc_new_message(TASK_S1AP, 0, S1AP_UE_CONTEXT_RELEASE_COMMAND); + S1AP_UE_CONTEXT_RELEASE_COMMAND(message_p).eNB_ue_s1ap_id = enb_ue_s1ap_id; + itti_send_msg_to_task(TASK_RRC_ENB, ue_desc_p->eNB_instance->instance, message_p); + + return 0; + } + } + S1AP_ERROR("[SCTP %d] Received UE context release command(mME_UE_S1AP_ID) for non " + "existing UE context 0x%06lx\n", + assoc_id, + mme_ue_s1ap_id); + return -1; case S1AP_UE_S1AP_IDs_PR_NOTHING: default: @@ -975,12 +1091,10 @@ int s1ap_eNB_handle_ue_context_release_command(uint32_t assoc_id, return -1; } } else { + S1AP_ERROR( "Mandatory Element Nothing : UEContextReleaseCommand(UE_S1AP_IDs)\n" ); return -1; } - S1AP_FIND_PROTOCOLIE_BY_ID(S1AP_UEContextReleaseCommand_IEs_t, ie, container, - S1AP_ProtocolIE_ID_id_Cause, true); - /* TBD */ } static @@ -999,7 +1113,7 @@ int s1ap_eNB_handle_e_rab_setup_request(uint32_t assoc_id, container = &pdu->choice.initiatingMessage.value.choice.E_RABSetupRequest; if ((mme_desc_p = s1ap_eNB_get_MME(NULL, assoc_id, 0)) == NULL) { - S1AP_ERROR("[SCTP %d] Received initial context setup request for non " + S1AP_ERROR("[SCTP %d] Received E-RAB setup request for non " "existing MME context\n", assoc_id); return -1; } @@ -1026,7 +1140,7 @@ int s1ap_eNB_handle_e_rab_setup_request(uint32_t assoc_id, if ((ue_desc_p = s1ap_eNB_get_ue_context(mme_desc_p->s1ap_eNB_instance, enb_ue_s1ap_id)) == NULL) { - S1AP_ERROR("[SCTP %d] Received initial context setup request for non " + S1AP_ERROR("[SCTP %d] Received E-RAB setup request for non " "existing UE context 0x%06lx\n", assoc_id, enb_ue_s1ap_id); return -1; @@ -1099,6 +1213,7 @@ int s1ap_eNB_handle_e_rab_setup_request(uint32_t assoc_id, itti_send_msg_to_task(TASK_RRC_ENB, ue_desc_p->eNB_instance->instance, message_p); } else { + itti_free(ITTI_MSG_ORIGIN_ID(message_p), message_p); return -1; } @@ -1119,13 +1234,6 @@ int s1ap_eNB_handle_paging(uint32_t assoc_id, // received Paging Message from MME S1AP_DEBUG("[SCTP %d] Received Paging Message From MME\n",assoc_id); - /* Paging procedure -> stream != 0 */ - if (stream == 0) { - LOG_W(S1AP,"[SCTP %d] Received Paging procedure on stream (%d)\n", - assoc_id, stream); - return -1; - } - if ((mme_desc_p = s1ap_eNB_get_MME(NULL, assoc_id, 0)) == NULL) { S1AP_ERROR("[SCTP %d] Received Paging for non " "existing MME context\n", assoc_id); @@ -1153,6 +1261,7 @@ int s1ap_eNB_handle_paging(uint32_t assoc_id, S1AP_PAGING_IND(message_p).ue_paging_identity.choice.s_tmsi.mme_code = 0; S1AP_PAGING_IND(message_p).ue_paging_identity.choice.s_tmsi.m_tmsi = 0; } else { + itti_free(ITTI_MSG_ORIGIN_ID(message_p), message_p); return -1; } @@ -1180,6 +1289,7 @@ int s1ap_eNB_handle_paging(uint32_t assoc_id, if(i != ie->value.choice.UEPagingID.choice.iMSI.size - 1) { /* invalid paging_p->uePagingID.choise.iMSI.buffer */ S1AP_ERROR("[SCTP %d] Received Paging : uePagingID.choise.iMSI error(i %d 0x0F)\n", assoc_id,i); + itti_free(ITTI_MSG_ORIGIN_ID(message_p), message_p); return -1; } } else { @@ -1190,14 +1300,17 @@ int s1ap_eNB_handle_paging(uint32_t assoc_id, if (S1AP_PAGING_IND(message_p).ue_paging_identity.choice.imsi.length >= S1AP_IMSI_LENGTH) { /* invalid paging_p->uePagingID.choise.iMSI.size */ S1AP_ERROR("[SCTP %d] Received Paging : uePagingID.choise.iMSI.size(%d) is over IMSI length(%d)\n", assoc_id, S1AP_PAGING_IND(message_p).ue_paging_identity.choice.imsi.length, S1AP_IMSI_LENGTH); + itti_free(ITTI_MSG_ORIGIN_ID(message_p), message_p); return -1; } } else { /* of if (ie->value.choice.UEPagingID.present == S1AP_UEPagingID_PR_iMSI) */ /* invalid paging_p->uePagingID.present */ S1AP_ERROR("[SCTP %d] Received Paging : uePagingID.present(%d) is unknown\n", assoc_id, ie->value.choice.UEPagingID.present); + itti_free(ITTI_MSG_ORIGIN_ID(message_p), message_p); return -1; } } else { /* of ie != NULL */ + itti_free(ITTI_MSG_ORIGIN_ID(message_p), message_p); return -1; } @@ -1230,6 +1343,7 @@ int s1ap_eNB_handle_paging(uint32_t assoc_id, return -1; } } else { + itti_free(ITTI_MSG_ORIGIN_ID(message_p), message_p); return -1; } @@ -1257,6 +1371,7 @@ int s1ap_eNB_handle_paging(uint32_t assoc_id, S1AP_PAGING_IND(message_p).tac[i]); } } else { + itti_free(ITTI_MSG_ORIGIN_ID(message_p), message_p); return -1; } @@ -1351,6 +1466,7 @@ int s1ap_eNB_handle_e_rab_modify_request(uint32_t assoc_id, S1AP_E_RAB_MODIFY_RESP(message_p).e_rabs_failed[nb_of_e_rabs_failed].cause_value = S1AP_CauseRadioNetwork_unknown_mme_ue_s1ap_id; } } else { + itti_free(ITTI_MSG_ORIGIN_ID(message_p), message_p); return -1; } @@ -1403,6 +1519,7 @@ int s1ap_eNB_handle_e_rab_modify_request(uint32_t assoc_id, itti_send_msg_to_task(TASK_RRC_ENB, ue_desc_p->eNB_instance->instance, message_p); } else { /* of if (ie != NULL)*/ + itti_free(ITTI_MSG_ORIGIN_ID(message_p), message_p); return -1; } @@ -1476,6 +1593,24 @@ int s1ap_eNB_handle_e_rab_release_command(uint32_t assoc_id, message_p = itti_alloc_new_message(TASK_S1AP, 0, S1AP_E_RAB_RELEASE_COMMAND); S1AP_E_RAB_RELEASE_COMMAND(message_p).eNB_ue_s1ap_id = enb_ue_s1ap_id; S1AP_E_RAB_RELEASE_COMMAND(message_p).mme_ue_s1ap_id = mme_ue_s1ap_id; + /* id-E-RABToBeReleasedList */ + S1AP_FIND_PROTOCOLIE_BY_ID(S1AP_E_RABReleaseCommandIEs_t, ie, container, + S1AP_ProtocolIE_ID_id_E_RABToBeReleasedList, true); + + if (ie != NULL) { /* checked by macro but cppcheck doesn't see it */ + S1AP_E_RAB_RELEASE_COMMAND(message_p).nb_e_rabs_torelease = ie->value.choice.E_RABList.list.count; + + for (i = 0; i < ie->value.choice.E_RABList.list.count; i++) { + S1AP_E_RABItem_t *item_p; + item_p = &(((S1AP_E_RABItemIEs_t *)ie->value.choice.E_RABList.list.array[i])->value.choice.E_RABItem); + S1AP_E_RAB_RELEASE_COMMAND(message_p).e_rab_release_params[i].e_rab_id = item_p->e_RAB_ID; + S1AP_DEBUG("[SCTP] Received E-RAB release command for e-rab id %ld\n", item_p->e_RAB_ID); + } + } else { + itti_free(ITTI_MSG_ORIGIN_ID(message_p), message_p); + return -1; + } + /* id-NAS-PDU */ S1AP_FIND_PROTOCOLIE_BY_ID(S1AP_E_RABReleaseCommandIEs_t, ie, container, S1AP_ProtocolIE_ID_id_NAS_PDU, false); @@ -1491,24 +1626,6 @@ int s1ap_eNB_handle_e_rab_release_command(uint32_t assoc_id, S1AP_E_RAB_RELEASE_COMMAND(message_p).nas_pdu.length = 0; S1AP_E_RAB_RELEASE_COMMAND(message_p).nas_pdu.buffer = NULL; } - - /* id-E-RABToBeReleasedList */ - S1AP_FIND_PROTOCOLIE_BY_ID(S1AP_E_RABReleaseCommandIEs_t, ie, container, - S1AP_ProtocolIE_ID_id_E_RABToBeReleasedList, true); - - if (ie != NULL) { /* checked by macro but cppcheck doesn't see it */ - S1AP_E_RAB_RELEASE_COMMAND(message_p).nb_e_rabs_torelease = ie->value.choice.E_RABList.list.count; - - for (i = 0; i < ie->value.choice.E_RABList.list.count; i++) { - S1AP_E_RABItem_t *item_p; - item_p = &(((S1AP_E_RABItemIEs_t *)ie->value.choice.E_RABList.list.array[i])->value.choice.E_RABItem); - S1AP_E_RAB_RELEASE_COMMAND(message_p).e_rab_release_params[i].e_rab_id = item_p->e_RAB_ID; - S1AP_DEBUG("[SCTP] Received E-RAB release command for e-rab id %ld\n", item_p->e_RAB_ID); - } - } else { - return -1; - } - itti_send_msg_to_task(TASK_RRC_ENB, ue_desc_p->eNB_instance->instance, message_p); return 0; } @@ -1533,7 +1650,6 @@ int s1ap_eNB_handle_s1_path_switch_request_ack(uint32_t assoc_id, if (stream == 0) { S1AP_ERROR("[SCTP %d] Received s1 path switch request ack on stream (%d)\n", assoc_id, stream); - //return -1; } if ((mme_desc_p = s1ap_eNB_get_MME(NULL, assoc_id, 0)) == NULL) { @@ -1550,6 +1666,7 @@ int s1ap_eNB_handle_s1_path_switch_request_ack(uint32_t assoc_id, if (ie == NULL) { S1AP_ERROR("[SCTP %d] Received path switch request ack for non " "ie context is NULL\n", assoc_id); + itti_free(ITTI_MSG_ORIGIN_ID(message_p), message_p); return -1; } @@ -1572,6 +1689,7 @@ int s1ap_eNB_handle_s1_path_switch_request_ack(uint32_t assoc_id, if (ie == NULL) { S1AP_ERROR("[SCTP %d] Received path switch request ack for non " "ie context is NULL\n", assoc_id); + itti_free(ITTI_MSG_ORIGIN_ID(message_p), message_p); return -1; } @@ -1589,6 +1707,7 @@ int s1ap_eNB_handle_s1_path_switch_request_ack(uint32_t assoc_id, if (ie == NULL) { S1AP_ERROR("[SCTP %d] Received path switch request ack for non " "ie context is NULL\n", assoc_id); + itti_free(ITTI_MSG_ORIGIN_ID(message_p), message_p); return -1; } @@ -1602,14 +1721,10 @@ int s1ap_eNB_handle_s1_path_switch_request_ack(uint32_t assoc_id, S1AP_ProtocolIE_ID_id_uEaggregateMaximumBitrate, false); if (ie) { - OCTET_STRING_TO_INT32 ( - &ie->value.choice.UEAggregateMaximumBitrate.uEaggregateMaximumBitRateUL, - S1AP_PATH_SWITCH_REQ_ACK(message_p).ue_ambr.br_ul - ); - OCTET_STRING_TO_INT32 ( - &ie->value.choice.UEAggregateMaximumBitrate.uEaggregateMaximumBitRateDL, - S1AP_PATH_SWITCH_REQ_ACK(message_p).ue_ambr.br_dl - ); + asn_INTEGER2ulong(&ie->value.choice.UEAggregateMaximumBitrate.uEaggregateMaximumBitRateUL, + &S1AP_PATH_SWITCH_REQ_ACK(message_p).ue_ambr.br_ul); + asn_INTEGER2ulong(&ie->value.choice.UEAggregateMaximumBitrate.uEaggregateMaximumBitRateDL, + &S1AP_PATH_SWITCH_REQ_ACK(message_p).ue_ambr.br_dl); } else { S1AP_WARN("UEAggregateMaximumBitrate not supported\n"); S1AP_PATH_SWITCH_REQ_ACK(message_p).ue_ambr.br_ul = 0; @@ -1688,9 +1803,8 @@ int s1ap_eNB_handle_s1_path_switch_request_failure(uint32_t assoc_ pathSwitchRequestFailure = &pdu->choice.unsuccessfulOutcome.value.choice.PathSwitchRequestFailure; if (stream != 0) { - S1AP_ERROR("[SCTP %d] Received s1 path switch request failure on stream != 0 (%d)\n", + S1AP_WARN("[SCTP %d] Received s1 path switch request failure on stream != 0 (%d)\n", assoc_id, stream); - return -1; } if ((mme_desc_p = s1ap_eNB_get_MME(NULL, assoc_id, 0)) == NULL) { @@ -1754,3 +1868,144 @@ int s1ap_eNB_handle_s1_ENDC_e_rab_modification_confirm(uint32_t as return 0; } +//----------------------------------------------------------------------------- +/* +* eNB generate a S1 setup request towards MME +*/ +static int s1ap_eNB_snd_s1_setup_request( + s1ap_eNB_instance_t *instance_p, + s1ap_eNB_mme_data_t *s1ap_mme_data_p) +//----------------------------------------------------------------------------- +{ + S1AP_S1AP_PDU_t pdu; + S1AP_S1SetupRequest_t *out = NULL; + S1AP_S1SetupRequestIEs_t *ie = NULL; + S1AP_SupportedTAs_Item_t *ta = NULL; + S1AP_PLMNidentity_t *plmn = NULL; + uint8_t *buffer = NULL; + uint32_t len = 0; + int ret = 0; + uint32_t timer_kind = 0; + + DevAssert(instance_p != NULL); + DevAssert(s1ap_mme_data_p != NULL); + s1ap_mme_data_p->state = S1AP_ENB_STATE_WAITING; + /* Prepare the S1AP message to encode */ + memset(&pdu, 0, sizeof(pdu)); + pdu.present = S1AP_S1AP_PDU_PR_initiatingMessage; + pdu.choice.initiatingMessage.procedureCode = S1AP_ProcedureCode_id_S1Setup; + pdu.choice.initiatingMessage.criticality = S1AP_Criticality_reject; + pdu.choice.initiatingMessage.value.present = S1AP_InitiatingMessage__value_PR_S1SetupRequest; + out = &pdu.choice.initiatingMessage.value.choice.S1SetupRequest; + /* mandatory */ + ie = (S1AP_S1SetupRequestIEs_t *)calloc(1, sizeof(S1AP_S1SetupRequestIEs_t)); + ie->id = S1AP_ProtocolIE_ID_id_Global_ENB_ID; + ie->criticality = S1AP_Criticality_reject; + ie->value.present = S1AP_S1SetupRequestIEs__value_PR_Global_ENB_ID; + MCC_MNC_TO_PLMNID(instance_p->mcc[s1ap_mme_data_p->broadcast_plmn_index[0]], + instance_p->mnc[s1ap_mme_data_p->broadcast_plmn_index[0]], + instance_p->mnc_digit_length[s1ap_mme_data_p->broadcast_plmn_index[0]], + &ie->value.choice.Global_ENB_ID.pLMNidentity); + ie->value.choice.Global_ENB_ID.eNB_ID.present = S1AP_ENB_ID_PR_macroENB_ID; + MACRO_ENB_ID_TO_BIT_STRING(instance_p->eNB_id, + &ie->value.choice.Global_ENB_ID.eNB_ID.choice.macroENB_ID); + S1AP_INFO("%d -> %02x%02x%02x\n", instance_p->eNB_id, + ie->value.choice.Global_ENB_ID.eNB_ID.choice.macroENB_ID.buf[0], + ie->value.choice.Global_ENB_ID.eNB_ID.choice.macroENB_ID.buf[1], + ie->value.choice.Global_ENB_ID.eNB_ID.choice.macroENB_ID.buf[2]); + ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie); + + /* optional */ + if (instance_p->eNB_name) { + ie = (S1AP_S1SetupRequestIEs_t *)calloc(1, sizeof(S1AP_S1SetupRequestIEs_t)); + ie->id = S1AP_ProtocolIE_ID_id_eNBname; + ie->criticality = S1AP_Criticality_ignore; + ie->value.present = S1AP_S1SetupRequestIEs__value_PR_ENBname; + OCTET_STRING_fromBuf(&ie->value.choice.ENBname, instance_p->eNB_name, + strlen(instance_p->eNB_name)); + ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie); + } + + /* mandatory */ + ie = (S1AP_S1SetupRequestIEs_t *)calloc(1, sizeof(S1AP_S1SetupRequestIEs_t)); + ie->id = S1AP_ProtocolIE_ID_id_SupportedTAs; + ie->criticality = S1AP_Criticality_reject; + ie->value.present = S1AP_S1SetupRequestIEs__value_PR_SupportedTAs; + { + ta = (S1AP_SupportedTAs_Item_t *)calloc(1, sizeof(S1AP_SupportedTAs_Item_t)); + INT16_TO_OCTET_STRING(instance_p->tac, &ta->tAC); + { + for (int i = 0; i < s1ap_mme_data_p->broadcast_plmn_num; ++i) { + plmn = (S1AP_PLMNidentity_t *)calloc(1, sizeof(S1AP_PLMNidentity_t)); + MCC_MNC_TO_TBCD(instance_p->mcc[s1ap_mme_data_p->broadcast_plmn_index[i]], + instance_p->mnc[s1ap_mme_data_p->broadcast_plmn_index[i]], + instance_p->mnc_digit_length[s1ap_mme_data_p->broadcast_plmn_index[i]], + plmn); + ASN_SEQUENCE_ADD(&ta->broadcastPLMNs.list, plmn); + } + } + ASN_SEQUENCE_ADD(&ie->value.choice.SupportedTAs.list, ta); + } + ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie); + /* mandatory */ + ie = (S1AP_S1SetupRequestIEs_t *)calloc(1, sizeof(S1AP_S1SetupRequestIEs_t)); + ie->id = S1AP_ProtocolIE_ID_id_DefaultPagingDRX; + ie->criticality = S1AP_Criticality_ignore; + ie->value.present = S1AP_S1SetupRequestIEs__value_PR_PagingDRX; + ie->value.choice.PagingDRX = instance_p->default_drx; + ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie); + + /* optional */ + if (0) { + ie = (S1AP_S1SetupRequestIEs_t *)calloc(1, sizeof(S1AP_S1SetupRequestIEs_t)); + ie->id = S1AP_ProtocolIE_ID_id_CSG_IdList; + ie->criticality = S1AP_Criticality_reject; + ie->value.present = S1AP_S1SetupRequestIEs__value_PR_CSG_IdList; + // ie->value.choice.CSG_IdList = ; + ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie); + } + + /* optional */ +#if (S1AP_VERSION >= MAKE_VERSION(13, 0, 0)) + + if (0) { + ie = (S1AP_S1SetupRequestIEs_t *)calloc(1, sizeof(S1AP_S1SetupRequestIEs_t)); + ie->id = S1AP_ProtocolIE_ID_id_UE_RetentionInformation; + ie->criticality = S1AP_Criticality_ignore; + ie->value.present = S1AP_S1SetupRequestIEs__value_PR_UE_RetentionInformation; + // ie->value.choice.UE_RetentionInformation = ; + ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie); + } + + /* optional */ + if (0) { + ie = (S1AP_S1SetupRequestIEs_t *)calloc(1, sizeof(S1AP_S1SetupRequestIEs_t)); + ie->id = S1AP_ProtocolIE_ID_id_NB_IoT_DefaultPagingDRX; + ie->criticality = S1AP_Criticality_ignore; + ie->value.present = S1AP_S1SetupRequestIEs__value_PR_NB_IoT_DefaultPagingDRX; + // ie->value.choice.NB_IoT_DefaultPagingDRX = ; + ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie); + } + +#endif /* #if (S1AP_VERSION >= MAKE_VERSION(14, 0, 0)) */ + + if (s1ap_eNB_encode_pdu(&pdu, &buffer, &len) < 0) { + S1AP_ERROR("Failed to encode S1 setup request\n"); + return -1; + } + + timer_kind = s1ap_mme_data_p->cnx_id; + timer_kind = timer_kind | S1AP_MMEIND; + timer_kind = timer_kind | S1_SETRSP_WAIT; + + if( s1ap_timer_setup(instance_p->s1_setuprsp_wait_timer, 0, TASK_S1AP, instance_p->instance, timer_kind, S1AP_TIMER_ONE_SHOT, + NULL, &s1ap_mme_data_p->timer_id) < 0 ) + { + S1AP_ERROR("Timer Start NG(S1 Setup Response) : MME=%d\n",s1ap_mme_data_p->cnx_id); + } + s1ap_mme_data_p->s1_setupreq_cnt++; + + /* Non UE-Associated signalling -> stream = 0 */ + s1ap_eNB_itti_send_sctp_data_req(instance_p->instance, s1ap_mme_data_p->assoc_id, buffer, len, 0); + return ret; +} diff --git a/openair3/S1AP/s1ap_eNB_management_procedures.c b/openair3/S1AP/s1ap_eNB_management_procedures.c index fc7ae70e49..a870e975a2 100644 --- a/openair3/S1AP/s1ap_eNB_management_procedures.c +++ b/openair3/S1AP/s1ap_eNB_management_procedures.c @@ -95,23 +95,43 @@ struct s1ap_eNB_mme_data_s *s1ap_eNB_get_MME( { struct s1ap_eNB_mme_data_s temp; struct s1ap_eNB_mme_data_s *found; + struct s1ap_eNB_mme_data_s *mme_p; memset(&temp, 0, sizeof(struct s1ap_eNB_mme_data_s)); temp.assoc_id = assoc_id; temp.cnx_id = cnx_id; - if (instance_p == NULL) { - STAILQ_FOREACH(instance_p, &s1ap_eNB_internal_data.s1ap_eNB_instances_head, - s1ap_eNB_entries) { - found = RB_FIND(s1ap_mme_map, &instance_p->s1ap_mme_head, &temp); + if( cnx_id != 0 ) { + if (instance_p == NULL) { + STAILQ_FOREACH(instance_p, &s1ap_eNB_internal_data.s1ap_eNB_instances_head, + s1ap_eNB_entries) { + found = RB_FIND(s1ap_mme_map, &instance_p->s1ap_mme_head, &temp); - if (found != NULL) { - return found; + if (found != NULL) { + return found; + } } + } else { + return RB_FIND(s1ap_mme_map, &instance_p->s1ap_mme_head, &temp); } } else { - return RB_FIND(s1ap_mme_map, &instance_p->s1ap_mme_head, &temp); + if (instance_p == NULL) { + STAILQ_FOREACH(instance_p, &s1ap_eNB_internal_data.s1ap_eNB_instances_head, + s1ap_eNB_entries) { + RB_FOREACH(mme_p, s1ap_mme_map, &instance_p->s1ap_mme_head) { + if( mme_p->assoc_id == assoc_id ) { + return mme_p; + } + } + } + } else { + RB_FOREACH(mme_p, s1ap_mme_map, &instance_p->s1ap_mme_head) { + if( mme_p->assoc_id == assoc_id ) { + return mme_p; + } + } + } } return NULL; diff --git a/openair3/S1AP/s1ap_eNB_nas_procedures.c b/openair3/S1AP/s1ap_eNB_nas_procedures.c index 919989897a..b55bc06e11 100644 --- a/openair3/S1AP/s1ap_eNB_nas_procedures.c +++ b/openair3/S1AP/s1ap_eNB_nas_procedures.c @@ -138,8 +138,8 @@ int s1ap_eNB_handle_nas_first_req( * identity, selects the MME with the highest capacity. */ mme_desc_p = s1ap_eNB_nnsf_select_mme( - instance_p, - s1ap_nas_first_req_p->establishment_cause); + instance_p, + s1ap_nas_first_req_p->establishment_cause); if (mme_desc_p) { S1AP_INFO("[eNB %ld] Chose MME '%s' (assoc_id %d) through highest relative capacity\n", @@ -358,10 +358,18 @@ int s1ap_eNB_handle_nas_downlink(uint32_t assoc_id, container = &pdu->choice.initiatingMessage.value.choice.DownlinkNASTransport; S1AP_FIND_PROTOCOLIE_BY_ID(S1AP_DownlinkNASTransport_IEs_t, ie, container, S1AP_ProtocolIE_ID_id_MME_UE_S1AP_ID, true); + if(ie == NULL) + { + return -1; + } mme_ue_s1ap_id = ie->value.choice.MME_UE_S1AP_ID; S1AP_FIND_PROTOCOLIE_BY_ID(S1AP_DownlinkNASTransport_IEs_t, ie, container, S1AP_ProtocolIE_ID_id_eNB_UE_S1AP_ID, true); + if(ie == NULL) + { + return -1; + } enb_ue_s1ap_id = ie->value.choice.ENB_UE_S1AP_ID; if ((ue_desc_p = s1ap_eNB_get_ue_context(s1ap_eNB_instance, @@ -416,6 +424,10 @@ int s1ap_eNB_handle_nas_downlink(uint32_t assoc_id, S1AP_FIND_PROTOCOLIE_BY_ID(S1AP_DownlinkNASTransport_IEs_t, ie, container, S1AP_ProtocolIE_ID_id_NAS_PDU, true); + if(ie == NULL) + { + return -1; + } /* Forward the NAS PDU to RRC */ s1ap_eNB_itti_send_nas_downlink_ind(s1ap_eNB_instance->instance, ue_desc_p->ue_initial_id, @@ -494,9 +506,9 @@ int s1ap_eNB_nas_uplink(instance_t instance, s1ap_uplink_nas_t *s1ap_uplink_nas_ ie->criticality = S1AP_Criticality_ignore; ie->value.present = S1AP_UplinkNASTransport_IEs__value_PR_EUTRAN_CGI; MCC_MNC_TO_PLMNID( - s1ap_eNB_instance_p->mcc[ue_context_p->selected_plmn_identity], - s1ap_eNB_instance_p->mnc[ue_context_p->selected_plmn_identity], - s1ap_eNB_instance_p->mnc_digit_length[ue_context_p->selected_plmn_identity], + s1ap_eNB_instance_p->mcc[ue_context_p->mme_ref->broadcast_plmn_index[0]], + s1ap_eNB_instance_p->mnc[ue_context_p->mme_ref->broadcast_plmn_index[0]], + s1ap_eNB_instance_p->mnc_digit_length[ue_context_p->mme_ref->broadcast_plmn_index[0]], &ie->value.choice.EUTRAN_CGI.pLMNidentity); //#warning "TODO get cell id from RRC" MACRO_ENB_ID_TO_CELL_IDENTITY(s1ap_eNB_instance_p->eNB_id, diff --git a/openair3/S1AP/s1ap_eNB_nnsf.c b/openair3/S1AP/s1ap_eNB_nnsf.c index 6319f6e054..a5a4e74734 100644 --- a/openair3/S1AP/s1ap_eNB_nnsf.c +++ b/openair3/S1AP/s1ap_eNB_nnsf.c @@ -36,15 +36,29 @@ #include "s1ap_eNB_defs.h" #include "s1ap_eNB_nnsf.h" + +typedef struct MME_nnsf_inf { + struct s1ap_eNB_mme_data_s *mme_p; + uint64_t weight; +} MME_nnsf_inf_t; + struct s1ap_eNB_mme_data_s * s1ap_eNB_nnsf_select_mme(s1ap_eNB_instance_t *instance_p, rrc_establishment_cause_t cause) { struct s1ap_eNB_mme_data_s *mme_data_p = NULL; struct s1ap_eNB_mme_data_s *mme_highest_capacity_p = NULL; - uint8_t current_capacity = 0; - + + uint16_t capacity_sum = 0; + MME_nnsf_inf_t mme_inf[10]; + int cnt; + int nb_mme = 0; + uint64_t weight = 0; + + memset(mme_inf, 0, sizeof(mme_inf)); + RB_FOREACH(mme_data_p, s1ap_mme_map, &instance_p->s1ap_mme_head) { + capacity_sum = capacity_sum + mme_data_p->relative_mme_capacity; if (mme_data_p->state != S1AP_ENB_STATE_CONNECTED) { /* The association between MME and eNB is not ready for the moment, * go to the next known MME. @@ -69,7 +83,8 @@ s1ap_eNB_nnsf_select_mme(s1ap_eNB_instance_t *instance_p, || (cause == RRC_CAUSE_HIGH_PRIO_ACCESS))) { continue; } - + mme_inf[nb_mme].mme_p = mme_data_p; + nb_mme++; /* At this point, the RRC establishment can be handled by the MME * even if it is in overload state. */ @@ -78,14 +93,27 @@ s1ap_eNB_nnsf_select_mme(s1ap_eNB_instance_t *instance_p, continue; } } - - if (current_capacity < mme_data_p->relative_mme_capacity) { - /* We find a better MME, keep a reference to it */ - current_capacity = mme_data_p->relative_mme_capacity; - mme_highest_capacity_p = mme_data_p; - } } - + + if( nb_mme != 0 ) { + for( cnt = 0 ; cnt < nb_mme ; cnt++ ) { + mme_inf[cnt].weight = (capacity_sum*10)/mme_inf[cnt].mme_p->relative_mme_capacity; + mme_inf[cnt].weight = (mme_inf[cnt].weight)*(mme_inf[cnt].mme_p->nb_calls + 1); + } + mme_highest_capacity_p = mme_inf[0].mme_p; + weight = mme_inf[0].weight; + for( cnt = 1 ; cnt < nb_mme ; cnt++ ) { + if( weight > mme_inf[cnt].weight ) { + mme_highest_capacity_p = mme_inf[cnt].mme_p; + weight = mme_inf[cnt].weight; + } + } + } else { + mme_highest_capacity_p = NULL; + } + if( mme_highest_capacity_p != NULL ) { + mme_highest_capacity_p->nb_calls++; + } return mme_highest_capacity_p; } @@ -96,8 +124,15 @@ s1ap_eNB_nnsf_select_mme_by_plmn_id(s1ap_eNB_instance_t *instance_p, { struct s1ap_eNB_mme_data_s *mme_data_p = NULL; struct s1ap_eNB_mme_data_s *mme_highest_capacity_p = NULL; - uint8_t current_capacity = 0; - + + uint16_t capacity_sum = 0; + MME_nnsf_inf_t mme_inf[10]; + int cnt; + int nb_mme = 0; + uint64_t weight = 0; + + memset(mme_inf, 0, sizeof(mme_inf)); + RB_FOREACH(mme_data_p, s1ap_mme_map, &instance_p->s1ap_mme_head) { struct served_gummei_s *gummei_p = NULL; struct plmn_identity_s *served_plmn_p = NULL; @@ -140,6 +175,8 @@ s1ap_eNB_nnsf_select_mme_by_plmn_id(s1ap_eNB_instance_t *instance_p, STAILQ_FOREACH(served_plmn_p, &gummei_p->served_plmns, next) { if ((served_plmn_p->mcc == instance_p->mcc[selected_plmn_identity]) && (served_plmn_p->mnc == instance_p->mnc[selected_plmn_identity])) { + mme_inf[nb_mme].mme_p = mme_data_p; + nb_mme++; break; } } @@ -148,14 +185,27 @@ s1ap_eNB_nnsf_select_mme_by_plmn_id(s1ap_eNB_instance_t *instance_p, } /* if we didn't find such a served PLMN, go on with the next MME */ if (!served_plmn_p) continue; - - if (current_capacity < mme_data_p->relative_mme_capacity) { - /* We find a better MME, keep a reference to it */ - current_capacity = mme_data_p->relative_mme_capacity; - mme_highest_capacity_p = mme_data_p; - } } + if( nb_mme != 0 ) { + for( cnt = 0 ; cnt < nb_mme ; cnt++ ) { + mme_inf[cnt].weight = (capacity_sum*10)/mme_inf[cnt].mme_p->relative_mme_capacity; + mme_inf[cnt].weight = (mme_inf[cnt].weight)*(mme_inf[cnt].mme_p->nb_calls + 1); + } + mme_highest_capacity_p = mme_inf[0].mme_p; + weight = mme_inf[0].weight; + for( cnt = 1 ; cnt < nb_mme ; cnt++ ) { + if( weight > mme_inf[cnt].weight ) { + mme_highest_capacity_p = mme_inf[cnt].mme_p; + weight = mme_inf[cnt].weight; + } + } + } else { + mme_highest_capacity_p = NULL; + } + if( mme_highest_capacity_p != NULL ) { + mme_highest_capacity_p->nb_calls++; + } return mme_highest_capacity_p; } diff --git a/openair3/S1AP/s1ap_eNB_overload.c b/openair3/S1AP/s1ap_eNB_overload.c index 9358ae62bd..64d3fcdf65 100644 --- a/openair3/S1AP/s1ap_eNB_overload.c +++ b/openair3/S1AP/s1ap_eNB_overload.c @@ -62,8 +62,16 @@ int s1ap_eNB_handle_overload_start(uint32_t assoc_id, S1AP_OverloadResponse_PR_overloadAction, S1AP_OverloadResponse_PR_overloadAction, 0, 0); } + else + { + return -1; + } /* Non UE-associated signalling -> stream 0 */ - DevCheck(stream == 0, stream, 0, 0); + if (stream != 0) { + S1AP_ERROR("[SCTP %d] Received s1 overload start on stream != 0 (%d)\n", + assoc_id, stream); + return -1; + } if ((mme_desc_p = s1ap_eNB_get_MME(NULL, assoc_id, 0)) == NULL) { /* No MME context associated */ @@ -93,7 +101,11 @@ int s1ap_eNB_handle_overload_stop(uint32_t assoc_id, s1ap_eNB_mme_data_t *mme_desc_p; /* Non UE-associated signalling -> stream 0 */ - DevCheck(stream == 0, stream, 0, 0); + if (stream != 0) { + S1AP_ERROR("[SCTP %d] Received s1 overload stop on stream != 0 (%d)\n", + assoc_id, stream); + return -1; + } if ((mme_desc_p = s1ap_eNB_get_MME(NULL, assoc_id, 0)) == NULL) { /* No MME context associated */ diff --git a/openair3/S1AP/s1ap_eNB_trace.c b/openair3/S1AP/s1ap_eNB_trace.c index 19f5059238..695eeb4ef8 100644 --- a/openair3/S1AP/s1ap_eNB_trace.c +++ b/openair3/S1AP/s1ap_eNB_trace.c @@ -121,6 +121,10 @@ int s1ap_eNB_handle_trace_start(uint32_t assoc_id, if (ie != NULL) { ue_desc_p = s1ap_eNB_get_ue_context(mme_ref_p->s1ap_eNB_instance, ie->value.choice.ENB_UE_S1AP_ID); + } + else + { + return -1; } if (ue_desc_p == NULL) { /* Could not find context associated with this eNB_ue_s1ap_id -> generate diff --git a/openair3/SCTP/sctp_default_values.h b/openair3/SCTP/sctp_default_values.h index 528ffb5a05..0f8f94dca9 100644 --- a/openair3/SCTP/sctp_default_values.h +++ b/openair3/SCTP/sctp_default_values.h @@ -24,8 +24,8 @@ #define SCTP_OUT_STREAMS (16) #define SCTP_IN_STREAMS (16) -#define SCTP_MAX_ATTEMPTS (2) -#define SCTP_TIMEOUT (5) +#define SCTP_MAX_ATTEMPTS (8) +#define SCTP_TIMEOUT (60000) #define SCTP_RECV_BUFFER_SIZE (8192) #endif /* SCTP_DEFAULT_VALUES_H_ */ diff --git a/openair3/SCTP/sctp_eNB_task.c b/openair3/SCTP/sctp_eNB_task.c index 2f732443be..af49c5c350 100644 --- a/openair3/SCTP/sctp_eNB_task.c +++ b/openair3/SCTP/sctp_eNB_task.c @@ -270,7 +270,7 @@ sctp_handle_new_association_req_multi( sctp_new_association_req_p->remote_address.ipv6_address); //close(sd); //return; - exit(1); + exit_fun("sctp_handle_new_association_req_multi fatal: inet_pton error"); } SCTP_DEBUG("Converted ipv6 address %*s to network type\n", @@ -290,7 +290,7 @@ sctp_handle_new_association_req_multi( sctp_new_association_req_p->remote_address.ipv4_address); //close(sd); //return; - exit(1); + exit_fun("sctp_handle_new_association_req_multi fatal: inet_pton error"); } SCTP_DEBUG("Converted ipv4 address %*s to network type\n", @@ -329,7 +329,7 @@ sctp_handle_new_association_req_multi( if (ns == -1) { perror("sctp_peeloff"); printf("sctp_peeloff: sd=%d assoc_id=%d\n", sd, assoc_id); - exit(1); + exit_fun("sctp_handle_new_association_req_multi fatal: sctp_peeloff error"); } sctp_cnx = calloc(1, sizeof(*sctp_cnx)); @@ -943,10 +943,12 @@ sctp_eNB_read_from_socket( &sinfo, &flags); if (n < 0) { - if (errno == ENOTCONN) { + if( (errno == ENOTCONN) || (errno == ECONNRESET) || (errno == ETIMEDOUT) || (errno == ECONNREFUSED) ) + { itti_unsubscribe_event_fd(TASK_SCTP, sctp_cnx->sd); SCTP_DEBUG("Received not connected for sd %d\n", sctp_cnx->sd); + SCTP_ERROR("sctp_recvmsg (fd %d, len %d ): %s:%d\n", sctp_cnx->sd, n, strerror(errno), errno); sctp_itti_send_association_resp( sctp_cnx->task_id, sctp_cnx->instance, -1, @@ -969,7 +971,7 @@ sctp_eNB_read_from_socket( if (!(flags & MSG_EOR)) { SCTP_ERROR("fatal: partial SCTP messages are not handled\n"); - exit(1); + exit_fun("fatal: partial SCTP messages are not handled" ); } if (flags & MSG_NOTIFICATION) { diff --git a/targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp b/targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp index dd29d01fae..61a742af65 100644 --- a/targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp +++ b/targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp @@ -1110,7 +1110,7 @@ extern "C" { case 46080000: //openair0_cfg[0].samples_per_packet = 2048; - openair0_cfg[0].tx_sample_advance = 15; + openair0_cfg[0].tx_sample_advance = 65; openair0_cfg[0].tx_bw = 40e6; openair0_cfg[0].rx_bw = 40e6; break; @@ -1125,7 +1125,7 @@ extern "C" { case 15360000: //openair0_cfg[0].samples_per_packet = 2048; - openair0_cfg[0].tx_sample_advance = 45; + openair0_cfg[0].tx_sample_advance = 40; openair0_cfg[0].tx_bw = 10e6; openair0_cfg[0].rx_bw = 10e6; break; diff --git a/targets/ARCH/rfsimulator/stored_node.c b/targets/ARCH/rfsimulator/stored_node.c index daf0133af2..dcea69b9dd 100644 --- a/targets/ARCH/rfsimulator/stored_node.c +++ b/targets/ARCH/rfsimulator/stored_node.c @@ -200,7 +200,10 @@ int main(int argc, char *argv[]) { int bufSize=100000; void *buff=malloc(bufSize); uint64_t timestamp=0; - const int blockSize=1000; + const int blockSize=1920; + + // If fileSize is not multiple of blockSize*4 then discard remaining samples + fileSize = (fileSize/(blockSize<<2))*(blockSize<<2); while (1) { //Rewind the file to loop on the samples 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 9e13d493a8..32de0aa4f5 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 @@ -225,14 +225,15 @@ MACRLCs = ( num_cc = 1; tr_s_preference = "local_L1"; tr_n_preference = "local_RRC"; - } + } ); L1s = ( - { + { num_cc = 1; tr_n_preference = "local_mac"; - } + pusch_proc_threads = 8; + } ); RUs = ( @@ -246,8 +247,15 @@ RUs = ( max_pdschReferenceSignalPower = -27; max_rxgain = 75; eNB_instances = [0]; - #beamforming 1x4 matrix: - bf_weights = [0x00007fff, 0x0000, 0x0000, 0x0000]; + ##beamforming 1x2 matrix: 1 layer x 2 antennas + bf_weights = [0x00007fff, 0x0000]; + ##beamforming 1x4 matrix: 1 layer x 4 antennas + #bf_weights = [0x00007fff, 0x0000,0x0000, 0x0000]; + ## beamforming 2x2 matrix: + # bf_weights = [0x00007fff, 0x00000000, 0x00000000, 0x00007fff]; + ## beamforming 4x4 matrix: + #bf_weights = [0x00007fff, 0x0000, 0x0000, 0x0000, 0x00000000, 0x00007fff, 0x0000, 0x0000, 0x0000, 0x0000, 0x00007fff, 0x0000, 0x0000, 0x0000, 0x0000, 0x00007fff]; + sdr_addrs = "addr=192.168.10.2,mgmt_addr=192.168.10.2,second_addr=192.168.20.2"; clock_src = "external"; # if_freq = 3700000000L; 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 831f9c7978..307cf52cb3 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 @@ -225,14 +225,15 @@ MACRLCs = ( num_cc = 1; tr_s_preference = "local_L1"; tr_n_preference = "local_RRC"; - } + } ); L1s = ( - { + { num_cc = 1; tr_n_preference = "local_mac"; - } + pusch_proc_threads = 8; + } ); RUs = ( @@ -246,8 +247,15 @@ RUs = ( max_pdschReferenceSignalPower = -27; max_rxgain = 114; eNB_instances = [0]; - #beamforming 1x4 matrix: - bf_weights = [0x00007fff, 0x0000, 0x0000, 0x0000]; + ##beamforming 1x2 matrix: 1 layer x 2 antennas + bf_weights = [0x00007fff, 0x0000]; + ##beamforming 1x4 matrix: 1 layer x 4 antennas + #bf_weights = [0x00007fff, 0x0000,0x0000, 0x0000]; + ## beamforming 2x2 matrix: + # bf_weights = [0x00007fff, 0x00000000, 0x00000000, 0x00007fff]; + ## beamforming 4x4 matrix: + #bf_weights = [0x00007fff, 0x0000, 0x0000, 0x0000, 0x00000000, 0x00007fff, 0x0000, 0x0000, 0x0000, 0x0000, 0x00007fff, 0x0000, 0x0000, 0x0000, 0x0000, 0x00007fff]; + sdr_addrs = "type=x300"; clock_src = "external"; # if_freq = 3700000000L; 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 new file mode 100644 index 0000000000..deed91c93c --- /dev/null +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.106PRB.PTRS.usrpx300.conf @@ -0,0 +1,331 @@ +Active_gNBs = ( "gNB-Eurecom-5GNRBox"); +# Asn1_verbosity, choice in: none, info, annoying +Asn1_verbosity = "none"; + +gNBs = +( + { + ////////// Identification parameters: + gNB_ID = 0xe00; + + cell_type = "CELL_MACRO_GNB"; + + gNB_name = "gNB-Eurecom-5GNRBox"; + + // Tracking area code, 0x0000 and 0xfffe are reserved values + tracking_area_code = 1; + + plmn_list = ({mcc = 208; mnc = 93; mnc_length = 2;}); + + tr_s_preference = "local_mac" + + ////////// Physical parameters: + + ssb_SubcarrierOffset = 0; + pdsch_AntennaPorts = 1; + + servingCellConfigCommon = ( + { + #spCellConfigCommon + + physCellId = 0; + + # downlinkConfigCommon + # frequencyInfoDL + # this is 3600 MHz + 43 PRBs@30kHz SCS (same as initial BWP) + absoluteFrequencySSB = 641032; + dl_frequencyBand = 78; + # this is 3600 MHz + dl_absoluteFrequencyPointA = 640000; + #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=0,L=50 (275*(L-1))+RBstart + initialDLBWPlocationAndBandwidth = 6366; + # subcarrierSpacing + # 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + initialDLBWPsubcarrierSpacing = 1; + #pdcch-ConfigCommon + initialDLBWPcontrolResourceSetZero = 12; + initialDLBWPsearchSpaceZero = 0; + #pdsch-ConfigCommon + #pdschTimeDomainAllocationList (up to 16 entries) + initialDLBWPk0_0 = 0; + #initialULBWPmappingType + #0=typeA,1=typeB + initialDLBWPmappingType_0 = 0; + #this is SS=1,L=13 + initialDLBWPstartSymbolAndLength_0 = 40; + + initialDLBWPk0_1 = 0; + initialDLBWPmappingType_1 = 0; + #this is SS=2,L=12 + initialDLBWPstartSymbolAndLength_1 = 53; + + initialDLBWPk0_2 = 0; + initialDLBWPmappingType_2 = 0; + #this is SS=1,L=12 + initialDLBWPstartSymbolAndLength_2 = 54; + + initialDLBWPk0_3 = 0; + initialDLBWPmappingType_3 = 0; + #this is SS=1,L=4 + initialDLBWPstartSymbolAndLength_3 = 57; + + #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 = 6366; + # 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 = -118; + #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; + #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; + #oneHalf (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, + + # pusch-ConfigCommon (up to 16 elements) + initialULBWPk2_0 = 6; + initialULBWPmappingType_0 = 1 + # this is SS=0 L=11 + initialULBWPstartSymbolAndLength_0 = 55; + + initialULBWPk2_1 = 6; + initialULBWPmappingType_1 = 1; + # this is SS=0 L=12 + initialULBWPstartSymbolAndLength_1 = 69; + initialULBWPk2_2 = 7; + initialULBWPmappingType_2 = 1; + # this is SS=10 L=4 + initialULBWPstartSymbolAndLength_2 = 52; + + 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 = 10; + } + + ); + + # Dedicated Serving Cell Configuration + servingCellConfigDedicated = ( + { + # DL PTRS related parameters. + # 3GPP TS 38.331 PTRS-DownlinkConfig + + # frequencyDensity value range: 1-276 + dl_ptrsFreqDensity0_0 = 25; + dl_ptrsFreqDensity1_0 = 75; + + # timeDensity value range: 0-29 + dl_ptrsTimeDensity0_0 = 2; + dl_ptrsTimeDensity1_0 = 4; + dl_ptrsTimeDensity2_0 = 10; + + # epre_Ratio + # 0 = "00", 1 = "01" in TS 38.214, table 4.1-2 + dl_ptrsEpreRatio_0 = 0; + + # resourceElementOffset + # 0 = offset01 1 = offset02, 2 = offset02 + # 3GPP TS 38.331 PTRS-DownlinkConfig; TS 38.211 sec. 7.4.1.2.2 + dl_ptrsReOffset_0 = 0; + + # UL PTRS related parameters. + # 3GPP TS 38.331 PTRS-UplinkConfig + + # frequencyDensity value range: 1-276 + ul_ptrsFreqDensity0_0 = 25; + ul_ptrsFreqDensity1_0 = 75; + + # timeDensity value range: 0-29 + ul_ptrsTimeDensity0_0 = 2; + ul_ptrsTimeDensity1_0 = 4; + ul_ptrsTimeDensity2_0 = 10; + + # resourceElementOffset + # 0 = offset01 1 = offset02, 2 = offset02 + # TS 38.331 PTRS-UplinkConfig; TS 38.211 sec. 6.4.1.2.2.1 + ul_ptrsReOffset_0 = 0; + + # maxNrofPorts + # 0 = n1, 1 = n2 + ul_ptrsMaxPorts_0 = 0; + + # ptrs-Power + # 0 = p00, 1 = p01, 2 = p10, 3 = p11 + #ul_ptrsPower_0 = 0; + } + ); + + # ------- SCTP definitions + SCTP : + { + # Number of streams to use in input/output + SCTP_INSTREAMS = 2; + SCTP_OUTSTREAMS = 2; + }; + + + ////////// MME parameters: + mme_ip_address = ( { ipv4 = "192.168.12.26"; + ipv6 = "192:168:30::17"; + active = "yes"; + preference = "ipv4"; + } + ); + + NETWORK_INTERFACES : + { + + GNB_INTERFACE_NAME_FOR_S1_MME = "eth0"; + GNB_IPV4_ADDRESS_FOR_S1_MME = "192.168.12.111/24"; + GNB_INTERFACE_NAME_FOR_S1U = "eth0"; + GNB_IPV4_ADDRESS_FOR_S1U = "192.168.12.111/24"; + GNB_PORT_FOR_S1U = 2152; # Spec 2152 + }; + } +); + +MACRLCs = ( + { + num_cc = 1; + tr_s_preference = "local_L1"; + tr_n_preference = "local_RRC"; + } +); + +L1s = ( + { + num_cc = 1; + tr_n_preference = "local_mac"; + } +); + +RUs = ( + { + local_rf = "yes" + nb_tx = 1 + nb_rx = 1 + att_tx = 0 + att_rx = 0; + bands = [7]; + max_pdschReferenceSignalPower = -27; + max_rxgain = 114; + eNB_instances = [0]; + #beamforming 1x4 matrix: + bf_weights = [0x00007fff, 0x0000, 0x0000, 0x0000]; + sdr_addrs = "type=x300"; + clock_src = "external"; + } +); + +THREAD_STRUCT = ( + { + #three config for level of parallelism "PARALLEL_SINGLE_THREAD", "PARALLEL_RU_L1_SPLIT", or "PARALLEL_RU_L1_TRX_SPLIT" + parallel_config = "PARALLEL_RU_L1_TRX_SPLIT"; + #two option for worker "WORKER_DISABLE" or "WORKER_ENABLE" + worker_config = "WORKER_ENABLE"; + } +); + +log_config : +{ + global_log_level ="info"; + global_log_verbosity ="medium"; + hw_log_level ="info"; + hw_log_verbosity ="medium"; + phy_log_level ="info"; + phy_log_verbosity ="medium"; + mac_log_level ="info"; + mac_log_verbosity ="high"; + rlc_log_level ="info"; + rlc_log_verbosity ="medium"; + pdcp_log_level ="info"; + pdcp_log_verbosity ="medium"; + rrc_log_level ="info"; + rrc_log_verbosity ="medium"; +}; 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 760689f653..c77497dedd 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 @@ -226,15 +226,15 @@ MACRLCs = ( num_cc = 1; tr_s_preference = "local_L1"; tr_n_preference = "local_RRC"; - } + } ); L1s = ( - { + { num_cc = 1; tr_n_preference = "local_mac"; - pusch_proc_threads = 8; - } + pusch_proc_threads = 8; + } ); RUs = ( 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 d38fff4241..b3fdd79475 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 @@ -23,7 +23,7 @@ gNBs = ssb_SubcarrierOffset = 0; pdsch_AntennaPorts = 1; - + servingCellConfigCommon = ( { #spCellConfigCommon @@ -135,18 +135,17 @@ gNBs = initialULBWPmappingType_0 = 1 # this is SS=0 L=11 initialULBWPstartSymbolAndLength_0 = 55; - - initialULBWPk2_1 = 6; + + initialULBWPk2_1 = 6; initialULBWPmappingType_1 = 1; # this is SS=0 L=12 initialULBWPstartSymbolAndLength_1 = 69; - initialULBWPk2_2 = 7; + initialULBWPk2_2 = 7; initialULBWPmappingType_2 = 1; # this is SS=10 L=4 initialULBWPstartSymbolAndLength_2 = 52; - msg3_DeltaPreamble = 1; p0_NominalWithGrant =-90; @@ -227,14 +226,15 @@ MACRLCs = ( num_cc = 1; tr_s_preference = "local_L1"; tr_n_preference = "local_RRC"; - } + } ); L1s = ( - { + { num_cc = 1; tr_n_preference = "local_mac"; - } + pusch_proc_threads = 8; + } ); RUs = ( @@ -248,8 +248,15 @@ RUs = ( max_pdschReferenceSignalPower = -27; max_rxgain = 114; eNB_instances = [0]; - #beamforming 1x4 matrix: - bf_weights = [0x00007fff, 0x0000, 0x0000, 0x0000]; + ##beamforming 1x2 matrix: 1 layer x 2 antennas + bf_weights = [0x00007fff, 0x0000]; + ##beamforming 1x4 matrix: 1 layer x 4 antennas + #bf_weights = [0x00007fff, 0x0000,0x0000, 0x0000]; + ## beamforming 2x2 matrix: + # bf_weights = [0x00007fff, 0x00000000, 0x00000000, 0x00007fff]; + ## beamforming 4x4 matrix: + #bf_weights = [0x00007fff, 0x0000, 0x0000, 0x0000, 0x00000000, 0x00007fff, 0x0000, 0x0000, 0x0000, 0x0000, 0x00007fff, 0x0000, 0x0000, 0x0000, 0x0000, 0x00007fff]; + sdr_addrs = "type=x300"; clock_src = "external"; } 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 new file mode 100644 index 0000000000..9f69849ace --- /dev/null +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.24PRB.usrpb210.conf @@ -0,0 +1,292 @@ +Active_gNBs = ( "gNB-Eurecom-5GNRBox"); +# Asn1_verbosity, choice in: none, info, annoying +Asn1_verbosity = "none"; + +gNBs = +( + { + ////////// Identification parameters: + gNB_ID = 0xe00; + + cell_type = "CELL_MACRO_GNB"; + + gNB_name = "gNB-Eurecom-5GNRBox"; + + // Tracking area code, 0x0000 and 0xfffe are reserved values + tracking_area_code = 1; + + plmn_list = ({mcc = 208; mnc = 93; mnc_length = 2;}); + + tr_s_preference = "local_mac" + + ////////// Physical parameters: + + ssb_SubcarrierOffset = 0; + pdsch_AntennaPorts = 1; + + servingCellConfigCommon = ( + { + #spCellConfigCommon + + physCellId = 0; + +# downlinkConfigCommon + #frequencyInfoDL + # this is 3600 MHz + 43 PRBs@30kHz SCS (same as initial BWP) + absoluteFrequencySSB = 640288; + dl_frequencyBand = 78; + # this is 3600 MHz + dl_absoluteFrequencyPointA = 640000; + #scs-SpecificCarrierList + dl_offstToCarrier = 0; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + dl_subcarrierSpacing = 1; + dl_carrierBandwidth = 24; + #initialDownlinkBWP + #genericParameters + # this is RBstart=41,L=24 (275*(L-1))+RBstart + initialDLBWPlocationAndBandwidth = 6325; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + initialDLBWPsubcarrierSpacing = 1; + #pdcch-ConfigCommon + initialDLBWPcontrolResourceSetZero = 0; + initialDLBWPsearchSpaceZero = 0; + #pdsch-ConfigCommon + #pdschTimeDomainAllocationList (up to 16 entries) + initialDLBWPk0_0 = 0; + #initialULBWPmappingType + #0=typeA,1=typeB + initialDLBWPmappingType_0 = 0; + #this is SS=1,L=13 + initialDLBWPstartSymbolAndLength_0 = 40; + + initialDLBWPk0_1 = 0; + initialDLBWPmappingType_1 = 0; + #this is SS=2,L=12 + initialDLBWPstartSymbolAndLength_1 = 53; + + initialDLBWPk0_2 = 0; + initialDLBWPmappingType_2 = 0; + #this is SS=1,L=12 + initialDLBWPstartSymbolAndLength_2 = 54; + + initialDLBWPk0_3 = 0; + initialDLBWPmappingType_3 = 0; + #this is SS=1,L=5 + initialDLBWPstartSymbolAndLength_3 = 57; + + #uplinkConfigCommon + #frequencyInfoUL + ul_frequencyBand = 78; + #scs-SpecificCarrierList + ul_offstToCarrier = 0; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + ul_subcarrierSpacing = 1; + ul_carrierBandwidth = 24; + pMax = 20; + #initialUplinkBWP + #genericParameters + initialULBWPlocationAndBandwidth = 6325; +# 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 = -118; +#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; +#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; +#oneHalf (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, + + # pusch-ConfigCommon (up to 16 elements) + initialULBWPk2_0 = 6; + initialULBWPmappingType_0 = 1 + # this is SS=0 L=11 + initialULBWPstartSymbolAndLength_0 = 55; + + initialULBWPk2_1 = 6; + initialULBWPmappingType_1 = 1; + # this is SS=0 L=12 + initialULBWPstartSymbolAndLength_1 = 69; + + initialULBWPk2_2 = 7; + initialULBWPmappingType_2 = 1; + # this is SS=10 L=4 + initialULBWPstartSymbolAndLength_2 = 52; + + 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 = 10; + } + + ); + + + # ------- SCTP definitions + SCTP : + { + # Number of streams to use in input/output + SCTP_INSTREAMS = 2; + SCTP_OUTSTREAMS = 2; + }; + + + ////////// MME parameters: + mme_ip_address = ( { ipv4 = "192.168.12.26"; + ipv6 = "192:168:30::17"; + active = "yes"; + preference = "ipv4"; + } + ); + + NETWORK_INTERFACES : + { + + GNB_INTERFACE_NAME_FOR_S1_MME = "eth0"; + GNB_IPV4_ADDRESS_FOR_S1_MME = "192.168.12.111/24"; + GNB_INTERFACE_NAME_FOR_S1U = "eth0"; + GNB_IPV4_ADDRESS_FOR_S1U = "192.168.12.111/24"; + GNB_PORT_FOR_S1U = 2152; # Spec 2152 + }; + } +); + +MACRLCs = ( + { + num_cc = 1; + tr_s_preference = "local_L1"; + tr_n_preference = "local_RRC"; + } +); + +L1s = ( + { + num_cc = 1; + tr_n_preference = "local_mac"; + pusch_proc_threads = 8; + } +); + +RUs = ( + { + local_rf = "yes" + nb_tx = 1 + nb_rx = 1 + att_tx = 0 + att_rx = 0; + bands = [7]; + max_pdschReferenceSignalPower = -27; + max_rxgain = 75; + eNB_instances = [0]; + ## beamforming 1x2 matrix: 1 layer x 2 antennas + bf_weights = [0x00007fff, 0x0000]; + ## beamforming 1x4 matrix: 1 layer x 4 antennas + #bf_weights = [0x00007fff, 0x0000,0x0000, 0x0000]; + ## beamforming 2x2 matrix: + #bf_weights = [0x00007fff, 0x00000000, 0x00000000, 0x00007fff]; + ## beamforming 4x4 matrix: + #bf_weights = [0x00007fff, 0x0000, 0x0000, 0x0000, 0x00000000, 0x00007fff, 0x0000, 0x0000, 0x0000, 0x0000, 0x00007fff, 0x0000, 0x0000, 0x0000, 0x0000, 0x00007fff]; + sdr_addrs = "type=b200"; + #"addr=192.168.18.207"; + #"addr=192.168.10.2,mgmt_addr=192.168.10.2,second_addr=192.168.20.2"; + clock_src = "external"; + } +); + +THREAD_STRUCT = ( + { + #three config for level of parallelism "PARALLEL_SINGLE_THREAD", "PARALLEL_RU_L1_SPLIT", or "PARALLEL_RU_L1_TRX_SPLIT" + parallel_config = "PARALLEL_RU_L1_TRX_SPLIT"; + #two option for worker "WORKER_DISABLE" or "WORKER_ENABLE" + worker_config = "WORKER_ENABLE"; + } +); + + log_config : + { + global_log_level ="info"; + global_log_verbosity ="medium"; + hw_log_level ="info"; + hw_log_verbosity ="medium"; + phy_log_level ="info"; + phy_log_verbosity ="medium"; + mac_log_level ="info"; + mac_log_verbosity ="high"; + rlc_log_level ="info"; + rlc_log_verbosity ="medium"; + pdcp_log_level ="info"; + pdcp_log_verbosity ="medium"; + rrc_log_level ="info"; + rrc_log_verbosity ="medium"; + }; + 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 new file mode 100644 index 0000000000..56f07668d7 --- /dev/null +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.24PRB.usrpn300.conf @@ -0,0 +1,290 @@ +Active_gNBs = ( "gNB-Eurecom-5GNRBox"); +# Asn1_verbosity, choice in: none, info, annoying +Asn1_verbosity = "none"; + +gNBs = +( + { + ////////// Identification parameters: + gNB_ID = 0xe00; + + cell_type = "CELL_MACRO_GNB"; + + gNB_name = "gNB-Eurecom-5GNRBox"; + + // Tracking area code, 0x0000 and 0xfffe are reserved values + tracking_area_code = 1; + + plmn_list = ({mcc = 208; mnc = 93; mnc_length = 2;}); + + tr_s_preference = "local_mac" + + ////////// Physical parameters: + + ssb_SubcarrierOffset = 0; + pdsch_AntennaPorts = 1; + + servingCellConfigCommon = ( + { + #spCellConfigCommon + + physCellId = 0; + +# downlinkConfigCommon + #frequencyInfoDL + # this is 3600 MHz + 43 PRBs@30kHz SCS (same as initial BWP) + absoluteFrequencySSB = 640288; + dl_frequencyBand = 78; + # this is 3600 MHz + dl_absoluteFrequencyPointA = 640000; + #scs-SpecificCarrierList + dl_offstToCarrier = 0; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + dl_subcarrierSpacing = 1; + dl_carrierBandwidth = 24; + #initialDownlinkBWP + #genericParameters + # this is RBstart=41,L=24 (275*(L-1))+RBstart + initialDLBWPlocationAndBandwidth = 6325; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + initialDLBWPsubcarrierSpacing = 1; + #pdcch-ConfigCommon + initialDLBWPcontrolResourceSetZero = 0; + initialDLBWPsearchSpaceZero = 0; + #pdsch-ConfigCommon + #pdschTimeDomainAllocationList (up to 16 entries) + initialDLBWPk0_0 = 0; + #initialULBWPmappingType + #0=typeA,1=typeB + initialDLBWPmappingType_0 = 0; + #this is SS=1,L=13 + initialDLBWPstartSymbolAndLength_0 = 40; + + initialDLBWPk0_1 = 0; + initialDLBWPmappingType_1 = 0; + #this is SS=2,L=12 + initialDLBWPstartSymbolAndLength_1 = 53; + + initialDLBWPk0_2 = 0; + initialDLBWPmappingType_2 = 0; + #this is SS=1,L=12 + initialDLBWPstartSymbolAndLength_2 = 54; + + initialDLBWPk0_3 = 0; + initialDLBWPmappingType_3 = 0; + #this is SS=1,L=5 + initialDLBWPstartSymbolAndLength_3 = 57; + + #uplinkConfigCommon + #frequencyInfoUL + ul_frequencyBand = 78; + #scs-SpecificCarrierList + ul_offstToCarrier = 0; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + ul_subcarrierSpacing = 1; + ul_carrierBandwidth = 24; + pMax = 20; + #initialUplinkBWP + #genericParameters + initialULBWPlocationAndBandwidth = 6325; +# 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 = -118; +#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; +#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; +#oneHalf (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, + + # pusch-ConfigCommon (up to 16 elements) + initialULBWPk2_0 = 6; + initialULBWPmappingType_0 = 1 + # this is SS=0 L=11 + initialULBWPstartSymbolAndLength_0 = 55; + + initialULBWPk2_1 = 6; + initialULBWPmappingType_1 = 1; + # this is SS=0 L=12 + initialULBWPstartSymbolAndLength_1 = 69; + + initialULBWPk2_2 = 7; + initialULBWPmappingType_2 = 1; + # this is SS=10 L=4 + initialULBWPstartSymbolAndLength_2 = 52; + + 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 = 10; + } + + ); + + + # ------- SCTP definitions + SCTP : + { + # Number of streams to use in input/output + SCTP_INSTREAMS = 2; + SCTP_OUTSTREAMS = 2; + }; + + + ////////// MME parameters: + mme_ip_address = ( { ipv4 = "192.168.12.26"; + ipv6 = "192:168:30::17"; + active = "yes"; + preference = "ipv4"; + } + ); + + NETWORK_INTERFACES : + { + + GNB_INTERFACE_NAME_FOR_S1_MME = "eth0"; + GNB_IPV4_ADDRESS_FOR_S1_MME = "192.168.12.111/24"; + GNB_INTERFACE_NAME_FOR_S1U = "eth0"; + GNB_IPV4_ADDRESS_FOR_S1U = "192.168.12.111/24"; + GNB_PORT_FOR_S1U = 2152; # Spec 2152 + }; + } +); + +MACRLCs = ( + { + num_cc = 1; + tr_s_preference = "local_L1"; + tr_n_preference = "local_RRC"; + } +); + +L1s = ( + { + num_cc = 1; + tr_n_preference = "local_mac"; + pusch_proc_threads = 8; + } +); + +RUs = ( + { + local_rf = "yes" + nb_tx = 1 + nb_rx = 1 + att_tx = 0 + att_rx = 0; + bands = [7]; + max_pdschReferenceSignalPower = -27; + max_rxgain = 75; + eNB_instances = [0]; + ## beamforming 1x2 matrix: 1 layer x 2 antennas + bf_weights = [0x00007fff, 0x0000]; + ## beamforming 1x4 matrix: 1 layer x 4 antennas + #bf_weights = [0x00007fff, 0x0000,0x0000, 0x0000]; + ## beamforming 2x2 matrix: + #bf_weights = [0x00007fff, 0x00000000, 0x00000000, 0x00007fff]; + ## beamforming 4x4 matrix: + #bf_weights = [0x00007fff, 0x0000, 0x0000, 0x0000, 0x00000000, 0x00007fff, 0x0000, 0x0000, 0x0000, 0x0000, 0x00007fff, 0x0000, 0x0000, 0x0000, 0x0000, 0x00007fff]; + sdr_addrs = "addr=192.168.10.2,mgmt_addr=192.168.10.2,second_addr=192.168.20.2"; + clock_src = "external"; + } +); + +THREAD_STRUCT = ( + { + #three config for level of parallelism "PARALLEL_SINGLE_THREAD", "PARALLEL_RU_L1_SPLIT", or "PARALLEL_RU_L1_TRX_SPLIT" + parallel_config = "PARALLEL_RU_L1_TRX_SPLIT"; + #two option for worker "WORKER_DISABLE" or "WORKER_ENABLE" + worker_config = "WORKER_ENABLE"; + } +); + + log_config : + { + global_log_level ="info"; + global_log_verbosity ="medium"; + hw_log_level ="info"; + hw_log_verbosity ="medium"; + phy_log_level ="info"; + phy_log_verbosity ="medium"; + mac_log_level ="info"; + mac_log_verbosity ="high"; + rlc_log_level ="info"; + rlc_log_verbosity ="medium"; + pdcp_log_level ="info"; + pdcp_log_verbosity ="medium"; + rrc_log_level ="info"; + rrc_log_verbosity ="medium"; + }; + 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 new file mode 100644 index 0000000000..687a188456 --- /dev/null +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.24PRB.usrpx300.conf @@ -0,0 +1,290 @@ +Active_gNBs = ( "gNB-Eurecom-5GNRBox"); +# Asn1_verbosity, choice in: none, info, annoying +Asn1_verbosity = "none"; + +gNBs = +( + { + ////////// Identification parameters: + gNB_ID = 0xe00; + + cell_type = "CELL_MACRO_GNB"; + + gNB_name = "gNB-Eurecom-5GNRBox"; + + // Tracking area code, 0x0000 and 0xfffe are reserved values + tracking_area_code = 1; + + plmn_list = ({mcc = 208; mnc = 93; mnc_length = 2;}); + + tr_s_preference = "local_mac" + + ////////// Physical parameters: + + ssb_SubcarrierOffset = 0; + pdsch_AntennaPorts = 1; + + servingCellConfigCommon = ( + { + #spCellConfigCommon + + physCellId = 0; + +# downlinkConfigCommon + #frequencyInfoDL + # this is 3600 MHz + 43 PRBs@30kHz SCS (same as initial BWP) + absoluteFrequencySSB = 640288; + dl_frequencyBand = 78; + # this is 3600 MHz + dl_absoluteFrequencyPointA = 640000; + #scs-SpecificCarrierList + dl_offstToCarrier = 0; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + dl_subcarrierSpacing = 1; + dl_carrierBandwidth = 24; + #initialDownlinkBWP + #genericParameters + # this is RBstart=41,L=24 (275*(L-1))+RBstart + initialDLBWPlocationAndBandwidth = 6325; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + initialDLBWPsubcarrierSpacing = 1; + #pdcch-ConfigCommon + initialDLBWPcontrolResourceSetZero = 0; + initialDLBWPsearchSpaceZero = 0; + #pdsch-ConfigCommon + #pdschTimeDomainAllocationList (up to 16 entries) + initialDLBWPk0_0 = 0; + #initialULBWPmappingType + #0=typeA,1=typeB + initialDLBWPmappingType_0 = 0; + #this is SS=1,L=13 + initialDLBWPstartSymbolAndLength_0 = 40; + + initialDLBWPk0_1 = 0; + initialDLBWPmappingType_1 = 0; + #this is SS=2,L=12 + initialDLBWPstartSymbolAndLength_1 = 53; + + initialDLBWPk0_2 = 0; + initialDLBWPmappingType_2 = 0; + #this is SS=1,L=12 + initialDLBWPstartSymbolAndLength_2 = 54; + + initialDLBWPk0_3 = 0; + initialDLBWPmappingType_3 = 0; + #this is SS=1,L=5 + initialDLBWPstartSymbolAndLength_3 = 57; + + #uplinkConfigCommon + #frequencyInfoUL + ul_frequencyBand = 78; + #scs-SpecificCarrierList + ul_offstToCarrier = 0; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + ul_subcarrierSpacing = 1; + ul_carrierBandwidth = 24; + pMax = 20; + #initialUplinkBWP + #genericParameters + initialULBWPlocationAndBandwidth = 6325; +# 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 = -118; +#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; +#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; +#oneHalf (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, + + # pusch-ConfigCommon (up to 16 elements) + initialULBWPk2_0 = 6; + initialULBWPmappingType_0 = 1 + # this is SS=0 L=11 + initialULBWPstartSymbolAndLength_0 = 55; + + initialULBWPk2_1 = 6; + initialULBWPmappingType_1 = 1; + # this is SS=0 L=12 + initialULBWPstartSymbolAndLength_1 = 69; + + initialULBWPk2_2 = 7; + initialULBWPmappingType_2 = 1; + # this is SS=10 L=4 + initialULBWPstartSymbolAndLength_2 = 52; + + 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 = 10; + } + + ); + + + # ------- SCTP definitions + SCTP : + { + # Number of streams to use in input/output + SCTP_INSTREAMS = 2; + SCTP_OUTSTREAMS = 2; + }; + + + ////////// MME parameters: + mme_ip_address = ( { ipv4 = "192.168.12.26"; + ipv6 = "192:168:30::17"; + active = "yes"; + preference = "ipv4"; + } + ); + + NETWORK_INTERFACES : + { + + GNB_INTERFACE_NAME_FOR_S1_MME = "eth0"; + GNB_IPV4_ADDRESS_FOR_S1_MME = "192.168.12.111/24"; + GNB_INTERFACE_NAME_FOR_S1U = "eth0"; + GNB_IPV4_ADDRESS_FOR_S1U = "192.168.12.111/24"; + GNB_PORT_FOR_S1U = 2152; # Spec 2152 + }; + } +); + +MACRLCs = ( + { + num_cc = 1; + tr_s_preference = "local_L1"; + tr_n_preference = "local_RRC"; + } +); + +L1s = ( + { + num_cc = 1; + tr_n_preference = "local_mac"; + pusch_proc_threads = 8; + } +); + +RUs = ( + { + local_rf = "yes" + nb_tx = 1 + nb_rx = 1 + att_tx = 0 + att_rx = 0; + bands = [7]; + max_pdschReferenceSignalPower = -27; + max_rxgain = 114; + eNB_instances = [0]; + ## beamforming 1x2 matrix: 1 layer x 2 antennas + bf_weights = [0x00007fff, 0x0000]; + ## beamforming 1x4 matrix: 1 layer x 4 antennas + #bf_weights = [0x00007fff, 0x0000,0x0000, 0x0000]; + ## beamforming 2x2 matrix: + #bf_weights = [0x00007fff, 0x00000000, 0x00000000, 0x00007fff]; + ## beamforming 4x4 matrix: + #bf_weights = [0x00007fff, 0x0000, 0x0000, 0x0000, 0x00000000, 0x00007fff, 0x0000, 0x0000, 0x0000, 0x0000, 0x00007fff, 0x0000, 0x0000, 0x0000, 0x0000, 0x00007fff]; + sdr_addrs = "type=x300"; + clock_src = "external"; + } +); + +THREAD_STRUCT = ( + { + #three config for level of parallelism "PARALLEL_SINGLE_THREAD", "PARALLEL_RU_L1_SPLIT", or "PARALLEL_RU_L1_TRX_SPLIT" + parallel_config = "PARALLEL_RU_L1_TRX_SPLIT"; + #two option for worker "WORKER_DISABLE" or "WORKER_ENABLE" + worker_config = "WORKER_ENABLE"; + } +); + + log_config : + { + global_log_level ="info"; + global_log_verbosity ="medium"; + hw_log_level ="info"; + hw_log_verbosity ="medium"; + phy_log_level ="info"; + phy_log_verbosity ="medium"; + mac_log_level ="info"; + mac_log_verbosity ="high"; + rlc_log_level ="info"; + rlc_log_verbosity ="medium"; + pdcp_log_level ="info"; + pdcp_log_verbosity ="medium"; + rrc_log_level ="info"; + rrc_log_verbosity ="medium"; + }; + diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/testing_gnb_24PRB.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/testing_gnb_24PRB.conf new file mode 100644 index 0000000000..12e4525454 --- /dev/null +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/testing_gnb_24PRB.conf @@ -0,0 +1,306 @@ +Active_gNBs = ( "gNB-Eurecom-5GNRBox"); +# Asn1_verbosity, choice in: none, info, annoying +Asn1_verbosity = "none"; + +gNBs = +( + { + ////////// Identification parameters: + gNB_ID = 0xe00; + + cell_type = "CELL_MACRO_GNB"; + + gNB_name = "gNB-Eurecom-5GNRBox"; + + // Tracking area code, 0x0000 and 0xfffe are reserved values + tracking_area_code = 1; + + plmn_list = ({mcc = 222; mnc = 01; mnc_length = 2;}); + + tr_s_preference = "local_mac" + + ////////// Physical parameters: + + ssb_SubcarrierOffset = 31; //0; + pdsch_AntennaPorts = 1; + pusch_TargetSNRx10 = 200; + pucch_TargetSNRx10 = 200; + + servingCellConfigCommon = ( + { + #spCellConfigCommon + + physCellId = 0; + +# downlinkConfigCommon + #frequencyInfoDL + # this is 3600 MHz + 12 PRBs@30kHz SCS + absoluteFrequencySSB = 640288; + dl_frequencyBand = 78; + # this is 3600 MHz + dl_absoluteFrequencyPointA = 640000; + #scs-SpecificCarrierList + dl_offstToCarrier = 0; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + dl_subcarrierSpacing = 1; + dl_carrierBandwidth = 24; + #initialDownlinkBWP + #genericParameters + # this is RBstart=0,L=24 (275*(L-1))+RBstart + initialDLBWPlocationAndBandwidth = 6325; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + initialDLBWPsubcarrierSpacing = 1; + #pdcch-ConfigCommon + initialDLBWPcontrolResourceSetZero = 0; + initialDLBWPsearchSpaceZero = 0; + #pdsch-ConfigCommon + #pdschTimeDomainAllocationList (up to 16 entries) + initialDLBWPk0_0 = 0; + #initialULBWPmappingType + #0=typeA,1=typeB + initialDLBWPmappingType_0 = 0; + #this is SS=1,L=13 + initialDLBWPstartSymbolAndLength_0 = 40; + + initialDLBWPk0_1 = 0; + initialDLBWPmappingType_1 = 0; + #this is SS=2,L=12 + initialDLBWPstartSymbolAndLength_1 = 53; + + initialDLBWPk0_2 = 0; + initialDLBWPmappingType_2 = 0; + #this is SS=1,L=12 + initialDLBWPstartSymbolAndLength_2 = 54; + + initialDLBWPk0_3 = 0; + initialDLBWPmappingType_3 = 0; + #this is SS=1,L=4 //5 (4 is for 43, 5 is for 57) + initialDLBWPstartSymbolAndLength_3 = 57; //43; //57; + #uplinkConfigCommon + #frequencyInfoUL + ul_frequencyBand = 78; + #scs-SpecificCarrierList + ul_offstToCarrier = 0; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + ul_subcarrierSpacing = 1; + ul_carrierBandwidth = 24; + pMax = 20; + #initialUplinkBWP + #genericParameters + initialULBWPlocationAndBandwidth = 6325; +# 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 = -100; +#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; +#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; +#oneHalf (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 + 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, + # pusch-ConfigCommon (up to 16 elements) + initialULBWPk2_0 = 2; + initialULBWPmappingType_0 = 1 + # this is SS=0 L=12 + initialULBWPstartSymbolAndLength_0 = 55; + + initialULBWPk2_1 = 2; + initialULBWPmappingType_1 = 1; + # this is SS=0 L=11 + initialULBWPstartSymbolAndLength_1 = 69; + + initialULBWPk2_2 = 7; + initialULBWPmappingType_2 = 1; + # this is SS=10 L=4 + initialULBWPstartSymbolAndLength_2 = 52; + + 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; #0x80; + +# 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; //8; //7; + nrofDownlinkSymbols = 6; //0; //6; + nrofUplinkSlots = 2; + nrofUplinkSymbols = 4; //0; //4; + + ssPBCH_BlockPower = -25; + } + + ); + + + # ------- SCTP definitions + SCTP : + { + # Number of streams to use in input/output + SCTP_INSTREAMS = 2; + SCTP_OUTSTREAMS = 2; + }; + + + ////////// MME parameters: + mme_ip_address = ( { ipv4 = "192.168.18.99"; + ipv6 = "192:168:30::17"; + active = "yes"; + preference = "ipv4"; + } + ); + + ///X2 + enable_x2 = "yes"; + t_reloc_prep = 1000; /* unit: millisecond */ + tx2_reloc_overall = 2000; /* unit: millisecond */ + t_dc_prep = 1000; /* unit: millisecond */ + t_dc_overall = 2000; /* unit: millisecond */ + target_enb_x2_ip_address = ( + { ipv4 = "192.168.18.199"; + ipv6 = "192:168:30::17"; + preference = "ipv4"; + } + ); + + NETWORK_INTERFACES : + { + + GNB_INTERFACE_NAME_FOR_S1_MME = "eth0"; + GNB_IPV4_ADDRESS_FOR_S1_MME = "192.168.18.198/24"; + GNB_INTERFACE_NAME_FOR_S1U = "eth0"; + GNB_IPV4_ADDRESS_FOR_S1U = "192.168.18.198/24"; + GNB_PORT_FOR_S1U = 2152; # Spec 2152 + GNB_IPV4_ADDRESS_FOR_X2C = "192.168.18.198/24"; + GNB_PORT_FOR_X2C = 36422; # Spec 36422 + }; + } +); + +MACRLCs = ( + { + num_cc = 1; + tr_s_preference = "local_L1"; + tr_n_preference = "local_RRC"; + } +); + +L1s = ( + { + num_cc = 1; + tr_n_preference = "local_mac"; + pusch_proc_threads = 8; + } +); + +RUs = ( + { + local_rf = "yes" + nb_tx = 1 + nb_rx = 1 + att_tx = 0 + att_rx = 0; + bands = [7]; + max_pdschReferenceSignalPower = -27; + max_rxgain = 114; + eNB_instances = [0]; + ## beamforming 1x2 matrix: 1 layer x 2 antennas + bf_weights = [0x00007fff, 0x0000]; + ## beamforming 1x4 matrix: 1 layer x 4 antennas + #bf_weights = [0x00007fff, 0x0000,0x0000, 0x0000]; + ## beamforming 2x2 matrix: + #bf_weights = [0x00007fff, 0x00000000, 0x00000000, 0x00007fff]; + ## beamforming 4x4 matrix: + #bf_weights = [0x00007fff, 0x0000, 0x0000, 0x0000, 0x00000000, 0x00007fff, 0x0000, 0x0000, 0x0000, 0x0000, 0x00007fff, 0x0000, 0x0000, 0x0000, 0x0000, 0x00007fff]; + clock_src = "external"; + } +); + +THREAD_STRUCT = ( + { + #three config for level of parallelism "PARALLEL_SINGLE_THREAD", "PARALLEL_RU_L1_SPLIT", or "PARALLEL_RU_L1_TRX_SPLIT" + parallel_config = "PARALLEL_RU_L1_TRX_SPLIT"; + //parallel_config = "PARALLEL_SINGLE_THREAD"; + #two option for worker "WORKER_DISABLE" or "WORKER_ENABLE" + worker_config = "WORKER_ENABLE"; + } +); + + log_config : + { + global_log_level ="info"; + global_log_verbosity ="medium"; + hw_log_level ="info"; + hw_log_verbosity ="medium"; + phy_log_level ="info"; + phy_log_verbosity ="medium"; + mac_log_level ="info"; + mac_log_verbosity ="high"; + rlc_log_level ="info"; + rlc_log_verbosity ="medium"; + pdcp_log_level ="info"; + pdcp_log_verbosity ="medium"; + rrc_log_level ="info"; + rrc_log_verbosity ="medium"; + }; + 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 4373f38e7b..d28427dbf3 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 @@ -75,17 +75,12 @@ gNBs = initialDLBWPk0_2 = 0; initialDLBWPmappingType_2 = 0; #this is SS=1,L=12 - initialDLBWPstartSymbolAndLength_2 = 95; + initialDLBWPstartSymbolAndLength_2 = 54; initialDLBWPk0_3 = 0; initialDLBWPmappingType_3 = 0; - #this is SS=2,L=7 - initialDLBWPstartSymbolAndLength_3 = 86; - - initialDLBWPk0_4 = 0; - initialDLBWPmappingType_4 = 0; - #this is SS=2,L=5 - initialDLBWPstartSymbolAndLength_4 = 58; + #this is SS=1,L=5 + initialDLBWPstartSymbolAndLength_3 = 57; #uplinkConfigCommon #frequencyInfoUL From cd9a8f963f0c54857d980403ec7cce5989db9a06 Mon Sep 17 00:00:00 2001 From: francescomani Date: Tue, 18 May 2021 11:04:10 +0200 Subject: [PATCH 12/91] moving pucch functions for harq at MAC (version still to be tested) --- cmake_targets/CMakeLists.txt | 1 - executables/nr-ue.c | 3 +- .../nfapi/public_inc/fapi_nr_ue_interface.h | 113 +- openair1/PHY/INIT/nr_init_ue.c | 10 + openair1/PHY/NR_UE_TRANSPORT/dci_nr.c | 4 +- .../PHY/NR_UE_TRANSPORT/nr_dlsch_decoding.c | 16 +- openair1/PHY/NR_UE_TRANSPORT/nr_pbch.c | 2 +- .../PHY/NR_UE_TRANSPORT/nr_transport_ue.h | 30 +- openair1/PHY/NR_UE_TRANSPORT/pucch_nr.c | 173 +-- openair1/PHY/NR_UE_TRANSPORT/pucch_nr.h | 46 +- openair1/PHY/defs_nr_UE.h | 12 +- openair1/PHY/impl_defs_nr.h | 16 +- openair1/SCHED_NR_UE/defs.h | 1 + openair1/SCHED_NR_UE/fapi_nr_ue_l1.c | 63 +- openair1/SCHED_NR_UE/harq_nr.c | 191 --- openair1/SCHED_NR_UE/harq_nr.h | 32 - openair1/SCHED_NR_UE/phy_procedures_nr_ue.c | 79 +- .../SCHED_NR_UE/pucch_power_control_ue_nr.c | 218 ---- .../SCHED_NR_UE/pucch_power_control_ue_nr.h | 65 - openair1/SCHED_NR_UE/pucch_uci_ue_nr.c | 1153 +---------------- openair1/SCHED_NR_UE/pucch_uci_ue_nr.h | 45 +- openair1/SIMULATION/NR_PHY/dlsim.c | 6 +- .../SIMULATION/NR_PHY/nr_dummy_functions.c | 1 + openair1/SIMULATION/NR_PHY/pucchsim.c | 101 +- openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c | 77 ++ openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h | 9 + openair2/LAYER2/NR_MAC_UE/mac_defs.h | 34 +- openair2/LAYER2/NR_MAC_UE/mac_proto.h | 58 +- openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c | 975 +++++++++++++- openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c | 71 + .../NR_MAC_gNB/gNB_scheduler_primitives.c | 315 +++-- .../LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c | 77 +- openair2/LAYER2/NR_MAC_gNB/mac_proto.h | 9 - openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c | 14 +- 34 files changed, 1708 insertions(+), 2312 deletions(-) delete mode 100644 openair1/SCHED_NR_UE/pucch_power_control_ue_nr.c delete mode 100644 openair1/SCHED_NR_UE/pucch_power_control_ue_nr.h diff --git a/cmake_targets/CMakeLists.txt b/cmake_targets/CMakeLists.txt index 95af74d9de..69f3d6c271 100644 --- a/cmake_targets/CMakeLists.txt +++ b/cmake_targets/CMakeLists.txt @@ -1487,7 +1487,6 @@ set(SCHED_SRC_NR_UE ${OPENAIR1_DIR}/SCHED_NR_UE/phy_frame_config_nr_ue.c ${OPENAIR1_DIR}/SCHED_NR_UE/harq_nr.c ${OPENAIR1_DIR}/SCHED_NR_UE/pucch_uci_ue_nr.c - ${OPENAIR1_DIR}/SCHED_NR_UE/pucch_power_control_ue_nr.c ) add_library(SCHED_NR_UE_LIB ${SCHED_SRC_NR_UE}) diff --git a/executables/nr-ue.c b/executables/nr-ue.c index 51448a747f..3ffbc621bc 100644 --- a/executables/nr-ue.c +++ b/executables/nr-ue.c @@ -373,8 +373,7 @@ void processSlotRX(void *arg) { if (get_softmodem_params()->usim_test==0) { pucch_procedures_ue_nr(UE, gNB_id, - proc, - FALSE); + proc); } LOG_D(PHY, "Sending Uplink data \n"); 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 dd7cf21895..c48af917b1 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 @@ -101,6 +101,8 @@ typedef struct { typedef struct { + uint8_t harq_pid; + uint8_t ack_nack; uint32_t pdu_length; uint8_t* pdu; } fapi_nr_pdsch_pdu_t; @@ -188,87 +190,33 @@ typedef struct { } fapi_nr_ul_config_prach_pdu; typedef struct { - - pucch_format_nr_t format; /* format 0 1 2 3 4 */ - uint8_t initialCyclicShift; /* x x */ - uint8_t nrofSymbols; /* x x x x x */ - uint8_t startingSymbolIndex; /* x x x x x */ - uint8_t timeDomainOCC; /* x */ - uint8_t nrofPRBs; /* x x */ - uint16_t startingPRB; /* maxNrofPhysicalResourceBlocks = 275 */ - uint8_t occ_length; /* x */ - uint8_t occ_Index; /* x */ - - feature_status_t intraSlotFrequencyHopping; - uint16_t secondHopPRB; - - /* - -- Enabling inter-slot frequency hopping when PUCCH Format 1, 3 or 4 is repeated over multiple slots. - -- The field is not applicable for format 2. - */ - feature_status_t interslotFrequencyHopping; - /* - -- Enabling 2 DMRS symbols per hop of a PUCCH Format 3 or 4 if both hops are more than X symbols when FH is enabled (X=4). - -- Enabling 4 DMRS sybmols for a PUCCH Format 3 or 4 with more than 2X+1 symbols when FH is disabled (X=4). - -- Corresponds to L1 parameter 'PUCCH-F3-F4-additional-DMRS' (see 38.213, section 9.2.1) - -- The field is not applicable for format 1 and 2. - */ - enable_feature_t additionalDMRS; - /* - -- Max coding rate to determine how to feedback UCI on PUCCH for format 2, 3 or 4 - -- Corresponds to L1 parameter 'PUCCH-F2-maximum-coderate', 'PUCCH-F3-maximum-coderate' and 'PUCCH-F4-maximum-coderate' - -- (see 38.213, section 9.2.5) - -- The field is not applicable for format 1. - */ - PUCCH_MaxCodeRate_t maxCodeRate; - /* - -- Number of slots with the same PUCCH F1, F3 or F4. When the field is absent the UE applies the value n1. - -- Corresponds to L1 parameter 'PUCCH-F1-number-of-slots', 'PUCCH-F3-number-of-slots' and 'PUCCH-F4-number-of-slots' - -- (see 38.213, section 9.2.6) - -- The field is not applicable for format 2. - */ - uint8_t nrofSlots; - /* - -- Enabling pi/2 BPSK for UCI symbols instead of QPSK for PUCCH. - -- Corresponds to L1 parameter 'PUCCH-PF3-PF4-pi/2PBSK' (see 38.213, section 9.2.5) - -- The field is not applicable for format 1 and 2. - */ - feature_status_t pi2PBSK; - /* - -- Enabling simultaneous transmission of CSI and HARQ-ACK feedback with or without SR with PUCCH Format 2, 3 or 4 - -- Corresponds to L1 parameter 'PUCCH-F2-Simultaneous-HARQ-ACK-CSI', 'PUCCH-F3-Simultaneous-HARQ-ACK-CSI' and - -- 'PUCCH-F4-Simultaneous-HARQ-ACK-CSI' (see 38.213, section 9.2.5) - -- When the field is absent the UE applies the value OFF - -- The field is not applicable for format 1. - */ - enable_feature_t simultaneousHARQ_ACK_CSI; - /* - -- Configuration of group- and sequence hopping for all the PUCCH formats 0, 1, 3 and 4. "neither" implies neither group - -- or sequence hopping is enabled. "enable" enables group hopping and disables sequence hopping. "disable"” disables group - -- hopping and enables sequence hopping. Corresponds to L1 parameter 'PUCCH-GroupHopping' (see 38.211, section 6.4.1.3) - pucch-GroupHopping ENUMERATED { neither, enable, disable }, - */ - pucch_GroupHopping_t pucch_GroupHopping; - /* - -- Cell-Specific scrambling ID for group hoppping and sequence hopping if enabled. - -- Corresponds to L1 parameter 'HoppingID' (see 38.211, section 6.3.2.2) - hoppingId BIT STRING (SIZE (10)) OPTIONAL, -- Need R - */ - uint16_t hoppingId; - /* - -- Power control parameter P0 for PUCCH transmissions. Value in dBm. Only even values (step size 2) allowed. - -- Corresponds to L1 parameter 'p0-nominal-pucch' (see 38.213, section 7.2) - p0-nominal INTEGER (-202..24) OPTIONAL, -- Need R - */ - int8_t p0_nominal; - - int8_t deltaF_PUCCH_f[NUMBER_PUCCH_FORMAT_NR]; - uint8_t p0_PUCCH_Id; /* INTEGER (1..8) */ - int8_t p0_PUCCH_Value; - // pathlossReferenceRSs SEQUENCE (SIZE (1..maxNrofPUCCH-PathlossReferenceRSs)) OF PUCCH-PathlossReferenceRS OPTIONAL, -- Need M - int8_t twoPUCCH_PC_AdjustmentStates; - - } fapi_nr_ul_config_pucch_pdu; + uint16_t rnti; + uint16_t bwp_size; + uint16_t bwp_start; + uint8_t format_type; + uint8_t start_symbol_index; + uint8_t nr_of_symbols; + uint16_t prb_start; + uint16_t prb_size; + uint32_t hopping_id; + uint8_t freq_hop_flag; + uint8_t group_hop_flag; + uint8_t sequence_hop_flag; + uint16_t second_hop_prb; + uint16_t initial_cyclic_shift; + uint8_t time_domain_occ_idx; + uint8_t add_dmrs_flag; + uint16_t dmrs_scrambling_id; + uint16_t data_scrambling_id; + uint8_t dmrs_cyclic_shift; + uint8_t pi_2bpsk; + uint8_t mcs; + uint8_t pre_dft_occ_idx; + uint8_t pre_dft_occ_len; + int16_t pucch_tx_power; + uint32_t n_bit; + uint64_t payload; +} fapi_nr_ul_config_pucch_pdu; typedef struct { @@ -460,11 +408,8 @@ typedef struct { uint8_t tb2_rv; uint8_t harq_process_nbr; vrb_to_prb_mapping_t vrb_to_prb_mapping; - uint8_t dai; double scaling_factor_S; int8_t accumulated_delta_PUCCH; - uint8_t pucch_resource_id; - uint8_t pdsch_to_harq_feedback_time_ind; uint8_t n_dmrs_cdm_groups; uint8_t dmrs_ports[10]; uint8_t n_front_load_symb; diff --git a/openair1/PHY/INIT/nr_init_ue.c b/openair1/PHY/INIT/nr_init_ue.c index 855acc01ff..7288f063c2 100644 --- a/openair1/PHY/INIT/nr_init_ue.c +++ b/openair1/PHY/INIT/nr_init_ue.c @@ -182,6 +182,16 @@ int init_nr_ue_signal(PHY_VARS_NR_UE *ue, } } + /////////////////////////PUCCH init///////////////////////// + /////////// + for (th_id = 0; th_id < RX_NB_TH_MAX; th_id++) { + for (gNB_id = 0; gNB_id < ue->n_connected_gNB; gNB_id++) { + ue->pucch_vars[th_id][gNB_id] = (NR_UE_PUCCH *)malloc16(sizeof(NR_UE_PUCCH)); + for (i=0; i<2; i++) + ue->pucch_vars[th_id][gNB_id]->active[i] = false; + } + } + /////////// //////////////////////////////////////////////////////////////////////////////////////////// diff --git a/openair1/PHY/NR_UE_TRANSPORT/dci_nr.c b/openair1/PHY/NR_UE_TRANSPORT/dci_nr.c index 4cf25ac5a6..6937c23a6d 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/dci_nr.c +++ b/openair1/PHY/NR_UE_TRANSPORT/dci_nr.c @@ -955,7 +955,8 @@ uint8_t nr_dci_decoding_procedure(PHY_VARS_NR_UE *ue, currentPtrDCI); n_rnti = rel15->rnti; - LOG_D(PHY, "(%i.%i) dci indication (rnti %x,dci format %s,n_CCE %d,payloadSize %d)\n", proc->frame_rx, proc->nr_slot_rx,n_rnti,nr_dci_format_string[rel15->dci_format_options[k]],CCEind,dci_length); + LOG_D(PHY, "(%i.%i) dci indication (rnti %x,dci format %s,n_CCE %d,payloadSize %d)\n", + proc->frame_rx, proc->nr_slot_rx,n_rnti,nr_dci_format_string[rel15->dci_format_options[k]],CCEind,dci_length); if (crc == n_rnti) { LOG_D(PHY, "(%i.%i) Received dci indication (rnti %x,dci format %s,n_CCE %d,payloadSize %d,payload %llx)\n", proc->frame_rx, proc->nr_slot_rx,n_rnti,nr_dci_format_string[rel15->dci_format_options[k]],CCEind,dci_length,*(unsigned long long*)dci_estimation); @@ -970,6 +971,7 @@ uint8_t nr_dci_decoding_procedure(PHY_VARS_NR_UE *ue, dci_ind->slot = proc->nr_slot_rx; dci_ind->dci_list[dci_ind->number_of_dcis].rnti = n_rnti; dci_ind->dci_list[dci_ind->number_of_dcis].n_CCE = CCEind; + dci_ind->dci_list[dci_ind->number_of_dcis].N_CCE = L; dci_ind->dci_list[dci_ind->number_of_dcis].dci_format = rel15->dci_format_options[k]; dci_ind->dci_list[dci_ind->number_of_dcis].payloadSize = dci_length; memcpy((void*)dci_ind->dci_list[dci_ind->number_of_dcis].payloadBits,(void*)dci_estimation,8); diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_decoding.c b/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_decoding.c index b85b777566..0554ddcca0 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_decoding.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_decoding.c @@ -625,9 +625,7 @@ uint32_t nr_dlsch_decoding(PHY_VARS_NR_UE *phy_vars_ue, LOG_D(PHY,"[UE %d] DLSCH: Setting NAK for SFN/SF %d/%d (pid %d, status %d, round %d, TBS %d, mcs %d) Kr %d r %d harq_process->round %d\n", phy_vars_ue->Mod_id, frame, nr_slot_rx, harq_pid,harq_process->status, harq_process->round,harq_process->TBS,harq_process->mcs,Kr,r,harq_process->round); - harq_process->harq_ack.ack = 0; - harq_process->harq_ack.harq_id = harq_pid; - harq_process->harq_ack.send_harq_status = 1; + harq_process->ack = 0; harq_process->errors[harq_process->round]++; if (harq_process->round >= dlsch->Mlimit) { @@ -650,9 +648,7 @@ uint32_t nr_dlsch_decoding(PHY_VARS_NR_UE *phy_vars_ue, harq_process->status = SCH_IDLE; harq_process->round = 0; - harq_process->harq_ack.ack = 1; - harq_process->harq_ack.harq_id = harq_pid; - harq_process->harq_ack.send_harq_status = 1; + harq_process->ack = 1; //LOG_D(PHY,"[UE %d] DLSCH: Setting ACK for SFN/SF %d/%d (pid %d, status %d, round %d, TBS %d, mcs %d)\n", // phy_vars_ue->Mod_id, frame, subframe, harq_pid, harq_process->status, harq_process->round,harq_process->TBS,harq_process->mcs); @@ -1171,9 +1167,7 @@ uint32_t nr_dlsch_decoding_mthread(PHY_VARS_NR_UE *phy_vars_ue, if (LOG_DEBUGFLAG(DEBUG_DLSCH_DECOD)) LOG_I(PHY,"[UE %d] DLSCH: Setting NAK for SFN/SF %d/%d (pid %d, status %d, round %d, TBS %d, mcs %d) Kr %d r %d harq_process->round %d\n", phy_vars_ue->Mod_id, frame, nr_slot_rx, harq_pid,harq_process->status, harq_process->round,harq_process->TBS,harq_process->mcs,Kr,r,harq_process->round); - harq_process->harq_ack.ack = 0; - harq_process->harq_ack.harq_id = harq_pid; - harq_process->harq_ack.send_harq_status = 1; + harq_process->ack = 0; harq_process->errors[harq_process->round]++; harq_process->round++; @@ -1195,9 +1189,7 @@ uint32_t nr_dlsch_decoding_mthread(PHY_VARS_NR_UE *phy_vars_ue, harq_process->status = SCH_IDLE; harq_process->round = 0; - harq_process->harq_ack.ack = 1; - harq_process->harq_ack.harq_id = harq_pid; - harq_process->harq_ack.send_harq_status = 1; + harq_process->ack = 1; //LOG_I(PHY,"[UE %d] DLSCH: Setting ACK for SFN/SF %d/%d (pid %d, status %d, round %d, TBS %d, mcs %d)\n", // phy_vars_ue->Mod_id, frame, subframe, harq_pid, harq_process->status, harq_process->round,harq_process->TBS,harq_process->mcs); diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_pbch.c b/openair1/PHY/NR_UE_TRANSPORT/nr_pbch.c index f0e6e9984b..d5eab63546 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_pbch.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_pbch.c @@ -613,7 +613,7 @@ int nr_rx_pbch( PHY_VARS_NR_UE *ue, uint16_t number_pdus = 1; nr_fill_dl_indication(&dl_indication, NULL, &rx_ind, proc, ue, gNB_id); - nr_fill_rx_indication(&rx_ind, FAPI_NR_RX_PDU_TYPE_SSB, gNB_id, ue, NULL, number_pdus); + nr_fill_rx_indication(&rx_ind, FAPI_NR_RX_PDU_TYPE_SSB, gNB_id, ue, NULL, NULL, number_pdus); if (ue->if_inst && ue->if_inst->dl_indication) ue->if_inst->dl_indication(&dl_indication, NULL); diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_transport_ue.h b/openair1/PHY/NR_UE_TRANSPORT/nr_transport_ue.h index aa32ecc8c9..eaff6df0c9 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_transport_ue.h +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_transport_ue.h @@ -56,34 +56,6 @@ typedef enum { RETRANSMISSION_HARQ } harq_result_t; -//#if defined(UPGRADE_RAT_NR) -#if 1 -typedef struct { - /// HARQ process id - uint8_t harq_id; - /// HARQ rx status - harq_result_t rx_status; - /// ACK bits (after decoding) 0:NACK / 1:ACK / 2:DTX - uint8_t ack; - /// send status (for PUCCH) - uint8_t send_harq_status; - /// nCCE (for PUCCH) - uint8_t nCCE; - /// DAI value detected from DCI1/1a/1b/1d/2/2a/2b/2c. 0xff indicates not touched - uint8_t vDAI_DL; - /// DAI value detected from DCI0/4. 0xff indicates not touched - uint8_t vDAI_UL; - /// allow to define pucch parameters TS 38.213 9.2.3 UE procedure for reporting HARQ-ACK - uint8_t pucch_resource_indicator; - /// slot on which feedback ack should be send to network - uint16_t slot_for_feedback_ack; - /// index of a first CCE for the PDCCH reception - uint8_t n_CCE; - /// number of CCEs in a control resource set of a PDCCH reception conveying DCI format 1_0 - uint8_t N_CCE; -} NR_UE_HARQ_STATUS_t; -#endif - typedef struct { /// NDAPI struct for UE nfapi_nr_ue_pusch_pdu_t pusch_pdu; @@ -319,7 +291,7 @@ typedef struct { /// codeword this transport block is mapped to uint8_t codeword; /// HARQ-ACKs - NR_UE_HARQ_STATUS_t harq_ack; + uint8_t ack; /// PTRS Frequency Density uint8_t PTRSFreqDensity; /// PTRS Time Density diff --git a/openair1/PHY/NR_UE_TRANSPORT/pucch_nr.c b/openair1/PHY/NR_UE_TRANSPORT/pucch_nr.c index c7bf459f6f..a28ac1bcc2 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/pucch_nr.c +++ b/openair1/PHY/NR_UE_TRANSPORT/pucch_nr.c @@ -54,16 +54,10 @@ void nr_generate_pucch0(PHY_VARS_NR_UE *ue, int32_t **txdataF, NR_DL_FRAME_PARMS *frame_parms, - long pucch_GroupHopping, - long hoppingId, int16_t amp, int nr_slot_tx, - uint8_t m0, - uint8_t mcs, - uint8_t nrofSymbols, - uint8_t startingSymbolIndex, - uint16_t startingPRB, - uint16_t secondHopPRB) { + fapi_nr_ul_config_pucch_pdu *pucch_pdu) { + #ifdef DEBUG_NR_PUCCH_TX printf("\t [nr_generate_pucch0] start function at slot(nr_slot_tx)=%d\n",nr_slot_tx); #endif @@ -103,15 +97,22 @@ void nr_generate_pucch0(PHY_VARS_NR_UE *ue, // x_n contains the sequence r_u_v_alpha_delta(n) int16_t x_n_re[2][24],x_n_im[2][24]; + uint16_t startingPRB = pucch_pdu->prb_start + pucch_pdu->bwp_start; + pucch_GroupHopping_t pucch_GroupHopping = pucch_pdu->group_hop_flag + (pucch_pdu->sequence_hop_flag<<1); + // we proceed to calculate alpha according to TS 38.211 Subclause 6.3.2.2.2 int prb_offset[2]={startingPRB,startingPRB}; - nr_group_sequence_hopping(pucch_GroupHopping,hoppingId,0,nr_slot_tx,&u[0],&v[0]); // calculating u and v value - if (startingPRB!=secondHopPRB) { - nr_group_sequence_hopping(pucch_GroupHopping,hoppingId,1,nr_slot_tx,&u[1],&v[1]); // calculating u and v value - prb_offset[1] = secondHopPRB; + nr_group_sequence_hopping(pucch_GroupHopping,pucch_pdu->hopping_id,0,nr_slot_tx,&u[0],&v[0]); // calculating u and v value + if (pucch_pdu->freq_hop_flag == 1) { + nr_group_sequence_hopping(pucch_GroupHopping,pucch_pdu->hopping_id,1,nr_slot_tx,&u[1],&v[1]); // calculating u and v value + prb_offset[1] = pucch_pdu->second_hop_prb; } - for (int l=0; lnr_of_symbols; l++) { + alpha = nr_cyclic_shift_hopping(pucch_pdu->hopping_id, + pucch_pdu->initial_cyclic_shift, + pucch_pdu->mcs,l, + pucch_pdu->start_symbol_index, + nr_slot_tx); #ifdef DEBUG_NR_PUCCH_TX printf("\t [nr_generate_pucch0] sequence generation \tu=%d \tv=%d \talpha=%lf \t(for symbol l=%d)\n",u[l],v[l],alpha,l); #endif @@ -135,8 +136,8 @@ void nr_generate_pucch0(PHY_VARS_NR_UE *ue, uint32_t re_offset=0; uint8_t l2; - for (int l=0; lnr_of_symbols; l++) { + l2=l+pucch_pdu->start_symbol_index; re_offset = (12*prb_offset[l]) + frame_parms->first_carrier_offset; if (re_offset>= frame_parms->ofdm_symbol_size) re_offset-=frame_parms->ofdm_symbol_size; @@ -168,20 +169,20 @@ void nr_generate_pucch0(PHY_VARS_NR_UE *ue, void nr_generate_pucch1(PHY_VARS_NR_UE *ue, int32_t **txdataF, NR_DL_FRAME_PARMS *frame_parms, - PUCCH_CONFIG_DEDICATED *pucch_config_dedicated, - uint64_t payload, int16_t amp, int nr_slot_tx, - uint8_t m0, - uint8_t nrofSymbols, - uint8_t startingSymbolIndex, - uint16_t startingPRB, - uint16_t startingPRB_intraSlotHopping, - uint8_t timeDomainOCC, - uint8_t nr_bit) { + fapi_nr_ul_config_pucch_pdu *pucch_pdu) { + + uint16_t m0 = pucch_pdu->initial_cyclic_shift; + uint64_t payload = pucch_pdu->payload; + uint8_t startingSymbolIndex = pucch_pdu->start_symbol_index; + uint8_t nrofSymbols = pucch_pdu->nr_of_symbols; + uint16_t startingPRB = pucch_pdu->prb_start + pucch_pdu->bwp_start; + uint8_t timeDomainOCC = pucch_pdu->time_domain_occ_idx; + #ifdef DEBUG_NR_PUCCH_TX - printf("\t [nr_generate_pucch1] start function at slot(nr_slot_tx)=%d payload=%lu m0=%d nrofSymbols=%d startingSymbolIndex=%d startingPRB=%d startingPRB_intraSlotHopping=%d timeDomainOCC=%d nr_bit=%d\n", - nr_slot_tx,payload,m0,nrofSymbols,startingSymbolIndex,startingPRB,startingPRB_intraSlotHopping,timeDomainOCC,nr_bit); + printf("\t [nr_generate_pucch1] start function at slot(nr_slot_tx)=%d payload=%lu m0=%d nrofSymbols=%d startingSymbolIndex=%d startingPRB=%d second_hop_prb=%d timeDomainOCC=%d nr_bit=%d\n", + nr_slot_tx,payload,m0,nrofSymbols,startingSymbolIndex,startingPRB,pucch_pdu->second_hop_prb,timeDomainOCC,pucch_pdu->n_bit); #endif /* * Implement TS 38.211 Subclause 6.3.2.4.1 Sequence modulation @@ -190,12 +191,12 @@ void nr_generate_pucch1(PHY_VARS_NR_UE *ue, // complex-valued symbol d_re, d_im containing complex-valued symbol d(0): int16_t d_re=0, d_im=0; - if (nr_bit == 1) { // using BPSK if M_bit=1 according to TC 38.211 Subclause 5.1.2 + if (pucch_pdu->n_bit == 1) { // using BPSK if M_bit=1 according to TC 38.211 Subclause 5.1.2 d_re = (payload&1)==0 ? (int16_t)(((int32_t)amp*ONE_OVER_SQRT2)>>15) : -(int16_t)(((int32_t)amp*ONE_OVER_SQRT2)>>15); d_im = (payload&1)==0 ? (int16_t)(((int32_t)amp*ONE_OVER_SQRT2)>>15) : -(int16_t)(((int32_t)amp*ONE_OVER_SQRT2)>>15); } - if (nr_bit == 2) { // using QPSK if M_bit=2 according to TC 38.211 Subclause 5.1.2 + if (pucch_pdu->n_bit == 2) { // using QPSK if M_bit=2 according to TC 38.211 Subclause 5.1.2 if (((payload&1)==0) && (((payload>>1)&1)==0)) { d_re = (int16_t)(((int32_t)amp*ONE_OVER_SQRT2)>>15); // 32767/sqrt(2) = 23170 (ONE_OVER_SQRT2) d_im = (int16_t)(((int32_t)amp*ONE_OVER_SQRT2)>>15); @@ -256,7 +257,7 @@ void nr_generate_pucch1(PHY_VARS_NR_UE *ue, //uint8_t PUCCH_Frequency_Hopping = 0 ; // from higher layers uint8_t intraSlotFrequencyHopping = 0; - if (startingPRB != startingPRB_intraSlotHopping) { + if (pucch_pdu->freq_hop_flag) { intraSlotFrequencyHopping=1; } @@ -287,8 +288,9 @@ void nr_generate_pucch1(PHY_VARS_NR_UE *ue, printf("\t [nr_generate_pucch1] entering function nr_group_sequence_hopping with n_hop=%d, nr_slot_tx=%d\n", n_hop,nr_slot_tx); #endif - nr_group_sequence_hopping(ue->pucch_config_common_nr->pucch_GroupHopping,ue->pucch_config_common_nr->hoppingId,n_hop,nr_slot_tx,&u,&v); // calculating u and v value - alpha = nr_cyclic_shift_hopping(ue->pucch_config_common_nr->hoppingId,m0,mcs,l,lprime,nr_slot_tx); + pucch_GroupHopping_t pucch_GroupHopping = pucch_pdu->group_hop_flag + (pucch_pdu->sequence_hop_flag<<1); + nr_group_sequence_hopping(pucch_GroupHopping,pucch_pdu->hopping_id,n_hop,nr_slot_tx,&u,&v); // calculating u and v value + alpha = nr_cyclic_shift_hopping(pucch_pdu->hopping_id,m0,mcs,l,lprime,nr_slot_tx); for (int n=0; n<12; n++) { r_u_v_alpha_delta_re[n] = (int16_t)(((((int32_t)(round(32767*cos(alpha*n))) * table_5_2_2_2_2_Re[u][n])>>15) @@ -441,7 +443,7 @@ void nr_generate_pucch1(PHY_VARS_NR_UE *ue, } if ((intraSlotFrequencyHopping == 1) && (lsecond_hop_prb; } if ((startingPRB < (frame_parms->N_RB_DL>>1)) && ((frame_parms->N_RB_DL & 1) == 0)) { // if number RBs in bandwidth is even and current PRB is lower band @@ -848,7 +850,7 @@ inline void nr_pucch2_3_4_scrambling(uint16_t M_bit,uint16_t rnti,uint16_t n_id, } void nr_uci_encoding(uint64_t payload, uint8_t nr_bit, - pucch_format_nr_t fmt, + int fmt, uint8_t is_pi_over_2_bpsk_enabled, uint8_t nrofSymbols, uint8_t nrofPRB, @@ -868,9 +870,9 @@ void nr_uci_encoding(uint64_t payload, // 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 == pucch_format2_nr) E = 16*nrofSymbols*nrofPRB; + if (fmt == 2) E = 16*nrofSymbols*nrofPRB; - if (fmt == pucch_format3_nr) { + if (fmt == 3) { E_init = (is_pi_over_2_bpsk_enabled == 0) ? 24:12; if (nrofSymbols == 4) { @@ -895,7 +897,7 @@ void nr_uci_encoding(uint64_t payload, } } - if (fmt == pucch_format4_nr) { + if (fmt == 4) { E_init = (is_pi_over_2_bpsk_enabled == 0) ? 24:12; if (nrofSymbols == 4) { @@ -953,20 +955,11 @@ void nr_uci_encoding(uint64_t payload, } //#if 0 void nr_generate_pucch2(PHY_VARS_NR_UE *ue, - uint16_t crnti, - uint32_t dmrs_scrambling_id, - uint32_t data_scrambling_id, int32_t **txdataF, NR_DL_FRAME_PARMS *frame_parms, - PUCCH_CONFIG_DEDICATED *pucch_config_dedicated, - uint64_t payload, int16_t amp, int nr_slot_tx, - uint8_t nrofSymbols, - uint8_t startingSymbolIndex, - uint8_t nrofPRB, - uint16_t startingPRB, - uint8_t nr_bit) { + fapi_nr_ul_config_pucch_pdu *pucch_pdu) { #ifdef DEBUG_NR_PUCCH_TX printf("\t [nr_generate_pucch2] start function at slot(nr_slot_tx)=%d with payload=%lu and nr_bit=%d\n",nr_slot_tx, payload, nr_bit); #endif @@ -974,7 +967,12 @@ void nr_generate_pucch2(PHY_VARS_NR_UE *ue, uint64_t b[16]; // limit to 1024-bit encoded length // M_bit is the number of bits of block b (payload after encoding) uint16_t M_bit; - nr_uci_encoding(payload,nr_bit,pucch_format2_nr,0,nrofSymbols,nrofPRB,1,0,0,&b[0],&M_bit); + 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); /* * Implementing TS 38.211 * Subclauses 6.3.2.5.1 Scrambling (PUCCH format 2) @@ -989,14 +987,14 @@ void nr_generate_pucch2(PHY_VARS_NR_UE *ue, */ uint8_t *btilde = malloc(sizeof(int8_t)*M_bit); // rnti is given by the C-RNTI - uint16_t rnti=crnti; + uint16_t rnti=pucch_pdu->rnti; #ifdef DEBUG_NR_PUCCH_TX printf("\t [nr_generate_pucch2] rnti = %d ,\n",rnti); #endif /* * Implementing TS 38.211 Subclause 6.3.2.5.1 scrambling format 2 */ - nr_pucch2_3_4_scrambling(M_bit,rnti,data_scrambling_id,&b[0],btilde); + nr_pucch2_3_4_scrambling(M_bit,rnti,pucch_pdu->data_scrambling_id,&b[0],btilde); /* * Implementing TS 38.211 Subclause 6.3.2.5.2 modulation format 2 * btilde shall be modulated as described in subclause 5.1 using QPSK @@ -1042,9 +1040,12 @@ void nr_generate_pucch2(PHY_VARS_NR_UE *ue, uint32_t x1, x2, s=0; int i=0; int m=0; + uint8_t startingSymbolIndex = pucch_pdu->start_symbol_index; + uint16_t startingPRB = pucch_pdu->prb_start + pucch_pdu->bwp_start; - for (int l=0; lnr_of_symbols; l++) { + // c_init calculation according to TS38.211 subclause + x2 = (((1<<17)*((14*nr_slot_tx) + (l+startingSymbolIndex) + 1)*((2*pucch_pdu->dmrs_scrambling_id) + 1)) + (2*pucch_pdu->dmrs_scrambling_id))%(1U<<31); int reset = 1; for (int ii=0; ii<=(startingPRB>>2); ii++) { @@ -1052,7 +1053,7 @@ void nr_generate_pucch2(PHY_VARS_NR_UE *ue, reset = 0; } m = 0; - for (int rb=0; rbprb_size; rb++) { //startingPRB = startingPRB + rb; if (((rb+startingPRB) < (frame_parms->N_RB_DL>>1)) && ((frame_parms->N_RB_DL & 1) == 0)) { // if number RBs in bandwidth is even and current PRB is lower band re_offset = ((l+startingSymbolIndex)*frame_parms->ofdm_symbol_size) + (12*(rb+startingPRB)) + frame_parms->first_carrier_offset; @@ -1124,22 +1125,11 @@ void nr_generate_pucch2(PHY_VARS_NR_UE *ue, } //#if 0 void nr_generate_pucch3_4(PHY_VARS_NR_UE *ue, - uint16_t crnti, int32_t **txdataF, NR_DL_FRAME_PARMS *frame_parms, - pucch_format_nr_t fmt, - PUCCH_CONFIG_DEDICATED *pucch_config_dedicated, - uint64_t payload, int16_t amp, int nr_slot_tx, - uint8_t nrofSymbols, - uint8_t startingSymbolIndex, - uint8_t nrofPRB, - uint16_t startingPRB, - uint16_t startingPRB_intraSlotHopping, - uint8_t nr_bit, - uint8_t occ_length_format4, - uint8_t occ_index_format4) { + fapi_nr_ul_config_pucch_pdu *pucch_pdu) { #ifdef DEBUG_NR_PUCCH_TX printf("\t [nr_generate_pucch3_4] start function at slot(nr_slot_tx)=%d with payload=%lu and nr_bit=%d\n", nr_slot_tx, payload, nr_bit); #endif @@ -1148,28 +1138,40 @@ void nr_generate_pucch3_4(PHY_VARS_NR_UE *ue, // M_bit is the number of bits of block b (payload after encoding) uint16_t M_bit; // parameter PUCCH-F4-preDFT-OCC-length set of {2,4} -> to use table -1 or -2 - uint8_t n_SF_PUCCH_s = 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), FIXME!!! - uint8_t is_pi_over_2_bpsk_enabled = 0; // this value has to be provided by higher layers parameter + // 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; + if (pucch_pdu->format_type == 3) + n_SF_PUCCH_s = 1; + else + n_SF_PUCCH_s = pucch_pdu->pre_dft_occ_len; + uint8_t is_pi_over_2_bpsk_enabled = pucch_pdu->pi_2bpsk; // Intra-slot frequency hopping shall be assumed when the higher-layer parameter intraSlotFrequencyHopping is provided, // regardless of whether the frequency-hop distance is zero or not, // otherwise no intra-slot frequency hopping shall be assumed //uint8_t PUCCH_Frequency_Hopping = 0 ; // from higher layers uint8_t intraSlotFrequencyHopping = 0; - if (startingPRB != startingPRB_intraSlotHopping) { + if (pucch_pdu->freq_hop_flag) { intraSlotFrequencyHopping=1; #ifdef DEBUG_NR_PUCCH_TX printf("\t [nr_generate_pucch3_4] intraSlotFrequencyHopping=%d \n",intraSlotFrequencyHopping); #endif } - // add_dmrs indicates if we are using or not Additional DM-RS for formats 3 and 4. From higher layers. FIXME!!! - uint8_t add_dmrs = 0; + uint8_t nrofSymbols = pucch_pdu->nr_of_symbols; + uint16_t nrofPRB = pucch_pdu->prb_size; + uint16_t startingPRB = pucch_pdu->prb_start + pucch_pdu->bwp_start; + uint8_t add_dmrs = pucch_pdu->add_dmrs_flag; - //nrofPRB = 2; // only for test purposes - if (fmt == pucch_format4_nr) nrofPRB = 1; - - nr_uci_encoding(payload,nr_bit,fmt,is_pi_over_2_bpsk_enabled,nrofSymbols,nrofPRB,n_SF_PUCCH_s,intraSlotFrequencyHopping,add_dmrs,&b[0],&M_bit); + 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[0],&M_bit); /* * Implementing TS 38.211 * Subclauses 6.3.2.6.1 Scrambling (PUCCH formats 3 and 4) @@ -1184,7 +1186,7 @@ void nr_generate_pucch3_4(PHY_VARS_NR_UE *ue, */ uint8_t *btilde = malloc(sizeof(int8_t)*M_bit); // rnti is given by the C-RNTI - uint16_t rnti=crnti, n_id=0; + uint16_t rnti=pucch_pdu->rnti, n_id=0; #ifdef DEBUG_NR_PUCCH_TX printf("\t [nr_generate_pucch3_4] rnti = %d ,\n",rnti); #endif @@ -1300,12 +1302,11 @@ void nr_generate_pucch3_4(PHY_VARS_NR_UE *ue, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 1, 1, 1, 0, 0, 0,-1,-1,-1} }; - //uint8_t occ_Length = occ_length_format4; // higher layer parameter occ-Length - uint8_t occ_Index = occ_index_format4; // higher layer parameter occ-Index + + uint8_t occ_Index = pucch_pdu->pre_dft_occ_idx; // higher layer parameter occ-Index //occ_Index = 1; //only for testing purposes; to be removed FIXME!!! - if (fmt == pucch_format3_nr) { // no block-wise spreading for format 3 - n_SF_PUCCH_s = 1; + if (pucch_pdu->format_type == 3) { // no block-wise spreading for format 3 for (int l=0; l < floor(m_symbol/(12*nrofPRB)); l++) { for (int k=0; k < (12*nrofPRB); k++) { @@ -1319,7 +1320,7 @@ void nr_generate_pucch3_4(PHY_VARS_NR_UE *ue, } } - if (fmt == pucch_format4_nr) { + if (pucch_pdu->format_type == 4) { nrofPRB = 1; for (int l=0; l < floor((n_SF_PUCCH_s*m_symbol)/(12*nrofPRB)); l++) { @@ -1414,9 +1415,9 @@ void nr_generate_pucch3_4(PHY_VARS_NR_UE *ue, uint8_t m0; uint8_t mcs=0; - if (fmt == pucch_format3_nr) m0 = 0; + if (pucch_pdu->format_type == 3) m0 = 0; - if (fmt == pucch_format4_nr) { + if (pucch_pdu->format_type == 4) { if (n_SF_PUCCH_s == 2) { m0 = (occ_Index == 0) ? 0 : 6; } @@ -1456,7 +1457,8 @@ void nr_generate_pucch3_4(PHY_VARS_NR_UE *ue, for (int l=0; l= (int)floor(nrofSymbols/2))) n_hop = 1; // n_hop = 1 for second hop - nr_group_sequence_hopping(ue->pucch_config_common_nr->pucch_GroupHopping,ue->pucch_config_common_nr->hoppingId,n_hop,nr_slot_tx,&u,&v); // calculating u and v value + pucch_GroupHopping_t pucch_GroupHopping = pucch_pdu->group_hop_flag + (pucch_pdu->sequence_hop_flag<<1); + nr_group_sequence_hopping(pucch_GroupHopping,pucch_pdu->hopping_id,n_hop,nr_slot_tx,&u,&v); // calculating u and v value // Next we proceed to calculate base sequence for DM-RS signal, according to TS 38.211 subclause 6.4.1.33 if (nrofPRB >= 3) { // TS 38.211 subclause 5.2.2.1 (Base sequences of length 36 or larger) applies @@ -1501,12 +1503,13 @@ void nr_generate_pucch3_4(PHY_VARS_NR_UE *ue, } } + uint8_t startingSymbolIndex = pucch_pdu->start_symbol_index; uint16_t j=0; - alpha = nr_cyclic_shift_hopping(ue->pucch_config_common_nr->hoppingId,m0,mcs,l,startingSymbolIndex,nr_slot_tx); + alpha = nr_cyclic_shift_hopping(pucch_pdu->hopping_id,m0,mcs,l,startingSymbolIndex,nr_slot_tx); for (int rb=0; rbsecond_hop_prb; } //startingPRB = startingPRB + rb; diff --git a/openair1/PHY/NR_UE_TRANSPORT/pucch_nr.h b/openair1/PHY/NR_UE_TRANSPORT/pucch_nr.h index cb4b59c92f..dcf7fb4a37 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/pucch_nr.h +++ b/openair1/PHY/NR_UE_TRANSPORT/pucch_nr.h @@ -49,62 +49,30 @@ void nr_generate_pucch0(PHY_VARS_NR_UE *ue, int32_t **txdataF, NR_DL_FRAME_PARMS *frame_parms, - long pucch_GroupHopping, - long hoppingId, int16_t amp, int nr_slot_tx, - uint8_t m0, - uint8_t mcs, - uint8_t nrofSymbols, - uint8_t startingSymbolIndex, - uint16_t startingPRB, - uint16_t secondHopPRB); + fapi_nr_ul_config_pucch_pdu *pucch_pdu); + void nr_generate_pucch1(PHY_VARS_NR_UE *ue, int32_t **txdataF, NR_DL_FRAME_PARMS *frame_parms, - PUCCH_CONFIG_DEDICATED *pucch_config_dedicated, - uint64_t payload, int16_t amp, int nr_slot_tx, - uint8_t m0, - uint8_t nrofSymbols, - uint8_t startingSymbolIndex, - uint16_t startingPRB, - uint16_t startingPRB_intraSlotHopping, - uint8_t timeDomainOCC, - uint8_t nr_bit); + fapi_nr_ul_config_pucch_pdu *pucch_pdu); + void nr_generate_pucch2(PHY_VARS_NR_UE *ue, - uint16_t crnti, - uint32_t dmrs_scrambling_id, - uint32_t data_scrambling_id, int32_t **txdataF, NR_DL_FRAME_PARMS *frame_parms, - PUCCH_CONFIG_DEDICATED *pucch_config_dedicated, - uint64_t payload, int16_t amp, int nr_slot_tx, - uint8_t nrofSymbols, - uint8_t startingSymbolIndex, - uint8_t nrofPRB, - uint16_t startingPRB, - uint8_t nr_bit); + fapi_nr_ul_config_pucch_pdu *pucch_pdu); + void nr_generate_pucch3_4(PHY_VARS_NR_UE *ue, - uint16_t crnti, int32_t **txdataF, NR_DL_FRAME_PARMS *frame_parms, - pucch_format_nr_t fmt, - PUCCH_CONFIG_DEDICATED *pucch_config_dedicated, - uint64_t payload, int16_t amp, int nr_slot_tx, - uint8_t nrofSymbols, - uint8_t startingSymbolIndex, - uint8_t nrofPRB, - uint16_t startingPRB, - uint16_t startingPRB_intraSlotHopping, - uint8_t nr_bit, - uint8_t occ_length_format4, - uint8_t occ_index_format4); + 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}; diff --git a/openair1/PHY/defs_nr_UE.h b/openair1/PHY/defs_nr_UE.h index e3c0737838..c9f29e2266 100644 --- a/openair1/PHY/defs_nr_UE.h +++ b/openair1/PHY/defs_nr_UE.h @@ -235,6 +235,11 @@ typedef struct { int32_t *txdataF_layers[NR_MAX_NB_LAYERS]; } NR_UE_PUSCH; +typedef struct { + bool active[2]; + fapi_nr_ul_config_pucch_pdu pucch_pdu[2]; + } NR_UE_PUCCH; + typedef struct { /// \brief Holds the transmit data in time domain. /// For IFFT_FPGA this points to the same memory as PHY_vars->tx_vars[a].TX_DMA_BUFFER. @@ -810,6 +815,7 @@ typedef struct { NR_UE_PDCCH *pdcch_vars[RX_NB_TH_MAX][NUMBER_OF_CONNECTED_gNB_MAX]; NR_UE_PRACH *prach_vars[NUMBER_OF_CONNECTED_gNB_MAX]; NR_UE_PUSCH *pusch_vars[RX_NB_TH_MAX][NUMBER_OF_CONNECTED_gNB_MAX]; + NR_UE_PUCCH *pucch_vars[RX_NB_TH_MAX][NUMBER_OF_CONNECTED_gNB_MAX]; NR_UE_DLSCH_t *dlsch[RX_NB_TH_MAX][NUMBER_OF_CONNECTED_gNB_MAX][NR_MAX_NB_CODEWORDS]; // two RxTx Threads NR_UE_ULSCH_t *ulsch[RX_NB_TH_MAX][NUMBER_OF_CONNECTED_gNB_MAX][NR_MAX_NB_CODEWORDS]; // two code words NR_UE_DLSCH_t *dlsch_SI[NUMBER_OF_CONNECTED_gNB_MAX]; @@ -957,9 +963,6 @@ typedef struct { /// PUSCH contention-based access vars PUSCH_CA_CONFIG_DEDICATED pusch_ca_config_dedicated[NUMBER_OF_eNB_MAX]; // lola - /// PUCCH variables - - PUCCH_CONFIG_DEDICATED pucch_config_dedicated[NUMBER_OF_CONNECTED_gNB_MAX]; //#if defined(UPGRADE_RAT_NR) #if 1 @@ -970,9 +973,6 @@ typedef struct { PDSCH_ServingCellConfig_t PDSCH_ServingCellConfig; PDSCH_Config_t PDSCH_Config; - PUCCH_ConfigCommon_nr_t pucch_config_common_nr[NUMBER_OF_CONNECTED_gNB_MAX]; - PUCCH_Config_t pucch_config_dedicated_nr[NUMBER_OF_CONNECTED_gNB_MAX]; - PUSCH_Config_t pusch_config; SRS_NR srs; diff --git a/openair1/PHY/impl_defs_nr.h b/openair1/PHY/impl_defs_nr.h index fad578c8b0..5ead56fe5f 100644 --- a/openair1/PHY/impl_defs_nr.h +++ b/openair1/PHY/impl_defs_nr.h @@ -681,23 +681,10 @@ uci_onPusch_t uci_onPusch; * ************************************************************************/ -#define MAX_NR_OF_PUCCH_P0_PER_SET (8) #define NUMBER_PUCCH_FORMAT_NR (5) typedef int8_t power_level_t; /* INTEGER (-16..15) */ -typedef struct { - uint8_t p0_PUCCH_Id; /* INTEGER (1..8) */ - power_level_t p0_PUCCH_Value; -} P0_PUCCH_t; - -typedef struct { - power_level_t deltaF_PUCCH_f[NUMBER_PUCCH_FORMAT_NR]; - P0_PUCCH_t *p0_Set[MAX_NR_OF_PUCCH_P0_PER_SET]; - // pathlossReferenceRSs SEQUENCE (SIZE (1..maxNrofPUCCH-PathlossReferenceRSs)) OF PUCCH-PathlossReferenceRS OPTIONAL, -- Need M - int8_t twoPUCCH_PC_AdjustmentStates; - -} PUCCH_PowerControl_t; /*********************************************************************** * @@ -887,9 +874,10 @@ typedef struct { PUCCH_FormatConfig_t *formatConfig[NUMBER_PUCCH_FORMAT_NR-1]; /* format 0 is not there */ uint8_t dl_DataToUL_ACK[NB_DL_DATA_TO_UL_ACK]; /* table TS 38.213 Table 9.2.3-1: Mapping of PSDCH-to-HARQ_feedback timing indicator field values to numbers of slots */ void *spatial_Relation_Info[MAX_NR_OF_SPATIAL_RELATION_INFOS]; - PUCCH_PowerControl_t pucch_PowerControl; } PUCCH_Config_t; + + /*********************************************************************** * * FUNCTIONALITY : PhysicalCellGroupConfig diff --git a/openair1/SCHED_NR_UE/defs.h b/openair1/SCHED_NR_UE/defs.h index 2675e46a04..c4a3de1d5a 100644 --- a/openair1/SCHED_NR_UE/defs.h +++ b/openair1/SCHED_NR_UE/defs.h @@ -417,6 +417,7 @@ void nr_fill_rx_indication(fapi_nr_rx_indication_t *rx_ind, uint8_t gNB_id, PHY_VARS_NR_UE *ue, NR_UE_DLSCH_t *dlsch0, + NR_UE_DLSCH_t *dlsch1, uint16_t n_pdus); diff --git a/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c b/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c index 06e1266208..7fb190931e 100644 --- a/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c +++ b/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c @@ -47,6 +47,7 @@ const char *ul_pdu_type[]={"PRACH", "PUCCH", "PUSCH", "SRS"}; int8_t nr_ue_scheduled_response(nr_scheduled_response_t *scheduled_response){ + bool found = false; if(scheduled_response != NULL){ module_id_t module_id = scheduled_response->module_id; @@ -59,7 +60,7 @@ int8_t nr_ue_scheduled_response(nr_scheduled_response_t *scheduled_response){ NR_UE_DLSCH_t *dlsch0 = NULL; NR_UE_PDCCH *pdcch_vars = PHY_vars_UE_g[module_id][cc_id]->pdcch_vars[thread_id][0]; NR_UE_ULSCH_t *ulsch0 = PHY_vars_UE_g[module_id][cc_id]->ulsch[thread_id][0][0]; - NR_DL_FRAME_PARMS frame_parms = PHY_vars_UE_g[module_id][cc_id]->frame_parms; + NR_UE_PUCCH *pucch_vars = PHY_vars_UE_g[module_id][cc_id]->pucch_vars[thread_id][0]; if(scheduled_response->dl_config != NULL){ fapi_nr_dl_config_request_t *dl_config = scheduled_response->dl_config; @@ -119,19 +120,13 @@ int8_t nr_ue_scheduled_response(nr_scheduled_response_t *scheduled_response){ dlsch0_harq->mcs = dlsch_config_pdu->mcs; dlsch0_harq->rvidx = dlsch_config_pdu->rv; dlsch0->g_pucch = dlsch_config_pdu->accumulated_delta_PUCCH; - dlsch0_harq->harq_ack.pucch_resource_indicator = dlsch_config_pdu->pucch_resource_id; - dlsch0_harq->harq_ack.slot_for_feedback_ack = (slot+dlsch_config_pdu->pdsch_to_harq_feedback_time_ind)%frame_parms.slots_per_frame; dlsch0_harq->Nl=1; dlsch0_harq->mcs_table=dlsch_config_pdu->mcs_table; - dlsch0_harq->harq_ack.rx_status = downlink_harq_process(dlsch0_harq, dlsch0->current_harq_pid, dlsch_config_pdu->ndi, dlsch0->rnti_type); if (dlsch0_harq->status != ACTIVE) { // dlsch0_harq->status not ACTIVE may be due to false retransmission. Reset the // following flag to skip PDSCH procedures in that case. dlsch0->active = 0; - dlsch0_harq->harq_ack.ack = 1; - dlsch0_harq->harq_ack.send_harq_status = 1; } - dlsch0_harq->harq_ack.vDAI_DL = dlsch_config_pdu->dai; /* PTRS */ dlsch0_harq->PTRSFreqDensity = dlsch_config_pdu->PTRSFreqDensity; dlsch0_harq->PTRSTimeDensity = dlsch_config_pdu->PTRSTimeDensity; @@ -139,7 +134,7 @@ int8_t nr_ue_scheduled_response(nr_scheduled_response_t *scheduled_response){ dlsch0_harq->nEpreRatioOfPDSCHToPTRS = dlsch_config_pdu->nEpreRatioOfPDSCHToPTRS; dlsch0_harq->PTRSReOffset = dlsch_config_pdu->PTRSReOffset; dlsch0_harq->pduBitmap = dlsch_config_pdu->pduBitmap; - LOG_D(MAC, ">>>> \tdlsch0->g_pucch = %d\tdlsch0_harq.mcs = %d\tpdsch_to_harq_feedback_time_ind = %d\tslot_for_feedback_ack = %d\n", dlsch0->g_pucch, dlsch0_harq->mcs, dlsch_config_pdu->pdsch_to_harq_feedback_time_ind, dlsch0_harq->harq_ack.slot_for_feedback_ack); + LOG_D(MAC, ">>>> \tdlsch0->g_pucch = %d\tdlsch0_harq.mcs = %d\n", dlsch0->g_pucch, dlsch0_harq->mcs); } } } @@ -163,9 +158,6 @@ int8_t nr_ue_scheduled_response(nr_scheduled_response_t *scheduled_response){ nfapi_nr_ue_pusch_pdu_t *pusch_config_pdu; /* PUCCH */ fapi_nr_ul_config_pucch_pdu *pucch_config_pdu; - PUCCH_ConfigCommon_nr_t *pucch_config_common_nr; - PUCCH_Config_t *pucch_config_dedicated_nr; - PUCCH_format_t *format_params; switch (pdu_type){ @@ -203,47 +195,16 @@ int8_t nr_ue_scheduled_response(nr_scheduled_response_t *scheduled_response){ break; case (FAPI_NR_UL_CONFIG_TYPE_PUCCH): - // pucch config pdu + found = false; pucch_config_pdu = &ul_config->ul_config_list[i].pucch_config_pdu; - pucch_resource_id = 0; //FIXME!!! - format = 1; // FIXME!!! - pucch_config_common_nr = &PHY_vars_UE_g[module_id][cc_id]->pucch_config_common_nr[0]; - pucch_config_dedicated_nr = &PHY_vars_UE_g[module_id][cc_id]->pucch_config_dedicated_nr[0]; - format_params = &pucch_config_dedicated_nr->PUCCH_Resource[pucch_resource_id]->format_parameters; - - format_params->initialCyclicShift = pucch_config_pdu->initialCyclicShift; - format_params->nrofSymbols = pucch_config_pdu->nrofSymbols; - format_params->startingSymbolIndex = pucch_config_pdu->startingSymbolIndex; - format_params->nrofPRBs = pucch_config_pdu->nrofPRBs; - format_params->timeDomainOCC = pucch_config_pdu->timeDomainOCC; - format_params->occ_length = pucch_config_pdu->occ_length; - format_params->occ_Index = pucch_config_pdu->occ_Index; - - pucch_config_dedicated_nr->PUCCH_Resource[pucch_resource_id]->startingPRB = pucch_config_pdu->startingPRB; - pucch_config_dedicated_nr->PUCCH_Resource[pucch_resource_id]->intraSlotFrequencyHopping = pucch_config_pdu->intraSlotFrequencyHopping; - pucch_config_dedicated_nr->PUCCH_Resource[pucch_resource_id]->secondHopPRB = pucch_config_pdu->secondHopPRB; // Not sure this parameter is used - pucch_config_dedicated_nr->formatConfig[format - 1]->additionalDMRS = pucch_config_pdu->additionalDMRS; // At this point we need to know which format is going to be used - pucch_config_dedicated_nr->formatConfig[format - 1]->pi2PBSK = pucch_config_pdu->pi2PBSK; - - pucch_config_common_nr->pucch_GroupHopping = pucch_config_pdu->pucch_GroupHopping; - pucch_config_common_nr->hoppingId = pucch_config_pdu->hoppingId; - pucch_config_common_nr->p0_nominal = pucch_config_pdu->p0_nominal; - - /* pucch_config_dedicated->PUCCH_Resource[pucch_resource_id]->format_parameters.initialCyclicShift = pucch_config_pdu->initialCyclicShift; - pucch_config_dedicated->PUCCH_Resource[pucch_resource_id]->format_parameters.nrofSymbols = pucch_config_pdu->nrofSymbols; - pucch_config_dedicated->PUCCH_Resource[pucch_resource_id]->format_parameters.startingSymbolIndex = pucch_config_pdu->startingSymbolIndex; - pucch_config_dedicated->PUCCH_Resource[pucch_resource_id]->format_parameters.nrofPRBs = pucch_config_pdu->nrofPRBs; - pucch_config_dedicated->PUCCH_Resource[pucch_resource_id]->startingPRB = pucch_config_pdu->startingPRB; - pucch_config_dedicated->PUCCH_Resource[pucch_resource_id]->format_parameters.timeDomainOCC = pucch_config_pdu->timeDomainOCC; - pucch_config_dedicated->PUCCH_Resource[pucch_resource_id]->format_parameters.occ_length = pucch_config_pdu->occ_length; - pucch_config_dedicated->PUCCH_Resource[pucch_resource_id]->format_parameters.occ_Index = pucch_config_pdu->occ_Index; - pucch_config_dedicated->PUCCH_Resource[pucch_resource_id]->intraSlotFrequencyHopping = pucch_config_pdu->intraSlotFrequencyHopping; - pucch_config_dedicated->PUCCH_Resource[pucch_resource_id]->secondHopPRB = pucch_config_pdu->secondHopPRB; // Not sure this parameter is used - pucch_config_dedicated->formatConfig[format-1]->additionalDMRS = pucch_config_pdu->additionalDMRS; // At this point we need to know which format is going to be used - pucch_config_dedicated->formatConfig[format-1]->pi2PBSK = pucch_config_pdu->pi2PBSK; - pucch_config_common->pucch_GroupHopping = pucch_config_pdu->pucch_GroupHopping; - pucch_config_common->hoppingId = pucch_config_pdu->hoppingId; - pucch_config_common->p0_nominal = pucch_config_pdu->p0_nominal;*/ + for(int j=0; j<2; j++) { + if(pucch_vars->active[j] == false) { + memcpy((void*)&(pucch_vars->pucch_pdu[j]), (void*)pucch_config_pdu, sizeof(fapi_nr_ul_config_pucch_pdu)); + found = true; + } + } + if (!found) + LOG_E(PHY, "Couldn't find allocation for PUCCH PDU in PUCCH VARS\n"); break; case (FAPI_NR_UL_CONFIG_TYPE_PRACH): diff --git a/openair1/SCHED_NR_UE/harq_nr.c b/openair1/SCHED_NR_UE/harq_nr.c index 85f6d90bbe..06395c79e8 100644 --- a/openair1/SCHED_NR_UE/harq_nr.c +++ b/openair1/SCHED_NR_UE/harq_nr.c @@ -98,43 +98,6 @@ #define DL_DCI (1) #define UL_DCI (0) -/******************************************************************* -* -* NAME : get_dci_info_for_harq -* -* PARAMETERS : pointer to ue context -* id of current gNB -* number of uplink processes -* maximum number of uplink retransmissions -* RETURN : none -* -* DESCRIPTION : update HARQ entity with information from DCI -* TS 38.212 7.3.1.2 DCI formats for scheduling PDSCH -* -*********************************************************************/ - -void get_dci_info_for_harq(PHY_VARS_NR_UE *ue, NR_DCI_INFO_EXTRACTED_t *nr_dci_info_extracted, - NR_UE_DLSCH_t **dlsch, NR_UE_ULSCH_t *ulsch, uint8_t slot, uint8_t tx_offset) -{ - if (nr_dci_info_extracted->identifier_dci_formats == DL_DCI) { - - dlsch[0]->current_harq_pid = nr_dci_info_extracted->harq_process_number; - - NR_DL_UE_HARQ_t *dl_harq = dlsch[0]->harq_processes[dlsch[0]->current_harq_pid]; - - dl_harq->harq_ack.vDAI_DL = nr_dci_info_extracted->dai+1; - dl_harq->harq_ack.pucch_resource_indicator = nr_dci_info_extracted->pucch_resource_ind; - dl_harq->harq_ack.slot_for_feedback_ack = (slot + nr_dci_info_extracted->pdsch_to_harq_feedback_time_ind)%ue->frame_parms.slots_per_subframe; - dl_harq->harq_ack.harq_id = nr_dci_info_extracted->harq_process_number; - dl_harq->harq_ack.rx_status = downlink_harq_process(dl_harq, dlsch[0]->current_harq_pid, nr_dci_info_extracted->ndi, dlsch[0]->rnti_type); - } - else if (nr_dci_info_extracted->identifier_dci_formats == UL_DCI) { - - /* store harq id for which pusch should be transmitted at rx_slot + tx_offset */ - set_tx_harq_id(ulsch, nr_dci_info_extracted->harq_process_number, (slot + tx_offset)%ue->frame_parms.slots_per_subframe); - ulsch->harq_processes[nr_dci_info_extracted->harq_process_number]->tx_status = uplink_harq_process(ulsch, nr_dci_info_extracted->harq_process_number, nr_dci_info_extracted->ndi, ulsch->rnti_type); - } -} /******************************************************************* * @@ -345,158 +308,4 @@ void init_downlink_harq_status(NR_DL_UE_HARQ_t *dl_harq) dl_harq->status = SCH_IDLE; dl_harq->first_tx = 1; dl_harq->round = 0; - dl_harq->harq_ack.ack = DL_ACKNACK_NO_SET; - dl_harq->harq_ack.send_harq_status = 0; - dl_harq->harq_ack.vDAI_UL = UL_DAI_NO_SET; - dl_harq->harq_ack.vDAI_DL = DL_DAI_NO_SET; - dl_harq->harq_ack.slot_for_feedback_ack = NR_MAX_SLOTS_PER_FRAME; - dl_harq->harq_ack.pucch_resource_indicator = MAX_PUCCH_RESOURCE_INDICATOR; - dl_harq->harq_ack.n_CCE = 0; - dl_harq->harq_ack.N_CCE = 0;; -} - -/******************************************************************* -* -* NAME : config_downlink_harq_process -* -* PARAMETERS : pointer to ue context -* id of current gNB -* number of downlink processes -* -* RETURN : none -* -* DESCRIPTION : configuration of downlink HARQ entity -* -*********************************************************************/ - -void config_downlink_harq_process(PHY_VARS_NR_UE *ue, int gNB_id, int TB_id, int execution_thread_number, uint8_t number_harq_processes_for_pdsch) -{ - NR_UE_DLSCH_t *dlsch; - - dlsch = (NR_UE_DLSCH_t *)malloc16(sizeof(NR_UE_DLSCH_t)); - - if (dlsch != NULL) { - - memset(dlsch,0,sizeof(NR_UE_DLSCH_t)); - - ue->dlsch[execution_thread_number][gNB_id][TB_id] = dlsch; - } - else { - LOG_E(PHY, "Fatal memory allocation problem at line %d in function %s of file %s \n", __LINE__ , __func__, __FILE__); - assert(0); - } - - dlsch->Mdlharq = number_harq_processes_for_pdsch; /* an additional HARQ is reserved for PBCCH */ - dlsch->number_harq_processes_for_pdsch = number_harq_processes_for_pdsch; - - /* allocation of HARQ process context */ - for (int harq_pid = 0; harq_pid < number_harq_processes_for_pdsch; harq_pid++) { - - //dlsch->harq_processes[harq_pid] = (NR_DL_UE_HARQ_t *)malloc16(sizeof(NR_DL_UE_HARQ_t)); - - /*if (dlsch->harq_processes[harq_pid] == NULL) { - LOG_E(PHY, "Fatal memory allocation problem at line %d in function %s of file %s \n", __LINE__ , __func__, __FILE__); - assert(0); - }*/ - - memset(&dlsch->harq_processes[harq_pid],0,sizeof(NR_DL_UE_HARQ_t)); - - NR_DL_UE_HARQ_t *dl_harq = dlsch->harq_processes[harq_pid]; - - init_downlink_harq_status(dl_harq); - } -} - -/******************************************************************* -* -* NAME : release_downlink_harq_process -* -* PARAMETERS : pointer to ue context -* id of current gNB -* TB_id transport block identity 0 or 1 -* execution_thread_number thread number for current downlink processing -* RETURN : none -* -* DESCRIPTION : release of HARQ downlink entity -* -*********************************************************************/ - -void release_downlink_harq_process(PHY_VARS_NR_UE *ue, int gNB_id, int TB_id, int execution_thread_number) -{ - NR_UE_DLSCH_t *dlsch = ue->dlsch[execution_thread_number][gNB_id][TB_id]; - - /*for (int process_id = 0; process_id < dlsch->Mdlharq; process_id++) { - - free16(dlsch->harq_processes[process_id],sizeof(NR_DL_UE_HARQ_t)); - - dlsch->harq_processes[process_id] = NULL; - }*/ - - free16(dlsch,sizeof(NR_UE_DLSCH_t)); - - ue->dlsch[execution_thread_number][gNB_id][TB_id] = NULL; -} - -/******************************************************************* -* -* NAME : downlink_harq_process -* -* PARAMETERS : downlink harq context -* harq identifier -* ndi (new data indicator) from DCI -* rnti_type from DCI -* -* RETURN : none -* -* DESCRIPTION : manage downlink information from DCI for downlink transmissions/retransmissions -* TS 38.321 5.3.1 DL Assignment reception -* TS 38.321 5.3.2 HARQ operation -* -*********************************************************************/ - -harq_result_t downlink_harq_process(NR_DL_UE_HARQ_t *dl_harq, int harq_pid, int ndi, uint8_t rnti_type) -{ - harq_result_t result_harq = RETRANSMISSION_HARQ; - - if (rnti_type == _CS_RNTI_) - { - LOG_E(PHY, "Fatal error in HARQ entity due to not supported CS_RNTI at line %d in function %s of file %s \n", __LINE__ , __func__, __FILE__); - return(NEW_TRANSMISSION_HARQ); - } - else if ((rnti_type != _C_RNTI_) && (rnti_type != _TC_RNTI_)) { - /* harq mechanism is not relevant for other rnti */ - return(NEW_TRANSMISSION_HARQ); - } - - if (dl_harq->first_tx == 1) { - dl_harq->round = 0; - dl_harq->status = ACTIVE; - dl_harq->DCINdi = ndi; - dl_harq->first_tx = 0; - - result_harq = NEW_TRANSMISSION_HARQ; - - LOG_D(PHY, "[HARQ-DL-PDSCH harqId : %d] first new reception \n", harq_pid); - } - else if (dl_harq->DCINdi != ndi) { - dl_harq->round = 0; - dl_harq->status = ACTIVE; - dl_harq->DCINdi = ndi; - - result_harq = NEW_TRANSMISSION_HARQ; - - LOG_D(PHY, "[HARQ-DL-PDSCH harqId : %d] new reception due to toogle of ndi \n", harq_pid); - } - else { - - dl_harq->round++; - - if (dl_harq->harq_ack.ack) dl_harq->status = SCH_IDLE; - - result_harq = RETRANSMISSION_HARQ; - - LOG_D(PHY, "[HARQ-DL-PDSCH harqId : %d] reception of a retransmission \n", harq_pid); - } - - return (result_harq); } diff --git a/openair1/SCHED_NR_UE/harq_nr.h b/openair1/SCHED_NR_UE/harq_nr.h index c6d47a91ef..8b48886d88 100644 --- a/openair1/SCHED_NR_UE/harq_nr.h +++ b/openair1/SCHED_NR_UE/harq_nr.h @@ -46,8 +46,6 @@ #define NR_DEFAULT_DLSCH_HARQ_PROCESSES (8) /* TS 38.214 5.1 */ -#define NR_DL_MAX_DAI (4) /* TS 38.213 table 9.1.3-1 Value of counter DAI for DCI format 1_0 and 1_1 */ -#define NR_DL_MAX_NB_CW (2) /* number of downlink code word */ #define DL_ACKNACK_NO_SET (2) #define DL_NACK (0) #define DL_ACK (1) @@ -68,18 +66,6 @@ /*************** FUNCTIONS ****************************************/ -/** \brief This function updates HARQ context according to dci - @param PHY_VARS_NR_UE ue context - @param nr_dci_info_extracted extracted information from dci - @param dlsch downlink context - @param ulsch uplink context - @param nr_slot_rx rx slot - @param tx_offset slot offset for tx - @returns none */ - -void get_dci_info_for_harq(PHY_VARS_NR_UE *ue, NR_DCI_INFO_EXTRACTED_t *nr_dci_info_extracted, - NR_UE_DLSCH_t **dlsch, NR_UE_ULSCH_t *ulsch, uint8_t nr_slot_rx, uint8_t tx_offset); - /** \brief This function configures uplink HARQ context @param PHY_VARS_NR_UE ue context @param gNB_id gNodeB identifier @@ -127,24 +113,6 @@ harq_result_t uplink_harq_process(NR_UE_ULSCH_t *ulsch, int harq_pid, int ndi, u void init_downlink_harq_status(NR_DL_UE_HARQ_t *dl_harq); -/** \brief This function configures downlink HARQ context - @param PHY_VARS_NR_UE ue context - @param gNB_id gNodeB identifier - @param TB_id transport block identifier - @param execution_thread_number thread_number - @param number_harq_processes maximum number of downlink HARQ processes - @returns none */ - -void config_downlink_harq_process(PHY_VARS_NR_UE *ue, int gNB_id, int TB_id, int execution_thread_number, uint8_t number_harq_processes); - -/** \brief This function releases downlink HARQ context - @param PHY_VARS_NR_UE ue context - @param gNB_id gNodeB identifier - @param TB_id transport block identifier - @param execution_thread_number thread_number - @returns none */ - -void release_downlink_harq_process(PHY_VARS_NR_UE *ue, int gNB_id, int TB_id, int execution_thread_number); /** \brief This function update downlink harq context and return reception type (new transmission or retransmission) @param dlsch downlink harq context diff --git a/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c b/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c index b2073c5b30..028009e75b 100644 --- a/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c +++ b/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c @@ -122,9 +122,10 @@ void nr_fill_rx_indication(fapi_nr_rx_indication_t *rx_ind, uint8_t gNB_id, PHY_VARS_NR_UE *ue, NR_UE_DLSCH_t *dlsch0, + NR_UE_DLSCH_t *dlsch1, uint16_t n_pdus){ - int harq_pid; + NR_DL_FRAME_PARMS *frame_parms = &ue->frame_parms; if (n_pdus > 1){ @@ -133,11 +134,27 @@ void nr_fill_rx_indication(fapi_nr_rx_indication_t *rx_ind, switch (pdu_type){ case FAPI_NR_RX_PDU_TYPE_SIB: + rx_ind->rx_indication_body[n_pdus - 1].pdsch_pdu.harq_pid = dlsch0->current_harq_pid; + rx_ind->rx_indication_body[n_pdus - 1].pdsch_pdu.ack_nack = dlsch0->harq_processes[dlsch0->current_harq_pid]->ack; + rx_ind->rx_indication_body[n_pdus - 1].pdsch_pdu.pdu = dlsch0->harq_processes[dlsch0->current_harq_pid]->b; + rx_ind->rx_indication_body[n_pdus - 1].pdsch_pdu.pdu_length = dlsch0->harq_processes[dlsch0->current_harq_pid]->TBS / 8; + break; case FAPI_NR_RX_PDU_TYPE_DLSCH: + if(dlsch0) { + rx_ind->rx_indication_body[n_pdus - 1].pdsch_pdu.harq_pid = dlsch0->current_harq_pid; + rx_ind->rx_indication_body[n_pdus - 1].pdsch_pdu.ack_nack = dlsch0->harq_processes[dlsch0->current_harq_pid]->ack; + rx_ind->rx_indication_body[n_pdus - 1].pdsch_pdu.pdu = dlsch0->harq_processes[dlsch0->current_harq_pid]->b; + rx_ind->rx_indication_body[n_pdus - 1].pdsch_pdu.pdu_length = dlsch0->harq_processes[dlsch0->current_harq_pid]->TBS / 8; + } + if(dlsch1) { + AssertFatal(1==0,"Second codeword currently not supported\n"); + } + break; case FAPI_NR_RX_PDU_TYPE_RAR: - harq_pid = dlsch0->current_harq_pid; - rx_ind->rx_indication_body[n_pdus - 1].pdsch_pdu.pdu = dlsch0->harq_processes[harq_pid]->b; - rx_ind->rx_indication_body[n_pdus - 1].pdsch_pdu.pdu_length = dlsch0->harq_processes[harq_pid]->TBS / 8; + rx_ind->rx_indication_body[n_pdus - 1].pdsch_pdu.harq_pid = dlsch0->current_harq_pid; + rx_ind->rx_indication_body[n_pdus - 1].pdsch_pdu.ack_nack = dlsch0->harq_processes[dlsch0->current_harq_pid]->ack; + rx_ind->rx_indication_body[n_pdus - 1].pdsch_pdu.pdu = dlsch0->harq_processes[dlsch0->current_harq_pid]->b; + rx_ind->rx_indication_body[n_pdus - 1].pdsch_pdu.pdu_length = dlsch0->harq_processes[dlsch0->current_harq_pid]->TBS / 8; break; case FAPI_NR_RX_PDU_TYPE_SSB: rx_ind->rx_indication_body[n_pdus - 1].ssb_pdu.pdu = ue->pbch_vars[gNB_id]->decoded_output; @@ -1018,6 +1035,28 @@ void nr_ue_dlsch_procedures(PHY_VARS_NR_UE *ue, } + switch (pdsch) { + case RA_PDSCH: + nr_fill_dl_indication(&dl_indication, NULL, &rx_ind, proc, ue, gNB_id); + nr_fill_rx_indication(&rx_ind, FAPI_NR_RX_PDU_TYPE_RAR, gNB_id, ue, dlsch0, NULL, number_pdus); + ue->UE_mode[gNB_id] = RA_RESPONSE; + break; + case PDSCH: + nr_fill_dl_indication(&dl_indication, NULL, &rx_ind, proc, ue, gNB_id); + nr_fill_rx_indication(&rx_ind, FAPI_NR_RX_PDU_TYPE_DLSCH, gNB_id, ue, dlsch0, NULL, number_pdus); + break; + case SI_PDSCH: + nr_fill_dl_indication(&dl_indication, NULL, &rx_ind, proc, ue, gNB_id); + nr_fill_rx_indication(&rx_ind, FAPI_NR_RX_PDU_TYPE_SIB, gNB_id, ue, dlsch0, NULL, number_pdus); + break; + default: + break; + } + + LOG_D(PHY, "In %s DL PDU length in bits: %d, in bytes: %d \n", __FUNCTION__, dlsch0->harq_processes[harq_pid]->TBS, dlsch0->harq_processes[harq_pid]->TBS / 8); + + + #if UE_TIMING_TRACE stop_meas(&ue->dlsch_decoding_stats[proc->thread_id]); #if DISABLE_LOG_X @@ -1115,43 +1154,19 @@ void nr_ue_dlsch_procedures(PHY_VARS_NR_UE *ue, #endif #endif - LOG_I(PHY,"AbsSubframe %d.%d --> ldpc Decoding for CW1 %5.3f\n", + LOG_D(PHY,"AbsSubframe %d.%d --> ldpc Decoding for CW1 %5.3f\n", frame_rx%1024, nr_slot_rx,(ue->dlsch_decoding_stats[proc->thread_id].p_time)/(cpuf*1000.0)); LOG_D(PHY, "harq_pid: %d, TBS expected dlsch1: %d \n", harq_pid, dlsch1->harq_processes[harq_pid]->TBS); } LOG_D(PHY," ------ end ldpc decoder for AbsSubframe %d.%d ------ decoded in %d \n", frame_rx, nr_slot_rx, ret); - LOG_D(PHY, "harq_pid: %d, TBS expected dlsch0: %d \n",harq_pid, dlsch0->harq_processes[harq_pid]->TBS); - if(retmax_ldpc_iterations+1){ - - switch (pdsch) { - case RA_PDSCH: - nr_fill_dl_indication(&dl_indication, NULL, &rx_ind, proc, ue, gNB_id); - nr_fill_rx_indication(&rx_ind, FAPI_NR_RX_PDU_TYPE_RAR, gNB_id, ue, dlsch0, number_pdus); - ue->UE_mode[gNB_id] = RA_RESPONSE; - break; - case PDSCH: - nr_fill_dl_indication(&dl_indication, NULL, &rx_ind, proc, ue, gNB_id); - nr_fill_rx_indication(&rx_ind, FAPI_NR_RX_PDU_TYPE_DLSCH, gNB_id, ue, dlsch0, number_pdus); - break; - case SI_PDSCH: - nr_fill_dl_indication(&dl_indication, NULL, &rx_ind, proc, ue, gNB_id); - nr_fill_rx_indication(&rx_ind, FAPI_NR_RX_PDU_TYPE_SIB, gNB_id, ue, dlsch0, number_pdus); - break; - default: - break; + // send to mac + if (ue->if_inst && ue->if_inst->dl_indication) { + ue->if_inst->dl_indication(&dl_indication, ul_time_alignment); } - LOG_D(PHY, "In %s DL PDU length in bits: %d, in bytes: %d \n", __FUNCTION__, dlsch0->harq_processes[harq_pid]->TBS, dlsch0->harq_processes[harq_pid]->TBS / 8); - - // send to mac - if (ue->if_inst && ue->if_inst->dl_indication) { - ue->if_inst->dl_indication(&dl_indication, ul_time_alignment); - } - } - if (ue->mac_enabled == 1) { /* Time Alignment procedure diff --git a/openair1/SCHED_NR_UE/pucch_power_control_ue_nr.c b/openair1/SCHED_NR_UE/pucch_power_control_ue_nr.c deleted file mode 100644 index f43f4d98c9..0000000000 --- a/openair1/SCHED_NR_UE/pucch_power_control_ue_nr.c +++ /dev/null @@ -1,218 +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 - */ - -/************************************************************************ -* -* MODULE : PUCCH power control for UE NR -* -* DESCRIPTION : functions related to PUCCH Transmit power -* TS 38.213 7.2.1 UE behaviour -* -**************************************************************************/ - -#include "PHY/NR_REFSIG/ss_pbch_nr.h" -#include "PHY/defs_nr_UE.h" -#include "SCHED_NR_UE/pucch_uci_ue_nr.h" -#include "SCHED_NR_UE/pucch_power_control_ue_nr.h" -#include -#include - -/**************** defines **************************************/ - -/**************** variables **************************************/ - - -/**************** functions **************************************/ - - -/******************************************************************* -* -* NAME : get_pucch_tx_power_ue -* -* PARAMETERS : ue context -* gNB_id identity -* slots for rx and tx -* pucch_format_nr_t pucch format -* nb_of_prbs number of prb allocated to pucch -* N_sc_ctrl_RB subcarrier control rb related to current pucch format -* N_symb_PUCCH number of pucch symbols excluding those reserved for dmrs -* O_UCI number of bits for UCI Uplink Control Information -* O_SR number of bits for SR scheduling Request -* O_UCI number of bits for CSI Channel State Information -* O_ACK number of bits for HARQ-ACK -* O_CRC number of bits for CRC -* n_HARQ_ACK use for obtaining a PUCCH transmission power -* -* RETURN : pucch power level in dBm -* -* DESCRIPTION : determines pucch transmission power in dBm -* TS 38.213 7.2.1 UE behaviour -* -*********************************************************************/ - -int16_t get_pucch_tx_power_ue(PHY_VARS_NR_UE *ue, - uint8_t gNB_id, - UE_nr_rxtx_proc_t *proc, - pucch_format_nr_t pucch_format, - int nb_of_prbs, - int N_sc_ctrl_RB, - int N_symb_PUCCH, - int O_UCI, - int O_SR, - int O_CSI, - int O_ACK, - int O_CRC, - int n_HARQ_ACK) { - - int16_t P_O_NOMINAL_PUCCH = ue->pucch_config_common_nr[gNB_id].p0_nominal; - PUCCH_PowerControl_t *power_config = &ue->pucch_config_dedicated_nr[gNB_id].pucch_PowerControl; - int16_t P_O_UE_PUCCH; - int16_t G_b_f_c = 0; - - if (ue->pucch_config_dedicated_nr[gNB_id].spatial_Relation_Info[0] != NULL) { /* FFS TODO NR */ - LOG_E(PHY,"PUCCH Spatial relation infos are not yet implemented : at line %d in function %s of file %s \n", LINE_FILE , __func__, __FILE__); - return (PUCCH_POWER_DEFAULT); - } - - if (power_config->p0_Set[0] != NULL) { - P_O_UE_PUCCH = power_config->p0_Set[0]->p0_PUCCH_Value; /* get from index 0 if no spatial relation set */ - G_b_f_c = 0; - } - else { - G_b_f_c = ue->dlsch[proc->thread_id][gNB_id][0]->g_pucch; - LOG_D(PHY,"PUCCH Transmit power control command not yet implemented for NR : at line %d in function %s of file %s \n", LINE_FILE , __func__, __FILE__); - return (PUCCH_POWER_DEFAULT); - } - - int P_O_PUCCH = P_O_NOMINAL_PUCCH + P_O_UE_PUCCH; - - int16_t PL = get_nr_PL(ue->Mod_id, ue->CC_id, gNB_id); /* LTE function because NR path loss not yet implemented FFS TODO NR */ - - int16_t delta_F_PUCCH = power_config->deltaF_PUCCH_f[pucch_format]; - - int DELTA_TF; - uint16_t N_ref_PUCCH; - - /* computing of pucch transmission power adjustment */ - switch (pucch_format) { - case pucch_format0_nr: - { - N_ref_PUCCH = 2; - DELTA_TF = 10 * log10(N_ref_PUCCH/N_symb_PUCCH); - break; - } - case pucch_format1_nr: - { - N_ref_PUCCH = N_SYMB_SLOT; - DELTA_TF = 10 * log10(N_ref_PUCCH/N_symb_PUCCH); - break; - } - case pucch_format2_nr: - case pucch_format3_nr: - case pucch_format4_nr: - { - float N_RE = nb_of_prbs * N_sc_ctrl_RB * N_symb_PUCCH; - float K1 = 6; - /* initial phase so no higher layer parameters */ - if (ue->UE_mode[gNB_id] != PUSCH) { - if (O_ACK == 0) { - n_HARQ_ACK = 0; - } - else { - n_HARQ_ACK = 1; - } - } - if (O_UCI < 12) { - - DELTA_TF = 10 * log10((double)(((K1 * (n_HARQ_ACK + O_SR + O_CSI))/N_RE))); - } - else { - float K2 = 2.4; - float BPRE = (O_ACK + O_SR + O_CSI + O_CRC)/N_RE; - DELTA_TF = 10 * log10((double)(pow(2,(K2*BPRE)) - 1)); - } - break; - } - default: - { - LOG_E(PHY,"PUCCH unknown pucch format : at line %d in function %s of file %s \n", LINE_FILE , __func__, __FILE__); - return (0); - } - } - - int k2; - - if (power_config->twoPUCCH_PC_AdjustmentStates > 1) { - LOG_E(PHY,"PUCCH power control adjustment states with 2 states not yet implemented : at line %d in function %s of file %s \n", LINE_FILE , __func__, __FILE__); - return (PUCCH_POWER_DEFAULT); - } - - /* response to a detection by the UE of a DCI format 1_0 or DCI format 1_1 */ - //int K_PUCCH = 0; - if (O_ACK != 0) { - /* it assumes that PDCCH is in the first symbol of receive slot FFS TDDO NR */ - //int slots_gap = (proc->nr_slot_tx > proc->nr_slot_rx ? (proc->nr_slot_tx - proc->nr_slot_rx - 1) : ((proc->nr_slot_tx + ue->frame_parms.slots_per_subframe) - proc->nr_slot_rx - 1)); - //K_PUCCH = (slots_gap * (ue->frame_parms.symbols_per_tti)) - 1; - } - else { - /* field k2 is not present - to check k2 of pucch from upper layer FFS TDDO NR */ - if (ue->pusch_config.pusch_TimeDomainResourceAllocation[0] == NULL) { - if (ue->frame_parms.numerology_index == 0) { - k2 = 1; - } - else { - k2 = ue->frame_parms.numerology_index; - } - } - else - { - /* get minimum value of k2 */ - int i = 0; - int k2_min = 32; /* max value of k2 */ - do { - k2 = ue->pusch_config.pusch_TimeDomainResourceAllocation[i]->k2; - if (k2 < k2_min) { - k2_min = k2; - } - i++; - if (i >= MAX_NR_OF_UL_ALLOCATIONS) { - break; - } - } while(ue->pusch_config.pusch_TimeDomainResourceAllocation[i] != NULL); - k2 = k2_min; - } - //K_PUCCH = N_SYMB_SLOT * k2; /* the product of a number of symbols per slot and the minimum of the values provided by higher layer parameter k2 */ - } - - int contributor = (10 * log10((double)(pow(2,(ue->frame_parms.numerology_index)) * nb_of_prbs))); - - int16_t pucch_power = P_O_PUCCH + contributor + PL + delta_F_PUCCH + DELTA_TF + G_b_f_c; - - if (pucch_power > ue->tx_power_max_dBm) { - pucch_power = ue->tx_power_max_dBm; - } - - NR_TST_PHY_PRINTF("PUCCH ( Tx power : %d dBm ) ( 10Log(...) : %d ) ( from Path Loss : %d ) ( delta_F_PUCCH : %d ) ( DELTA_TF : %d ) ( G_b_f_c : %d ) \n", - pucch_power, contributor, PL, delta_F_PUCCH, DELTA_TF, G_b_f_c); - - return (pucch_power); -} - diff --git a/openair1/SCHED_NR_UE/pucch_power_control_ue_nr.h b/openair1/SCHED_NR_UE/pucch_power_control_ue_nr.h deleted file mode 100644 index 3ebd263c94..0000000000 --- a/openair1/SCHED_NR_UE/pucch_power_control_ue_nr.h +++ /dev/null @@ -1,65 +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 - */ - -/************************************************************************ -* -* MODULE : PUCCH power control for UE NR -* -* DESCRIPTION : functions related to PUCCH Transmit power -* TS 38.213 7.2.1 UE behaviour -* -**************************************************************************/ - -#ifndef PUCCH_POWER_CONTROL_H -#define PUCCH_POWER_CONTROL_H - -/*************** INCLUDE *******************************************/ - -/*************** DEFINE ********************************************/ - -#define PUCCH_POWER_DEFAULT (0) /* in dBm */ - -/*************** VARIABLES *****************************************/ - -/*************** FUNCTIONS *****************************************/ - - -/** \brief This function returns pucch power level in dBm - @param ue context - @param gNB_id identity - @param slots for rx and tx - @param pucch_format_nr_t pucch format - @param nb_of_prbs number of prb allocated to pucch - @param N_sc_ctrl_RB subcarrier control rb related to current pucch format - @param N_symb_PUCCH number of pucch symbols excluding those reserved for dmrs - @param O_UCI number of bits for UCI Uplink Control Information - @param O_SR number of bits for SR scheduling Request - @param int O_UCI number of bits for CSI Channel State Information - @param O_ACK number of bits for HARQ-ACK - @param O_CRC number of bits for CRC - @param n_HARQ_ACK use for obtaining a PUCCH transmission power - @returns pucch power level in dBm */ - -int16_t get_pucch_tx_power_ue(PHY_VARS_NR_UE *ue, uint8_t gNB_id, UE_nr_rxtx_proc_t *proc, pucch_format_nr_t pucch_format, - int nb_of_prbs, int N_sc_ctrl_RB, int N_symb_PUCCH, int O_UCI, int O_SR, int O_CSI, int O_ACK, - int O_CRC, int n_HARQ_ACK); - -#endif /* PUCCH_POWER_CONTROL_H */ diff --git a/openair1/SCHED_NR_UE/pucch_uci_ue_nr.c b/openair1/SCHED_NR_UE/pucch_uci_ue_nr.c index 6ca3f856e4..cc12589e78 100644 --- a/openair1/SCHED_NR_UE/pucch_uci_ue_nr.c +++ b/openair1/SCHED_NR_UE/pucch_uci_ue_nr.c @@ -47,7 +47,6 @@ #include "SCHED_NR_UE/defs.h" #include "SCHED_NR_UE/harq_nr.h" -#include "SCHED_NR_UE/pucch_power_control_ue_nr.h" #define DEFINE_VARIABLES_PUCCH_UE_NR_H #include "SCHED_NR_UE/pucch_uci_ue_nr.h" @@ -56,19 +55,6 @@ #endif -/* 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 */ -/* Sequence cyclic shift */ = { 0, 6 } -; - -/* TS 36.213 Table 9.2.5-2: Mapping of values for two HARQ-ACK bits and positive SR to sequences */ -static const int sequence_cyclic_shift_2_harq_ack_bits_positive_sr[4] -/* HARQ-ACK Value (0,0) (0,1) (1,0) (1,1) */ -/* Sequence cyclic shift */ = { 1, 4, 10, 7 } -; - - uint8_t nr_is_cqi_TXOp(PHY_VARS_NR_UE *ue,UE_nr_rxtx_proc_t *proc,uint8_t gNB_id); uint8_t nr_is_ri_TXOp(PHY_VARS_NR_UE *ue,UE_nr_rxtx_proc_t *proc,uint8_t gNB_id); @@ -76,49 +62,12 @@ static const uint16_t scheduling_request_periodicity[NB_SR_PERIOD] = { 0, 0, 1, 2, 4, 5, 8, 10, 16, 20, 40, 80, 160, 320, 640 } ; -/* TS 38.213 9.2.5.2 UE procedure for multiplexing HARQ-ACK/SR and CSI in a PUCCH */ -/* this is a counter of number of pucch format 4 per subframe */ -static int nb_pucch_format_4_in_subframes[LTE_NUMBER_OF_SUBFRAMES_PER_FRAME] = { 0 } ; - /* TS 36.213 Table 9.2.5.2-1: Code rate corresponding to higher layer parameter PUCCH-F2-maximum-coderate, */ /* or PUCCH-F3-maximum-coderate, or PUCCH-F4-maximum-coderate */ /* add one additional element set to 0 for parsing the array until this end */ /* stored values are code rates * 100 */ //static const int code_rate_r_time_100[8] = { (0.08 * 100), (0.15 * 100), (0.25*100), (0.35*100), (0.45*100), (0.60*100), (0.80*100), 0 } ; -/* TS 38.213 Table 9.2.3-4: Mapping of values for two HARQ-ACK bits to sequences */ -static const int sequence_cyclic_shift_2_harq_ack_bits[4] -/* HARQ-ACK Value (0,0) (0,1) (1,0) (1,1) */ -/* Sequence cyclic shift */ = { 0, 3, 9, 6 } -; - -/* TS 38.211 Table 6.4.1.3.3.2-1: DM-RS positions for PUCCH format 3 and 4 */ -static const int nb_symbols_excluding_dmrs[NB_SYMBOL_MINUS_FOUR][2][2] -= { -/* No additional DMRS Additional DMRS */ -/* PUCCH length No hopping hopping No hopping hopping */ -/* index 0 1 0 1 */ -/* 4 */ {{ 3 , 2 } , { 3 , 2 }}, -/* 5 */ {{ 3 , 3 } , { 3 , 3 }}, -/* 6 */ {{ 4 , 4 } , { 4 , 4 }}, -/* 7 */ {{ 5 , 5 } , { 5 , 5 }}, -/* 8 */ {{ 6 , 6 } , { 6 , 6 }}, -/* 9 */ {{ 7 , 7 } , { 7 , 7 }}, -/* 10 */ {{ 8 , 8 } , { 6 , 6 }}, -/* 11 */ {{ 9 , 9 } , { 7 , 7 }}, -/* 12 */ {{ 10 , 10 } , { 8 , 8 }}, -/* 13 */ {{ 11 , 11 } , { 9 , 9 }}, -/* 14 */ {{ 12 , 12 } , { 10 , 10 }}, -} -; - - -/* TS 36.213 Table 9.2.5-1: Mapping of values for one HARQ-ACK bit and positive SR to sequences */ -static const int sequence_cyclic_shift_1_harq_ack_bit_positive_sr[2] -/* HARQ-ACK Value 0 1 */ -/* Sequence cyclic shift */ = { 3, 9 } -; - static float RSRP_meas_mapping_nr[98] = { -140, @@ -366,1065 +315,85 @@ void nr_generate_pucch3_4(int32_t **txdataF, * *********************************************************************/ -/* TS 36.213 Table 9.2.1-1: PUCCH resource sets before dedicated PUCCH resource configuration */ -const initial_pucch_resource_t initial_pucch_resource[NB_INITIAL_PUCCH_RESOURCE] -= -{ -/* format first symbol Number of symbols PRB offset nb index for set of initial CS */ -/* 0 */ { pucch_format0_nr, 12, 2, 0, 2, { 0, 3, 0, 0 } }, -/* 1 */ { pucch_format0_nr, 12, 2, 0, 3, { 0, 4, 8, 0 } }, -/* 2 */ { pucch_format0_nr, 12, 2, 3, 3, { 0, 4, 8, 0 } }, -/* 3 */ { pucch_format1_nr, 10, 4, 0, 2, { 0, 6, 0, 0 } }, -/* 4 */ { pucch_format1_nr, 10, 4, 0, 4, { 0, 3, 6, 9 } }, -/* 5 */ { pucch_format1_nr, 10, 4, 2, 4, { 0, 3, 6, 9 } }, -/* 6 */ { pucch_format1_nr, 10, 4, 4, 4, { 0, 3, 6, 9 } }, -/* 7 */ { pucch_format1_nr, 4, 10, 0, 2, { 0, 6, 0, 0 } }, -/* 8 */ { pucch_format1_nr, 4, 10, 0, 4, { 0, 3, 6, 9 } }, -/* 9 */ { pucch_format1_nr, 4, 10, 2, 4, { 0, 3, 6, 9 } }, -/* 10 */ { pucch_format1_nr, 4, 10, 4, 4, { 0, 3, 6, 9 } }, -/* 11 */ { pucch_format1_nr, 0, 14, 0, 2, { 0, 6, 0, 0 } }, -/* 12 */ { pucch_format1_nr, 0, 14, 0, 4, { 0, 3, 6, 9 } }, -/* 13 */ { pucch_format1_nr, 0, 14, 2, 4, { 0, 3, 6, 9 } }, -/* 14 */ { pucch_format1_nr, 0, 14, 4, 4, { 0, 3, 6, 9 } }, -/* 15 */ { pucch_format1_nr, 0, 14, 0, 4, { 0, 3, 6, 9 } }, -} -; +void pucch_procedures_ue_nr(PHY_VARS_NR_UE *ue, + uint8_t gNB_id, + UE_nr_rxtx_proc_t *proc) { -bool pucch_procedures_ue_nr(PHY_VARS_NR_UE *ue, uint8_t gNB_id, UE_nr_rxtx_proc_t *proc, bool reset_harq) -{ - uint8_t sr_payload = 0; - uint32_t pucch_ack_payload = 0; /* maximum number of bits for pucch payload is supposed to be 32 */ - uint64_t pucch_payload = 0; - uint32_t csi_payload = 0; - int frame_tx = proc->frame_tx; int nr_slot_tx = proc->nr_slot_tx; - int Mod_id = ue->Mod_id; - int CC_id = ue->CC_id; + fapi_nr_ul_config_pucch_pdu *pucch_pdu; + NR_UE_PUCCH *pucch_vars = ue->pucch_vars[proc->thread_id][gNB_id]; - int O_SR = 0; - int O_ACK = 0; - int O_CSI = 0; /* channel state information */ - int N_UCI = 0; /* size in bits for Uplink Control Information */ - int cqi_status = 0; - int ri_status = 0; - int csi_status = 0; + for (int i=0; i<2; i++) { + if(pucch_vars->active[i]) { + pucch_pdu = &pucch_vars->pucch_pdu[i]; + uint16_t nb_of_prbs = pucch_pdu->prb_size; + /* Generate PUCCH signal according to its format and parameters */ + ue->generate_ul_signal[gNB_id] = 1; - int initial_pucch_id = NB_INITIAL_PUCCH_RESOURCE; - int pucch_resource_set = MAX_NB_OF_PUCCH_RESOURCE_SETS; - int pucch_resource_id = MAX_NB_OF_PUCCH_RESOURCES; - int pucch_resource_indicator = MAX_PUCCH_RESOURCE_INDICATOR; - int n_HARQ_ACK; + int16_t PL = get_nr_PL(ue->Mod_id, ue->CC_id, gNB_id); /* LTE function because NR path loss not yet implemented FFS TODO NR */ + int contributor = (10 * log10((double)(pow(2,(ue->frame_parms.numerology_index)) * nb_of_prbs))); - int dmrs_scrambling_id=0,data_scrambling_id=0; + int16_t pucch_tx_power = pucch_pdu->pucch_tx_power + contributor + PL; - NR_UE_MAC_INST_t *mac = get_mac_inst(0); - NR_PUCCH_Resource_t *pucch_resource; - uint16_t crnti = mac->crnti; - NR_BWP_Id_t bwp_id = mac->UL_BWP_Id; + if (pucch_tx_power > ue->tx_power_max_dBm) + pucch_tx_power = ue->tx_power_max_dBm; - /* update current context */ + /* set tx power */ + ue->tx_power_dBm[nr_slot_tx] = pucch_tx_power; + ue->tx_total_RE[nr_slot_tx] = nb_of_prbs*N_SC_RB; - int subframe_number = proc->nr_slot_rx / ue->frame_parms.slots_per_subframe; - nb_pucch_format_4_in_subframes[subframe_number] = 0; /* reset pucch format 4 counter at current rx position */ - - int dl_harq_pid = ue->dlsch[proc->thread_id][gNB_id][0]->current_harq_pid; - - if (dl_harq_pid < ue->dlsch[proc->thread_id][gNB_id][0]->number_harq_processes_for_pdsch) { - /* pucch indicator can be reseted in function get_downlink_ack so it should be get now */ - pucch_resource_indicator = ue->dlsch[proc->thread_id][gNB_id][0]->harq_processes[dl_harq_pid]->harq_ack.pucch_resource_indicator; - } - - LOG_D(PHY, "PUCCH: %d.%d bwp_id %ld dl_harq_pid = %d, pucch_resource_indicator = %d\n", frame_tx, nr_slot_tx, bwp_id,dl_harq_pid, pucch_resource_indicator); - - /* Part - I - * Collect feedback that should be transmitted at this nr_slot_tx : - * - ACK/NACK, SR, CSI (CQI, RI, ...) - */ - - sr_payload = 0; - - if (trigger_periodic_scheduling_request( ue, gNB_id, proc ) == 1) { - O_SR = 1; /* sr should be transmitted */ - if (ue->mac_enabled == 1) { - - /* sr_payload = 1 means that this is a positive SR, sr_payload = 0 means that it is a negative SR */ - sr_payload = nr_ue_get_SR(Mod_id, - CC_id, - frame_tx, - gNB_id, - 0,//ue->pdcch_vars[proc->thread_id][gNB_id]->crnti, - nr_slot_tx); // nr_slot_rx used for meas gap - } - else { - sr_payload = 1; - } - } - - O_ACK = get_downlink_ack( ue, gNB_id, proc, &pucch_ack_payload, - &n_HARQ_ACK, reset_harq); // 1 to reset ACK/NACK status : 0 otherwise - - cqi_status = ((ue->cqi_report_config[gNB_id].CQI_ReportPeriodic.cqi_PMI_ConfigIndex>0) && - (nr_is_cqi_TXOp(ue,proc,gNB_id) == 1)); - - ri_status = ((ue->cqi_report_config[gNB_id].CQI_ReportPeriodic.ri_ConfigIndex>0) && - (nr_is_ri_TXOp(ue,proc,gNB_id) == 1)); - - - if (mac->cg && - mac->cg->spCellConfig && - mac->cg->spCellConfig->spCellConfigDedicated && - mac->cg->spCellConfig->spCellConfigDedicated->csi_MeasConfig&& - mac->cg->spCellConfig->spCellConfigDedicated->csi_MeasConfig->choice.setup) { - NR_CSI_MeasConfig_t *csi_MeasConfig = mac->cg->spCellConfig->spCellConfigDedicated->csi_MeasConfig->choice.setup; - - uint16_t report_slot_csi =csi_MeasConfig->csi_ReportConfigToAddModList->list.array[0]->reportConfigType.choice.periodic->reportSlotConfig.choice.slots320; - - //if (mac->csirc->reportQuantity.choice.ssb_Index_RSRP){ - if (report_slot_csi == proc->nr_slot_tx) - csi_status = get_csi_nr(mac, ue, gNB_id, &csi_payload); - else - csi_status = 0; - //} - - O_CSI = cqi_status + ri_status + csi_status; - - /* Part - II */ - /* if payload is empty or only negative SR -> no pucch transmission */ - - if(O_ACK == 0) { - N_UCI = O_SR + O_CSI; - if ((N_UCI == 0) || ((O_CSI == 0) && (sr_payload == 0))) { /* TS 38.213 9.2.4 UE procedure for reporting SR */ - NR_TST_PHY_PRINTF("PUCCH No feedback AbsSubframe %d.%d \n", frame_tx%1024, nr_slot_tx); - LOG_D(PHY,"PUCCH No feedback AbsSubframe %d.%d \n", frame_tx%1024, nr_slot_tx); - return (FALSE); - } - else { - /* a resource set and a resource should be find according to payload size */ - pucch_resource_set = find_pucch_resource_set( mac, gNB_id, N_UCI); - if (pucch_resource_set != MAX_NB_OF_PUCCH_RESOURCE_SETS) { - pucch_resource_indicator = 0; - pucch_resource_id = mac->ULbwp[bwp_id-1]->bwp_Dedicated->pucch_Config->choice.setup->resourceSetToAddModList->list.array[pucch_resource_set]->resourceList.list.array[pucch_resource_indicator][0]; /* get the first resource of the set */ - } - else { - LOG_W(PHY,"PUCCH no resource set found for CSI at line %d in function %s of file %s \n", LINE_FILE , __func__, FILE_NAME); - O_CSI = 0; - csi_payload = 0; - } - - if (O_CSI == 0) { - /* only SR has to be send */ - /* in this case there is no DCI related to PUCCH parameters so pucch resource should be get from sr configuration */ - /* TS 38.213 9.2.4 UE procedure for reporting SR */ - pucch_resource_set = 0; /* force it to a valid value */ - if (ue->scheduling_request_config_nr[gNB_id].sr_ResourceConfig[ue->scheduling_request_config_nr[gNB_id].active_sr_id] != NULL) { - pucch_resource_id = ue->scheduling_request_config_nr[gNB_id].sr_ResourceConfig[ue->scheduling_request_config_nr[gNB_id].active_sr_id]->resource; - } - else { - LOG_E(PHY,"PUCCH No scheduling request configuration : at line %d in function %s of file %s \n", LINE_FILE , __func__, FILE_NAME); - return(FALSE); - } - } - } - } - } - - N_UCI = O_SR + O_ACK + O_CSI; - if (N_UCI ==0) return(TRUE); - - /* Part - III */ - /* Choice PUCCH format and its related parameters */ - pucch_format_nr_t format = pucch_format0_nr; - uint8_t starting_symbol_index=0; - uint8_t nb_symbols_total = 0; - uint8_t nb_symbols = 0; - uint16_t startingPRB = 0;; /* it can be considered as first hop on case of pucch hopping */ - uint16_t secondHopPRB = 0; /* second part for pucch for hopping */ - uint8_t nb_of_prbs = 0; - int m_0 = 0; /* format 0 only */ - int m_CS = 0; /* for all format except for format 0 */ - int index_additional_dmrs = I_PUCCH_NO_ADDITIONAL_DMRS; - int index_hopping = I_PUCCH_NO_HOPPING; - int time_domain_occ = 0; - int occ_length = 0; - int occ_Index = 0; - int BWPsize = 0; - int BWPstart = 0; - - NR_UE_HARQ_STATUS_t *harq_status = &ue->dlsch[proc->thread_id][gNB_id][0]->harq_processes[dl_harq_pid]->harq_ack; - - if (select_pucch_resource(ue, mac, gNB_id, N_UCI, pucch_resource_indicator, &initial_pucch_id, &pucch_resource_set, - &pucch_resource_id, harq_status) == TRUE) { - /* use of initial pucch configuration provided by system information 1 */ - /***********************************************************************/ - if (initial_pucch_id != NB_INITIAL_PUCCH_RESOURCE) { - LOG_I(MAC,"Selecting INITIAL PUCCH Resource\n"); - format = initial_pucch_resource[initial_pucch_id].format; - starting_symbol_index = initial_pucch_resource[initial_pucch_id].startingSymbolIndex; - nb_symbols_total = initial_pucch_resource[initial_pucch_id].nrofSymbols; - - int N_CS = initial_pucch_resource[initial_pucch_id].nb_CS_indexes; - /* see TS 38213 Table 9.2.1-1: PUCCH resource sets before dedicated PUCCH resource configuration */ - BWPsize = NRRIV2BW(mac->scc_SIB->uplinkConfigCommon->initialUplinkBWP.genericParameters.locationAndBandwidth, - MAX_BWP_SIZE); - BWPstart = NRRIV2PRBOFFSET(mac->scc_SIB->uplinkConfigCommon->initialUplinkBWP.genericParameters.locationAndBandwidth, - MAX_BWP_SIZE); - int RB_BWP_offset; - if (initial_pucch_id == 15) { - RB_BWP_offset =BWPsize/4; - } - else - { - RB_BWP_offset = initial_pucch_resource[initial_pucch_id].PRB_offset; - } - if (initial_pucch_id/8 == 0) { - startingPRB = RB_BWP_offset + (initial_pucch_id/N_CS); - secondHopPRB = BWPsize - 1 - RB_BWP_offset - (initial_pucch_id/N_CS); - m_0 = initial_pucch_resource[initial_pucch_id].initial_CS_indexes[initial_pucch_id%N_CS]; - } - else if (initial_pucch_id/8 == 1) - { - startingPRB = RB_BWP_offset + (initial_pucch_id/N_CS); - secondHopPRB = BWPsize - 1 - RB_BWP_offset - ((initial_pucch_id - 8)/N_CS); - m_0 = initial_pucch_resource[initial_pucch_id].initial_CS_indexes[(initial_pucch_id - 8)%N_CS]; - } - if ((ue->UE_mode[gNB_id] != PUSCH) && (O_ACK > 1)) { - O_ACK = 1; - pucch_ack_payload &= 0x1; /* take only first ack */ - LOG_W(PHY,"PUCCH ue is not expected to generate more than one HARQ-ACK at AbsSubframe %d.%d \n", frame_tx%1024, nr_slot_tx); - } - NR_TST_PHY_PRINTF("PUCCH common configuration with index %d \n", initial_pucch_id); - startingPRB += BWPstart; - secondHopPRB += BWPstart; - } - /* use dedicated pucch resource configuration */ - /**********************************************/ - else if ((pucch_resource_set != MAX_NB_OF_PUCCH_RESOURCE_SETS) && (pucch_resource_id != MAX_NB_OF_PUCCH_RESOURCES)) { - /* check that current configuration is supported */ - if (mac->cg && - mac->cg->physicalCellGroupConfig && - (mac->cg->physicalCellGroupConfig->harq_ACK_SpatialBundlingPUCCH != NULL || - mac->cg->physicalCellGroupConfig->pdsch_HARQ_ACK_Codebook != 1)) { - LOG_E(PHY,"PUCCH Unsupported cell group configuration : at line %d in function %s of file %s \n", LINE_FILE , __func__, FILE_NAME); - return(FALSE); - } - else if (mac->cg && - mac->cg->spCellConfig && - mac->cg->spCellConfig->spCellConfigDedicated && - mac->cg->spCellConfig->spCellConfigDedicated->pdsch_ServingCellConfig && - mac->cg->spCellConfig->spCellConfigDedicated->pdsch_ServingCellConfig->choice.setup && - mac->cg->spCellConfig->spCellConfigDedicated->pdsch_ServingCellConfig->choice.setup->codeBlockGroupTransmission != NULL) { - LOG_E(PHY,"PUCCH Unsupported code block group for serving cell config : at line %d in function %s of file %s \n", LINE_FILE , __func__, FILE_NAME); - return(FALSE); - } - NR_PUCCH_Config_t *pucch_Config; - if (bwp_id>0 && - mac->ULbwp[bwp_id-1] && - mac->ULbwp[bwp_id-1]->bwp_Dedicated && - mac->ULbwp[bwp_id-1]->bwp_Dedicated->pucch_Config && - mac->ULbwp[bwp_id-1]->bwp_Dedicated->pucch_Config->choice.setup) - pucch_Config = mac->ULbwp[bwp_id-1]->bwp_Dedicated->pucch_Config->choice.setup; - else if (bwp_id==0 && - mac->cg && - mac->cg->spCellConfig && - mac->cg->spCellConfig->spCellConfigDedicated && - mac->cg->spCellConfig->spCellConfigDedicated->uplinkConfig && - mac->cg->spCellConfig->spCellConfigDedicated->uplinkConfig->initialUplinkBWP && - mac->cg->spCellConfig->spCellConfigDedicated->uplinkConfig->initialUplinkBWP->pucch_Config && - mac->cg->spCellConfig->spCellConfigDedicated->uplinkConfig->initialUplinkBWP->pucch_Config->choice.setup) { - pucch_Config = mac->cg->spCellConfig->spCellConfigDedicated->uplinkConfig->initialUplinkBWP->pucch_Config->choice.setup; - BWPsize = NRRIV2BW(mac->scc_SIB->uplinkConfigCommon->initialUplinkBWP.genericParameters.locationAndBandwidth,MAX_BWP_SIZE); - BWPstart = NRRIV2PRBOFFSET(mac->scc_SIB->uplinkConfigCommon->initialUplinkBWP.genericParameters.locationAndBandwidth,MAX_BWP_SIZE); - } - - else AssertFatal(1==0,"no pucch_Config\n"); - pucch_resource = select_resource_by_id(pucch_resource_id, pucch_Config); - format = pucch_resource->format.present; - nb_symbols_total = get_nb_symbols_pucch(pucch_resource, format); - starting_symbol_index = get_starting_symb_idx(pucch_resource, format); - startingPRB = BWPstart + pucch_resource->startingPRB; - secondHopPRB = pucch_resource->intraSlotFrequencyHopping ? (BWPstart+*pucch_resource->secondHopPRB) : startingPRB; - if (format==pucch_format1_nr) - time_domain_occ = pucch_resource->format.choice.format1->timeDomainOCC; - if (format==pucch_format4_nr) { - occ_length = pucch_resource->format.choice.format4->occ_Length; - occ_Index = pucch_resource->format.choice.format4->occ_Index; - } - - m_0 = get_ics_pucch(pucch_resource, format); - AssertFatal(m_0 >= 0, "Invalid m_0\n"); - if (format == pucch_format3_nr) { - if (mac->ULbwp[bwp_id-1]->bwp_Dedicated->pucch_Config->choice.setup->format3->choice.setup->additionalDMRS[0] == 1) { - index_additional_dmrs = I_PUCCH_ADDITIONAL_DMRS; - } - } - else if (format == pucch_format4_nr) { - if (mac->ULbwp[bwp_id-1]->bwp_Dedicated->pucch_Config->choice.setup->format4->choice.setup->additionalDMRS[0] == 1) { - index_additional_dmrs = I_PUCCH_ADDITIONAL_DMRS; - } - } - - if ((format == pucch_format3_nr) || (format == pucch_format4_nr)) { - if (pucch_resource->intraSlotFrequencyHopping[0] == 1) { - index_hopping = I_PUCCH_HOPING; - } - } - - NR_TST_PHY_PRINTF("PUCCH dedicated configuration with resource index %d \n", pucch_resource_id); - } - } - else { - LOG_W(PHY,"PUCCH No PUCCH resource found at AbsSubframe %d.%d \n", frame_tx%1024, nr_slot_tx); - return (FALSE); - } - - //int max_code_rate = 0; - //int Q_m = BITS_PER_SYMBOL_QPSK; /* default pucch modulation type is QPSK with 2 bits per symbol */ - int N_sc_ctrl_RB = 0; - int O_CRC = 0; - - nb_symbols = nb_symbols_total; /* by default, it can be reduced due to symbols reserved for dmrs */ - pucch_resource = format>1 ? - mac->ULbwp[bwp_id-1]->bwp_Dedicated->pucch_Config->choice.setup->resourceToAddModList->list.array[pucch_resource_id]: - 0; - - switch(format) { - case pucch_format0_nr: - { - nb_of_prbs = 1; - N_sc_ctrl_RB = N_SC_RB; - break; - } - case pucch_format1_nr: - { - nb_of_prbs = 1; - N_sc_ctrl_RB = N_SC_RB; - break; - } - case pucch_format2_nr: - { - nb_of_prbs = pucch_resource->format.choice.format2->nrofPRBs; - N_sc_ctrl_RB = N_SC_RB - 4; - break; - } - case pucch_format3_nr: - { - nb_of_prbs = pucch_resource->format.choice.format3->nrofPRBs; - //if (mac->ULbwp[bwp_id-1]->bwp_Dedicated->pucch_Config->choice.setup->format3->choice.setup->pi2BPSK[0] == 1) { - // Q_m = BITS_PER_SYMBOL_BPSK; /* set bpsk modulation type with 1 bit per modulation symbol */ - //} - N_sc_ctrl_RB = N_SC_RB; - nb_symbols = nb_symbols_excluding_dmrs[nb_symbols_total-4][index_additional_dmrs][index_hopping]; - break; - } - case pucch_format4_nr: - { - //if (mac->ULbwp[bwp_id-1]->bwp_Dedicated->pucch_Config->choice.setup->format4->choice.setup->pi2BPSK[0] == 1) { - // Q_m = BITS_PER_SYMBOL_BPSK; /* set bpsk modulation type with 1 bit per modulation symbol */ - //} - nb_symbols = nb_symbols_excluding_dmrs[nb_symbols_total-4][index_additional_dmrs][index_hopping]; - nb_of_prbs = 1; - subframe_number = nr_slot_tx / ue->frame_parms.slots_per_subframe; - nb_pucch_format_4_in_subframes[subframe_number]++; /* increment number of transmit pucch 4 in current subframe */ - NR_TST_PHY_PRINTF("PUCCH Number of pucch format 4 in subframe %d is %d \n", subframe_number, nb_pucch_format_4_in_subframes[subframe_number]); - N_sc_ctrl_RB = N_SC_RB/(nb_pucch_format_4_in_subframes[subframe_number]); - break; - } - } - - /* TS 38.213 9.2.5.2 UE procedure for multiplexing HARQ-ACK/SR and CSI */ - /* drop CSI report if simultaneous HARQ-ACK/SR and periodic/semi-periodic CSI cannot be transmitted at the same time */ - if (format != pucch_format0_nr) { - - if (mac->ULbwp[bwp_id-1]->bwp_Dedicated->pucch_Config->choice.setup->format1 != NULL) { - //max_code_rate = code_rate_r_time_100[mac->ULbwp[bwp_id-1]->bwp_Dedicated->pucch_Config->choice.setup->format1->choice.setup->maxCodeRate[0]]; /* it is code rate * 10 */ - - if ((O_ACK != 0) && (mac->ULbwp[bwp_id-1]->bwp_Dedicated->pucch_Config->choice.setup->format1->choice.setup->simultaneousHARQ_ACK_CSI[0] == 0)) { - N_UCI = N_UCI - O_CSI; - O_CSI = cqi_status = ri_status = 0; - csi_payload = 0; /* csi should be dropped in this case */ - } - } - - /* TS 38.212 6.3.1.2 Code block segmentation and CRC attachment */ - /* crc attachment can be done depending of payload size */ -// if (N_UCI < 11) { -// O_CRC = 0; /* no additional crc bits */ -// } -// else if ((N_UCI >= 12) && (N_UCI <= 19)) { -// O_CRC = 6; /* number of additional crc bits */ -// } -// else if (N_UCI >= 20) { -// O_CRC = 11; /* number of additional crc bits */ -// } - - N_UCI = N_UCI + O_CRC; - - /* for format 2 and 3, number of prb should be adjusted to minimum value which cope to information size */ - /*if (nb_of_prbs > 1 ) { - int nb_prb_min = 0; - int payload_in_bits; - do { - nb_prb_min++; - payload_in_bits = (nb_prb_min * N_sc_ctrl_RB * nb_symbols * Q_m * max_code_rate)/100; */ /* code rate has been multiplied by 100 */ - - /*NR_TST_PHY_PRINTF("PUCCH Adjust number of prb : (N_UCI : %d ) (payload_in_bits : %d) (N_sc_ctrl_RB : %d) (nb_symbols : %d) (Q_m : %d) (max_code_rate*100 : %d) \n", - N_UCI, payload_in_bits, N_sc_ctrl_RB, nb_symbols, Q_m, max_code_rate); - } while (N_UCI > payload_in_bits); - - if (nb_prb_min > nb_of_prbs) { - LOG_E(PHY,"PUCCH Number of prbs too small for current pucch bits to transmit : at line %d in function %s of file %s \n", LINE_FILE , __func__, FILE_NAME); - return (FALSE); - } - else { - nb_of_prbs = nb_prb_min; - } - }*/ - - /* TS 38.213 9.2.4 for a positive SR transmission, payload b(0) = 0 */ - if ((O_SR == 1) && (format == pucch_format1_nr)) { - sr_payload = 0; - } - } - else { /* only format 0 here */ - if ((O_SR == 0) && (O_CSI == 0)) { /* only ack is transmitted TS 36.213 9.2.3 UE procedure for reporting HARQ-ACK */ - if (O_ACK == 1) { - m_CS = sequence_cyclic_shift_1_harq_ack_bit[pucch_ack_payload & 0x1]; /* only harq of 1 bit */ - } - else { - m_CS = sequence_cyclic_shift_2_harq_ack_bits[pucch_ack_payload & 0x3]; /* only harq with 2 bits */ - } - } - else if ((O_SR == 1) && (O_CSI == 0)) { /* SR + eventually ack are transmitted TS 36.213 9.2.5.1 UE procedure for multiplexing HARQ-ACK or CSI and SR */ - if (sr_payload == 1) { /* positive scheduling request */ - if (O_ACK == 1) { - m_CS = sequence_cyclic_shift_1_harq_ack_bit_positive_sr[pucch_ack_payload & 0x1]; /* positive SR and harq of 1 bit */ - } - else if (O_ACK == 2) { - m_CS = sequence_cyclic_shift_2_harq_ack_bits_positive_sr[pucch_ack_payload & 0x3]; /* positive SR and harq with 2 bits */ - } - else { - m_CS = 0; /* only positive SR */ - } - } - } - N_UCI = O_SR = O_ACK = 0; - pucch_payload = sr_payload = pucch_ack_payload = 0; /* no data for format 0 */ - } - - /* TS 38.212 6.3.1 Uplink control information on PUCCH */ - /* information concatenation of payload */ - /* CSI SR HARQ-ACK */ - /* bit order of payload of size n : a(n)....................................a(0) */ - /* a(0) is the LSB and a(n) the MSB <--------><--------------><------------><----------> */ - /* O_CRC O_CSI O_SR O_ACK */ - /* */ - /* remark: crc is not part of payload, it is later added by block coding. */ - - if (N_UCI > (sizeof(uint64_t)*8)) { - LOG_E(PHY,"PUCCH number of UCI bits exceeds payload size : at line %d in function %s of file %s \n", LINE_FILE , __func__, FILE_NAME); - return(0); - } - - pucch_payload = pucch_payload | (csi_payload << (O_ACK + O_SR)) | (sr_payload << O_ACK) | pucch_ack_payload; - - NR_TST_PHY_PRINTF("PUCCH ( AbsSubframe : %d.%d ) ( total payload size %d data 0x%02x ) ( ack length %d data 0x%02x ) ( sr length %d value %d ) ( csi length %d data : 0x%02x ) \n", - frame_tx%1024, nr_slot_tx, N_UCI, pucch_payload, O_ACK, pucch_ack_payload, O_SR, sr_payload, csi_status, csi_payload); - - NR_TST_PHY_PRINTF("PUCCH ( format : %d ) ( modulation : %s ) ( nb prb : %d ) ( nb symbols total: %d ) ( nb symbols : %d ) ( max code rate*100 : %d ) ( starting_symbol_index : %d ) \n", - format, (Q_m == BITS_PER_SYMBOL_QPSK ? " QPSK " : " BPSK "), nb_of_prbs, nb_symbols_total, nb_symbols, max_code_rate, starting_symbol_index); - - NR_TST_PHY_PRINTF("PUCCH ( startingPRB : %d ) ( secondHopPRB : %d ) ( m_0 : %d ) ( m_CS : %d ) ( time_domain_occ %d ) (occ_length : %d ) ( occ_Index : %d ) \n", - startingPRB (absolute), secondHopPRB (absolute), m_0, m_CS, time_domain_occ, occ_length, occ_Index); - - /* Part - IV */ - /* Generate PUCCH signal according to its format and parameters */ - ue->generate_ul_signal[gNB_id] = 1; - - int16_t pucch_tx_power = get_pucch_tx_power_ue( ue, gNB_id, proc, format, - nb_of_prbs, N_sc_ctrl_RB, nb_symbols, N_UCI, O_SR, O_CSI, O_ACK, - O_CRC, n_HARQ_ACK); - - /* set tx power */ - ue->tx_power_dBm[nr_slot_tx] = pucch_tx_power; - ue->tx_total_RE[nr_slot_tx] = nb_of_prbs*N_SC_RB; - - int tx_amp; + int tx_amp; #if defined(EXMIMO) || defined(OAI_USRP) || defined(OAI_BLADERF) || defined(OAI_LMSSDR) || defined(OAI_ADRV9371_ZC706) - tx_amp = nr_get_tx_amp(pucch_tx_power, - ue->tx_power_max_dBm, - ue->frame_parms.N_RB_UL, - nb_of_prbs); + tx_amp = nr_get_tx_amp(pucch_tx_power, + ue->tx_power_max_dBm, + ue->frame_parms.N_RB_UL, + nb_of_prbs); #else - tx_amp = AMP; + tx_amp = AMP; #endif - switch(format) { - case pucch_format0_nr: - { - int pucch_GroupHopping = mac->ULbwp[bwp_id-1] ? - mac->ULbwp[bwp_id-1]->bwp_Common->pucch_ConfigCommon->choice.setup->pucch_GroupHopping: - mac->scc_SIB->uplinkConfigCommon->initialUplinkBWP.pucch_ConfigCommon->choice.setup->pucch_GroupHopping; - int hoppingId = mac->ULbwp[bwp_id-1] ? - mac->ULbwp[bwp_id-1]->bwp_Common->pucch_ConfigCommon->choice.setup->hoppingId[0]: - (mac->scc_SIB->uplinkConfigCommon->initialUplinkBWP.pucch_ConfigCommon->choice.setup->hoppingId? - mac->scc_SIB->uplinkConfigCommon->initialUplinkBWP.pucch_ConfigCommon->choice.setup->hoppingId[0]: - mac->physCellId); - nr_generate_pucch0(ue,ue->common_vars.txdataF, - &ue->frame_parms, - pucch_GroupHopping, - hoppingId, - tx_amp, - nr_slot_tx, - (uint8_t)m_0, - (uint8_t)m_CS, - nb_symbols_total, - starting_symbol_index, - startingPRB, - secondHopPRB - ); - break; - } - case pucch_format1_nr: - { - nr_generate_pucch1(ue,ue->common_vars.txdataF, - &ue->frame_parms, - &ue->pucch_config_dedicated[gNB_id], - pucch_payload, - tx_amp, - nr_slot_tx, - (uint8_t)m_0, - nb_symbols_total, - starting_symbol_index, - startingPRB, - secondHopPRB, - (uint8_t)time_domain_occ, - (uint8_t)N_UCI); - break; - } - case pucch_format2_nr: - { - nr_generate_pucch2(ue, - crnti, - dmrs_scrambling_id, - data_scrambling_id, - ue->common_vars.txdataF, - &ue->frame_parms, - &ue->pucch_config_dedicated[gNB_id], - pucch_payload, - tx_amp, - nr_slot_tx, - nb_symbols_total, - starting_symbol_index, - nb_of_prbs, - startingPRB, - (uint8_t)N_UCI); - break; - } - case pucch_format3_nr: - case pucch_format4_nr: - { - nr_generate_pucch3_4(ue, - 0,//ue->pdcch_vars[proc->thread_id][gNB_id]->crnti, - ue->common_vars.txdataF, - &ue->frame_parms, - format, - &ue->pucch_config_dedicated[gNB_id], - pucch_payload, - tx_amp, - nr_slot_tx, - nb_symbols_total, - starting_symbol_index, - nb_of_prbs, - startingPRB, - secondHopPRB, - (uint8_t)N_UCI, - (uint8_t)occ_length, - (uint8_t)occ_Index); - break; + switch(pucch_pdu->format_type) { + case 0: + nr_generate_pucch0(ue, + ue->common_vars.txdataF, + &ue->frame_parms, + tx_amp, + nr_slot_tx, + pucch_pdu); + break; + case 1: + nr_generate_pucch1(ue, + ue->common_vars.txdataF, + &ue->frame_parms, + tx_amp, + nr_slot_tx, + pucch_pdu); + break; + case 2: + nr_generate_pucch2(ue, + ue->common_vars.txdataF, + &ue->frame_parms, + tx_amp, + nr_slot_tx, + pucch_pdu); + break; + case 3: + case 4: + nr_generate_pucch3_4(ue, + ue->common_vars.txdataF, + &ue->frame_parms, + tx_amp, + nr_slot_tx, + pucch_pdu); + break; + } } + pucch_vars->active[i] = false; } - return (TRUE); } -/******************************************************************* -* -* NAME : get_downlink_ack -* -* PARAMETERS : ue context -* processing slots of reception/transmission -* gNB_id identifier -* -* RETURN : o_ACK acknowledgment data -* o_ACK_number_bits number of bits for acknowledgment -* -* DESCRIPTION : return acknowledgment value -* TS 38.213 9.1.3 Type-2 HARQ-ACK codebook determination -* -* --+--------+-------+--------+-------+--- ---+-------+-- -* | PDCCH1 | | PDCCH2 |PDCCH3 | | PUCCH | -* --+--------+-------+--------+-------+--- ---+-------+-- -* DAI_DL 1 2 3 ACK for -* V V V PDCCH1, PDDCH2 and PCCH3 -* | | | ^ -* +-----------------+-------+---------------+ -* -* PDCCH1, PDCCH2 and PDCCH3 are PDCCH monitoring occasions -* M is the total of monitoring occasions -* -*********************************************************************/ - -uint8_t get_downlink_ack(PHY_VARS_NR_UE *ue, uint8_t gNB_id, UE_nr_rxtx_proc_t *proc, - uint32_t *o_ACK, int *n_HARQ_ACK, - bool do_reset) // 1 to reset ACK/NACK status : 0 otherwise -{ - NR_UE_HARQ_STATUS_t *harq_status; - uint32_t ack_data[NR_DL_MAX_NB_CW][NR_DL_MAX_DAI] = {{0},{0}}; - uint32_t dai[NR_DL_MAX_NB_CW][NR_DL_MAX_DAI] = {{0},{0}}; /* for serving cell */ - uint32_t dai_total[NR_DL_MAX_NB_CW][NR_DL_MAX_DAI] = {{0},{0}}; /* for multiple cells */ - int number_harq_feedback = 0; - uint32_t dai_current = 0; - uint32_t dai_max = 0; - int number_pid_dl = ue->dlsch[proc->thread_id][gNB_id][0]->number_harq_processes_for_pdsch; - bool two_transport_blocks = FALSE; - int number_of_code_word = 1; - int U_DAI_c = 0; - int N_m_c_rx = 0; - int V_DAI_m_DL = 0; - NR_UE_MAC_INST_t *mac = get_mac_inst(0); - - - - if (mac->DLbwp[0] && - mac->DLbwp[0]->bwp_Dedicated && - mac->DLbwp[0]->bwp_Dedicated->pdsch_Config && - mac->DLbwp[0]->bwp_Dedicated->pdsch_Config->choice.setup && - mac->DLbwp[0]->bwp_Dedicated->pdsch_Config->choice.setup->maxNrofCodeWordsScheduledByDCI[0] == 2) { - two_transport_blocks = TRUE; - number_of_code_word = 2; - } - else { - number_of_code_word = 1; - } - - if (ue->n_connected_gNB > 1) { - LOG_E(PHY,"PUCCH ACK feedback is not implemented for mutiple gNB cells : at line %d in function %s of file %s \n", LINE_FILE , __func__, FILE_NAME); - return (0); - } - - /* look for dl acknowledgment which should be done on current uplink slot */ - for (int code_word = 0; code_word < number_of_code_word; code_word++) { - - for (int dl_harq_pid = 0; dl_harq_pid < number_pid_dl; dl_harq_pid++) { - - for (int thread_idx = 0; thread_idx < RX_NB_TH; thread_idx++) { - - harq_status = &ue->dlsch[thread_idx][gNB_id][code_word]->harq_processes[dl_harq_pid]->harq_ack; - - /* check if current tx slot should transmit downlink acknowlegment */ - if (harq_status->slot_for_feedback_ack == proc->nr_slot_tx) { - - if (harq_status->ack == DL_ACKNACK_NO_SET) { - LOG_E(PHY,"PUCCH Downlink acknowledgment has not been set : at line %d in function %s of file %s \n", LINE_FILE , __func__, FILE_NAME); - } - else if (harq_status->vDAI_DL == DL_DAI_NO_SET) { - LOG_E(PHY,"PUCCH Downlink DAI has not been set : at line %d in function %s of file %s \n", LINE_FILE , __func__, FILE_NAME); - } - else if (harq_status->vDAI_DL > NR_DL_MAX_DAI) { - LOG_E(PHY,"PUCCH Downlink DAI has an invalid value : at line %d in function %s of file %s \n", LINE_FILE , __func__, FILE_NAME); - } - else if (harq_status->send_harq_status == 0) { - LOG_E(PHY,"PUCCH Downlink ack can not be transmitted : at line %d in function %s of file %s \n", LINE_FILE , __func__, FILE_NAME); - } - else { - - dai_current = harq_status->vDAI_DL+1; // DCI DAI to counter DAI conversion - - if (dai_current == 0) { - LOG_E(PHY,"PUCCH Downlink dai is invalid : at line %d in function %s of file %s \n", LINE_FILE , __func__, FILE_NAME); - return(0); - } else if (dai_current > dai_max) { - dai_max = dai_current; - } - - number_harq_feedback++; - ack_data[code_word][dai_current - 1] = harq_status->ack; - dai[code_word][dai_current - 1] = dai_current; - harq_status->slot_for_feedback_ack = NR_MAX_SLOTS_PER_FRAME; - harq_status->send_harq_status = 0; - } - if (do_reset == TRUE) { - init_downlink_harq_status(ue->dlsch[thread_idx][gNB_id][code_word]->harq_processes[dl_harq_pid]); - } - } - } - } - } - - /* no any ack to transmit */ - if (number_harq_feedback == 0) { - *n_HARQ_ACK = 0; - return(0); - } - else if (number_harq_feedback > (sizeof(uint32_t)*8)) { - LOG_E(PHY,"PUCCH number of ack bits exceeds payload size : at line %d in function %s of file %s \n", LINE_FILE , __func__, FILE_NAME); - return(0); - } - - /* for computing n_HARQ_ACK for power */ - V_DAI_m_DL = dai_max; - U_DAI_c = number_harq_feedback/number_of_code_word; - N_m_c_rx = number_harq_feedback; - int N_SPS_c = 0; /* FFS TODO_NR multicells and SPS are not supported at the moment */ - if (mac->cg != NULL && - mac->cg->physicalCellGroupConfig != NULL && - mac->cg->physicalCellGroupConfig->harq_ACK_SpatialBundlingPUCCH != NULL) { - int N_TB_max_DL = mac->DLbwp[0]->bwp_Dedicated->pdsch_Config->choice.setup->maxNrofCodeWordsScheduledByDCI[0]; - *n_HARQ_ACK = (((V_DAI_m_DL - U_DAI_c)%4) * N_TB_max_DL) + N_m_c_rx + N_SPS_c; - NR_TST_PHY_PRINTF("PUCCH power n(%d) = ( V(%d) - U(%d) )mod4 * N_TB(%d) + N(%d) \n", *n_HARQ_ACK, V_DAI_m_DL, U_DAI_c, N_TB_max_DL, N_m_c_rx); - } - - /* - * For a monitoring occasion of a PDCCH with DCI format 1_0 or DCI format 1_1 in at least one serving cell, - * when a UE receives a PDSCH with one transport block and the value of higher layer parameter maxNrofCodeWordsScheduledByDCI is 2, - * the HARQ-ACK response is associated with the first transport block and the UE generates a NACK for the second transport block - * if spatial bundling is not applied (HARQ-ACK-spatial-bundling-PUCCH = FALSE) and generates HARQ-ACK value of ACK for the second - * transport block if spatial bundling is applied. - */ - - for (int code_word = 0; code_word < number_of_code_word; code_word++) { - for (uint32_t i = 0; i < dai_max ; i++ ) { - if (dai[code_word][i] != i + 1) { /* fill table with consistent value for each dai */ - dai[code_word][i] = i + 1; /* it covers case for which PDCCH DCI has not been successfully decoded and so it has been missed */ - ack_data[code_word][i] = 0; /* nack data transport block which has been missed */ - number_harq_feedback++; - } - if (two_transport_blocks == TRUE) { - dai_total[code_word][i] = dai[code_word][i]; /* for a single cell, dai_total is the same as dai of first cell */ - } - } - } - - int M = dai_max; - int j = 0; - uint32_t V_temp = 0; - uint32_t V_temp2 = 0; - int O_ACK = 0; - int O_bit_number_cw0 = 0; - int O_bit_number_cw1 = 0; - - for (int m = 0; m < M ; m++) { - - if (dai[0][m] <= V_temp) { - j = j + 1; - } - - V_temp = dai[0][m]; /* value of the counter DAI for format 1_0 and format 1_1 on serving cell c */ - - if (dai_total[0][m] == 0) { - V_temp2 = dai[0][m]; - } else { - V_temp2 = dai[1][m]; /* second code word has been received */ - O_bit_number_cw1 = (8 * j) + 2*(V_temp - 1) + 1; - *o_ACK = *o_ACK | (ack_data[1][m] << O_bit_number_cw1); - } - - if (two_transport_blocks == TRUE) { - O_bit_number_cw0 = (8 * j) + 2*(V_temp - 1); - } - else { - O_bit_number_cw0 = (4 * j) + (V_temp - 1); - } - - *o_ACK = *o_ACK | (ack_data[0][m] << O_bit_number_cw0); - } - - if (V_temp2 < V_temp) { - j = j + 1; - } - - if (two_transport_blocks == TRUE) { - O_ACK = 2 * ( 4 * j + V_temp2); /* for two transport blocks */ - } - else { - O_ACK = 4 * j + V_temp2; /* only one transport block */ - } - - if (number_harq_feedback != O_ACK) { - LOG_E(PHY,"PUCCH Error for number of bits for acknowledgment : at line %d in function %s of file %s \n", LINE_FILE , __func__, FILE_NAME); - return (0); - } - - return(number_harq_feedback); -} - -/******************************************************************* -* -* NAME : select_pucch_format -* -* PARAMETERS : ue context -* processing slots of reception/transmission -* gNB_id identifier -* -* RETURN : TRUE a valid resource has been found -* -* DESCRIPTION : return tx harq process identifier for given transmission slot -* TS 38.213 9.2.1 PUCCH Resource Sets -* TS 38.213 9.2.2 PUCCH Formats for UCI transmission -* In the case of pucch for scheduling request only, resource is already get from scheduling request configuration -* -*********************************************************************/ - -boolean_t select_pucch_resource(PHY_VARS_NR_UE *ue, NR_UE_MAC_INST_t *mac, uint8_t gNB_id, int uci_size, int pucch_resource_indicator, - int *initial_pucch_id, int *resource_set_id, int *resource_id, NR_UE_HARQ_STATUS_t *harq_status) -{ - boolean_t resource_set_found = FALSE; - int nb_symbols_for_tx = 0; - int current_resource_id = MAX_NB_OF_PUCCH_RESOURCES; - pucch_format_nr_t format_pucch; - int ready_pucch_resource_id = FALSE; /* in the case that it is already given */ - NR_PUCCH_Resource_t *pucch_resource; - NR_BWP_Id_t bwp_id = mac->UL_BWP_Id; - - /* ini values to unset */ - *initial_pucch_id = NB_INITIAL_PUCCH_RESOURCE; - //*resource_set_id = MAX_NB_OF_PUCCH_RESOURCE_SETS; - //*resource_id = MAX_NB_OF_PUCCH_RESOURCES; - - if ((bwp_id ==0 && - mac->cg == NULL) || - (bwp_id == 0 && - mac->cg && - mac->cg->spCellConfig && - mac->cg->spCellConfig->spCellConfigDedicated && - mac->cg->spCellConfig->spCellConfigDedicated->uplinkConfig && - mac->cg->spCellConfig->spCellConfigDedicated->uplinkConfig->initialUplinkBWP && - mac->cg->spCellConfig->spCellConfigDedicated->uplinkConfig->initialUplinkBWP->pucch_Config && - mac->cg->spCellConfig->spCellConfigDedicated->uplinkConfig->initialUplinkBWP->pucch_Config->choice.setup && - mac->cg->spCellConfig->spCellConfigDedicated->uplinkConfig->initialUplinkBWP->pucch_Config->choice.setup->resourceSetToAddModList && - mac->cg->spCellConfig->spCellConfigDedicated->uplinkConfig->initialUplinkBWP->pucch_Config->choice.setup->resourceSetToAddModList->list.array[0] == NULL) || - (mac->ULbwp[bwp_id-1] && - mac->ULbwp[bwp_id-1]->bwp_Dedicated && - mac->ULbwp[bwp_id-1]->bwp_Dedicated->pucch_Config && - mac->ULbwp[bwp_id-1]->bwp_Dedicated->pucch_Config->choice.setup && - mac->ULbwp[bwp_id-1]->bwp_Dedicated->pucch_Config->choice.setup->resourceSetToAddModList && - mac->ULbwp[bwp_id-1]->bwp_Dedicated->pucch_Config->choice.setup->resourceSetToAddModList->list.array[0] == NULL) - ){ - - /* No resource set has been already configured so pucch_configCommon from Sib1 should be used in this case */ - - if (ue->UE_mode[gNB_id] != PUSCH) { - *initial_pucch_id = *mac->scc_SIB->uplinkConfigCommon->initialUplinkBWP.pucch_ConfigCommon->choice.setup->pucch_ResourceCommon; - if (*initial_pucch_id >= NB_INITIAL_PUCCH_RESOURCE) { - LOG_E(PHY,"PUCCH Invalid initial resource index : at line %d in function %s of file %s \n", LINE_FILE , __func__, FILE_NAME); - *initial_pucch_id = NB_INITIAL_PUCCH_RESOURCE; - return (FALSE); - } - } - else { - /* see TS 38.213 9.2.1 PUCCH Resource Sets */ - int delta_PRI = harq_status->pucch_resource_indicator; - // n_CCE can be obtained from ue->dci_ind.dci_list[i].n_CCE. FIXME!!! - // N_CCE can be obtained from ue->dci_ind.dci_list[i].N_CCE. FIXME!!! - //int n_CCE = ue->dci_ind.dci_list[0].n_CCE; - //int N_CCE = ue->dci_ind.dci_list[0].N_CCE; - int n_CCE_0 = harq_status->n_CCE; - int N_CCE_0 = harq_status->N_CCE; - if (N_CCE_0 == 0) { - AssertFatal(1==0,"PUCCH No compatible pucch format found : at line %d in function %s of file %s \n", LINE_FILE , __func__, FILE_NAME); - } - int r_PUCCH = ((2 * n_CCE_0)/N_CCE_0) + (2 * delta_PRI); - *initial_pucch_id = r_PUCCH; - } - nb_symbols_for_tx = initial_pucch_resource[*initial_pucch_id].nrofSymbols; - format_pucch = initial_pucch_resource[*initial_pucch_id].format; - if (check_pucch_format(mac, gNB_id, format_pucch, nb_symbols_for_tx, uci_size) == TRUE) { - return (TRUE); - } - else { - LOG_E(PHY,"PUCCH No compatible pucch format found : at line %d in function %s of file %s \n", LINE_FILE , __func__, FILE_NAME); - return (FALSE); - } - } - else { - /* dedicated resources have been configured */ - int pucch_resource_set_id = 0; - if (*resource_set_id == MAX_NB_OF_PUCCH_RESOURCE_SETS) { - /* from TS 38.331 field maxPayloadMinus1 - -- Maximum number of payload bits minus 1 that the UE may transmit using this PUCCH resource set. In a PUCCH occurrence, the UE - -- chooses the first of its PUCCH-ResourceSet which supports the number of bits that the UE wants to transmit. - -- The field is not present in the first set (Set0) since the maximum Size of Set0 is specified to be 3 bit. - -- The field is not present in the last configured set since the UE derives its maximum payload size as specified in 38.213. - -- This field can take integer values that are multiples of 4. Corresponds to L1 parameter 'N_2' or 'N_3' (see 38.213, section 9.2) - */ - /* look for the first resource set which supports uci_size number of bits for payload */ - pucch_resource_set_id = find_pucch_resource_set(mac, gNB_id, uci_size); - if (pucch_resource_set_id != MAX_NB_OF_PUCCH_RESOURCE_SETS) { - resource_set_found = TRUE; - } - } - else { - /* a valid resource has already be found outside this function */ - resource_set_found = TRUE; - ready_pucch_resource_id = TRUE; - //pucch_resource_indicator = pucch_resource_indicator; - } - - if (resource_set_found == TRUE) { - if (pucch_resource_indicator < MAX_PUCCH_RESOURCE_INDICATOR) { - // Verify that the value of pucch_resource_indicator is valid - struct NR_PUCCH_Config__resourceSetToAddModList *resourceSetToAddModList = NULL; - struct NR_PUCCH_Config__resourceToAddModList *resourceToAddModList = NULL; - if (bwp_id > 0 && mac->ULbwp[bwp_id-1]) { - AssertFatal(mac->ULbwp[bwp_id-1]->bwp_Dedicated->pucch_Config->choice.setup->resourceSetToAddModList!=NULL,"mac->ULbwp[bwp_id-1]->bwp_Dedicated->pucch_Config->choice.setup->resourceSetToAddModList is null\n"); - resourceSetToAddModList = mac->ULbwp[bwp_id-1]->bwp_Dedicated->pucch_Config->choice.setup->resourceSetToAddModList; - resourceToAddModList = mac->ULbwp[bwp_id-1]->bwp_Dedicated->pucch_Config->choice.setup->resourceToAddModList; - } - else if (bwp_id == 0 && mac->cg->spCellConfig->spCellConfigDedicated->uplinkConfig->initialUplinkBWP->pucch_Config->choice.setup->resourceSetToAddModList!=NULL) { - resourceSetToAddModList = mac->cg->spCellConfig->spCellConfigDedicated->uplinkConfig->initialUplinkBWP->pucch_Config->choice.setup->resourceSetToAddModList; - resourceToAddModList = mac->cg->spCellConfig->spCellConfigDedicated->uplinkConfig->initialUplinkBWP->pucch_Config->choice.setup->resourceToAddModList; - } - if (resourceSetToAddModList->list.array[pucch_resource_set_id]->resourceList.list.count <= pucch_resource_indicator) - { - LOG_E(PHY, "Value of pucch_resource_indicator is out of bounds! Possibly due to a false DCI. \n"); - return (FALSE); - } - /* check if resource indexing by pucch_resource_indicator of this set is compatible */ - if ((ready_pucch_resource_id == TRUE) || (resourceSetToAddModList->list.array[pucch_resource_set_id]->resourceList.list.array[pucch_resource_indicator][0] != MAX_NB_OF_PUCCH_RESOURCES)) { - - if (ready_pucch_resource_id == TRUE) { - current_resource_id = *resource_id; - } - else { - int R_PUCCH = resourceSetToAddModList->list.array[pucch_resource_set_id]->resourceList.list.count; - /* is it the first resource and its size exceeds 8 */ - if ((pucch_resource_set_id == 0) - && (R_PUCCH > MAX_NB_OF_PUCCH_RESOURCES_PER_SET_NOT_0)) { - /* see TS 38.213 9.2.3 UE procedure for reporting HARQ-ACK */ - int delta_PRI = pucch_resource_indicator; - int n_CCE_p = harq_status->n_CCE; - int N_CCE_p = harq_status->N_CCE; - int r_PUCCH; - if (N_CCE_p == 0) { - LOG_E(PHY,"PUCCH No compatible pucch format found : at line %d in function %s of file %s \n", LINE_FILE , __func__, FILE_NAME); - return (FALSE); - } - if (pucch_resource_set_id < (R_PUCCH%8)) { - r_PUCCH = ((n_CCE_p * (R_PUCCH/8))/N_CCE_p) + (delta_PRI*(R_PUCCH/8)); - } - else { - r_PUCCH = ((n_CCE_p * (R_PUCCH/8))/N_CCE_p) + (delta_PRI*(R_PUCCH/8)) + (R_PUCCH%8); - } - current_resource_id = r_PUCCH; - } - else { - current_resource_id = resourceSetToAddModList->list.array[pucch_resource_set_id]->resourceList.list.array[pucch_resource_indicator][0]; - } - } - - pucch_resource = resourceToAddModList->list.array[current_resource_id]; - if (pucch_resource != NULL) { - format_pucch = resourceToAddModList->list.array[current_resource_id]->format.present; - nb_symbols_for_tx = get_nb_symbols_pucch(pucch_resource, format_pucch); - - if (check_pucch_format(mac, gNB_id, format_pucch, nb_symbols_for_tx, uci_size) == TRUE) { - *resource_set_id = pucch_resource_set_id; - *resource_id = current_resource_id; - return (TRUE); - } - else { - LOG_E(PHY,"PUCCH Found format no compatible with payload size and symbol length : at line %d in function %s of file %s \n", LINE_FILE , __func__, FILE_NAME); - return (FALSE); - } - } - } - else { - LOG_E(PHY,"PUCCH Undefined Resource related to pucch resource indicator: at line %d in function %s of file %s \n", LINE_FILE , __func__, FILE_NAME); - return (FALSE); - } - } - else { - LOG_E(PHY,"PUCCH Invalid pucch resource indicator: at line %d in function %s of file %s \n", LINE_FILE , __func__, FILE_NAME); - return (FALSE); - } - } - - /* check that a resource has been found */ - if (*resource_set_id == MAX_NB_OF_PUCCH_RESOURCES) { - LOG_E(PHY,"PUCCH No compatible pucch format found : at line %d in function %s of file %s \n", LINE_FILE , __func__, FILE_NAME); - return (FALSE); - } - } - return (FALSE); -} - -/******************************************************************* -* -* NAME : find_pucch_resource_set -* -* PARAMETERS : ue context -* gNB_id identifier -* -* -* RETURN : harq process identifier -* -* DESCRIPTION : return tx harq process identifier for given transmission slot -* YS 38.213 9.2.2 PUCCH Formats for UCI transmission -* -*********************************************************************/ - -int find_pucch_resource_set(NR_UE_MAC_INST_t *mac, uint8_t gNB_id, int uci_size) -{ - int pucch_resource_set_id = 0; - NR_BWP_Id_t bwp_id = mac->DL_BWP_Id; - - //long *pucch_max_pl_bits = NULL; - - /* from TS 38.331 field maxPayloadMinus1 - -- Maximum number of payload bits minus 1 that the UE may transmit using this PUCCH resource set. In a PUCCH occurrence, the UE - -- chooses the first of its PUCCH-ResourceSet which supports the number of bits that the UE wants to transmit. - -- The field is not present in the first set (Set0) since the maximum Size of Set0 is specified to be 3 bit. - -- The field is not present in the last configured set since the UE derives its maximum payload size as specified in 38.213. - -- This field can take integer values that are multiples of 4. Corresponds to L1 parameter 'N_2' or 'N_3' (see 38.213, section 9.2) - */ - /* look for the first resource set which supports uci_size number of bits for payload */ - while (pucch_resource_set_id < MAX_NB_OF_PUCCH_RESOURCE_SETS) { - if ((bwp_id>0 && - mac->ULbwp[bwp_id-1] && - mac->ULbwp[bwp_id-1]->bwp_Dedicated && - mac->ULbwp[bwp_id-1]->bwp_Dedicated->pucch_Config && - mac->ULbwp[bwp_id-1]->bwp_Dedicated->pucch_Config->choice.setup && - mac->ULbwp[bwp_id-1]->bwp_Dedicated->pucch_Config->choice.setup->resourceSetToAddModList && - mac->ULbwp[bwp_id-1]->bwp_Dedicated->pucch_Config->choice.setup->resourceSetToAddModList->list.array[pucch_resource_set_id] != NULL) || - (bwp_id==0 && - mac->cg && - mac->cg->spCellConfig && - mac->cg->spCellConfig->spCellConfigDedicated && - mac->cg->spCellConfig->spCellConfigDedicated->uplinkConfig && - mac->cg->spCellConfig->spCellConfigDedicated->uplinkConfig->initialUplinkBWP && - mac->cg->spCellConfig->spCellConfigDedicated->uplinkConfig->initialUplinkBWP->pucch_Config && - mac->cg->spCellConfig->spCellConfigDedicated->uplinkConfig->initialUplinkBWP->pucch_Config->choice.setup && - mac->cg->spCellConfig->spCellConfigDedicated->uplinkConfig->initialUplinkBWP->pucch_Config->choice.setup->resourceSetToAddModList && - mac->cg->spCellConfig->spCellConfigDedicated->uplinkConfig->initialUplinkBWP->pucch_Config->choice.setup->resourceSetToAddModList->list.array[pucch_resource_set_id] != NULL)) { - if (uci_size <= 2) { - pucch_resource_set_id = 0; - return (pucch_resource_set_id); - break; - } - else { - pucch_resource_set_id = 1; - return (pucch_resource_set_id); - break; - } - } - pucch_resource_set_id++; - } - - pucch_resource_set_id = MAX_NB_OF_PUCCH_RESOURCE_SETS; - - return (pucch_resource_set_id); -} /******************************************************************* * diff --git a/openair1/SCHED_NR_UE/pucch_uci_ue_nr.h b/openair1/SCHED_NR_UE/pucch_uci_ue_nr.h index 97d8d73282..b218cf2b38 100644 --- a/openair1/SCHED_NR_UE/pucch_uci_ue_nr.h +++ b/openair1/SCHED_NR_UE/pucch_uci_ue_nr.h @@ -58,51 +58,12 @@ #define BITS_PER_SYMBOL_BPSK (1) /* 1 bit per symbol for bpsk modulation */ #define BITS_PER_SYMBOL_QPSK (2) /* 2 bits per symbol for bpsk modulation */ -/************** VARIABLES *****************************************/ - -#define NB_SYMBOL_MINUS_FOUR (11) -#define I_PUCCH_NO_ADDITIONAL_DMRS (0) -#define I_PUCCH_ADDITIONAL_DMRS (1) -#define I_PUCCH_NO_HOPPING (0) -#define I_PUCCH_HOPING (1) - /*************** FUNCTIONS ****************************************/ -bool pucch_procedures_ue_nr(PHY_VARS_NR_UE *ue, uint8_t gNB_id, UE_nr_rxtx_proc_t *proc, bool reset_harq); - -/** \brief This function return number of downlink acknowledgement and its bitmap - @param ue context - @param gNB_id identity - @param slots for rx and tx - @param o_ACK HARQ-ACK information bits - @param n_HARQ_ACK use for obtaining a PUCCH transmission power - @param do_reset reset downlink HARQ context - @returns number of bits of o_ACK */ - -uint8_t get_downlink_ack(PHY_VARS_NR_UE *ue, uint8_t gNB_id, UE_nr_rxtx_proc_t *proc, uint32_t *o_ACK, - int *n_HARQ_ACK, bool do_reset); - -/** \brief This function selects a pucch resource - @param ue context - @param gNB_id identity - @param uci size number of uci bits - @param pucch_resource_indicator is from downlink DCI - @param initial_pucch_id pucch resource id for initial phase - @param resource_set_id pucch resource set if any - @param resource_id pucch resource id if any - @returns TRUE a pucch resource has been found FALSE no valid pucch resource */ - -boolean_t select_pucch_resource(PHY_VARS_NR_UE *ue, NR_UE_MAC_INST_t *mac, uint8_t gNB_id, int uci_size, int pucch_resource_indicator, - int *initial_pucch_id, int *resource_set_id, int *resource_id, NR_UE_HARQ_STATUS_t *harq_status); - -/** \brief This function select a pucch resource set - @param ue context - @param gNB_id identity - @param uci size number of uci bits - @returns number of the pucch resource set */ - -int find_pucch_resource_set(NR_UE_MAC_INST_t *mac, uint8_t gNB_id, int uci_size); +void pucch_procedures_ue_nr(PHY_VARS_NR_UE *ue, + uint8_t gNB_id, + UE_nr_rxtx_proc_t *proc); /** \brief This function check pucch format @param ue context diff --git a/openair1/SIMULATION/NR_PHY/dlsim.c b/openair1/SIMULATION/NR_PHY/dlsim.c index c924e28dc8..6a636003a4 100644 --- a/openair1/SIMULATION/NR_PHY/dlsim.c +++ b/openair1/SIMULATION/NR_PHY/dlsim.c @@ -996,12 +996,12 @@ int main(int argc, char **argv) NR_gNB_DLSCH_t *gNB_dlsch = gNB->dlsch[0][0]; nfapi_nr_dl_tti_pdsch_pdu_rel15_t *rel15 = &gNB_dlsch->harq_process.pdsch_pdu.pdsch_pdu_rel15; - UE_harq_process->harq_ack.ack = 0; + UE_harq_process->ack = 0; round = 0; UE_harq_process->round = round; UE_harq_process->first_tx = 1; - while ((roundharq_ack.ack==0)) { + while ((roundack==0)) { memset(RC.nrmac[0]->cce_list[1][0],0,MAX_NUM_CCE*sizeof(int)); memset(RC.nrmac[0]->cce_list[1][1],0,MAX_NUM_CCE*sizeof(int)); clear_nr_nfapi_information(RC.nrmac[0], 0, frame, slot); @@ -1230,7 +1230,7 @@ int main(int argc, char **argv) printf("errors_bit = %u (trial %d)\n", errors_bit, trial); } roundStats[snrRun]+=((float)round); - if (UE_harq_process->harq_ack.ack==1) effRate += ((float)TBS)/round; + if (UE_harq_process->ack==1) effRate += ((float)TBS)/round; } // noise trials blerStats[snrRun] = (float) n_errors / (float) n_trials; diff --git a/openair1/SIMULATION/NR_PHY/nr_dummy_functions.c b/openair1/SIMULATION/NR_PHY/nr_dummy_functions.c index 32b6b10412..629c00eea0 100644 --- a/openair1/SIMULATION/NR_PHY/nr_dummy_functions.c +++ b/openair1/SIMULATION/NR_PHY/nr_dummy_functions.c @@ -25,4 +25,5 @@ void nr_fill_rx_indication(fapi_nr_rx_indication_t *rx_ind, uint8_t gNB_id, PHY_VARS_NR_UE *ue, NR_UE_DLSCH_t *dlsch0, + NR_UE_DLSCH_t *dlsch1, uint16_t n_pdus) {} diff --git a/openair1/SIMULATION/NR_PHY/pucchsim.c b/openair1/SIMULATION/NR_PHY/pucchsim.c index 749703d230..7e2d2b9458 100644 --- a/openair1/SIMULATION/NR_PHY/pucchsim.c +++ b/openair1/SIMULATION/NR_PHY/pucchsim.c @@ -456,32 +456,8 @@ int main(int argc, char **argv) bzero(rxdataF[i],14*frame_parms->ofdm_symbol_size*sizeof(int)); } - - //configure UE - UE = malloc(sizeof(PHY_VARS_NR_UE)); - memcpy(&UE->frame_parms,frame_parms,sizeof(NR_DL_FRAME_PARMS)); - UE->pucch_config_common_nr->hoppingId = Nid_cell; - //phy_init_nr_top(UE); //called from init_nr_ue_signal - - UE->perfect_ce = 0; - - if(eps!=0.0) - UE->UE_fo_compensation = 1; // if a frequency offset is set then perform fo estimation and compensation - - if (init_nr_ue_signal(UE, 1, 0) != 0) - { - printf("Error at UE NR initialisation\n"); - exit(-1); - } uint8_t mcs=0; - startingPRB_intraSlotHopping=N_RB_DL-1; - pucch_GroupHopping_t PUCCH_GroupHopping=UE->pucch_config_common_nr->pucch_GroupHopping; - uint32_t hopping_id=UE->pucch_config_common_nr->hoppingId; - uint32_t dmrs_scrambling_id = 0, data_scrambling_id=0; - //t_nrPolar_params *currentPtr; - int shift = 0; - if(format==0){ if (sr_flag) shift = 1< 11) gNB->uci_polarParams = nr_polar_params(2, nr_bit, nrofPRB, 1, NULL); + startingPRB_intraSlotHopping=N_RB_DL-1; + uint32_t hopping_id=Nid_cell; + uint32_t dmrs_scrambling_id = 0, data_scrambling_id=0; + + //configure UE + UE = malloc(sizeof(PHY_VARS_NR_UE)); + memcpy(&UE->frame_parms,frame_parms,sizeof(NR_DL_FRAME_PARMS)); + + fapi_nr_ul_config_pucch_pdu pucch_tx_pdu; + if (format==0) { + pucch_tx_pdu.format_type = 0; + pucch_tx_pdu.nr_of_symbols = nrofSymbols; + pucch_tx_pdu.start_symbol_index = startingSymbolIndex; + pucch_tx_pdu.bwp_start = 0; + pucch_tx_pdu.prb_start = startingPRB; + pucch_tx_pdu.hopping_id = hopping_id; + pucch_tx_pdu.group_hop_flag = 0; + pucch_tx_pdu.sequence_hop_flag = 0; + pucch_tx_pdu.freq_hop_flag = 0; + pucch_tx_pdu.mcs = mcs; + pucch_tx_pdu.initial_cyclic_shift = 0; + pucch_tx_pdu.second_hop_prb = startingPRB_intraSlotHopping; + } + if (format==2) { + pucch_tx_pdu.format_type = 2; + pucch_tx_pdu.rnti = 0x1234; + pucch_tx_pdu.n_bit = nr_bit; + pucch_tx_pdu.payload = actual_payload; + pucch_tx_pdu.nr_of_symbols = nrofSymbols; + pucch_tx_pdu.start_symbol_index = startingSymbolIndex; + pucch_tx_pdu.bwp_start = 0; + pucch_tx_pdu.prb_start = startingPRB; + pucch_tx_pdu.hopping_id = hopping_id; + pucch_tx_pdu.group_hop_flag = 0; + pucch_tx_pdu.sequence_hop_flag = 0; + pucch_tx_pdu.freq_hop_flag = 0; + pucch_tx_pdu.dmrs_scrambling_id = dmrs_scrambling_id; + pucch_tx_pdu.data_scrambling_id = data_scrambling_id; + pucch_tx_pdu.second_hop_prb = startingPRB_intraSlotHopping; + } + + UE->perfect_ce = 0; + + if(eps!=0.0) + UE->UE_fo_compensation = 1; // if a frequency offset is set then perform fo estimation and compensation + + if (init_nr_ue_signal(UE, 1, 0) != 0) + { + printf("Error at UE NR initialisation\n"); + exit(-1); + } + + pucch_GroupHopping_t PUCCH_GroupHopping = pucch_tx_pdu.group_hop_flag + (pucch_tx_pdu.sequence_hop_flag<<1); + + //t_nrPolar_params *currentPtr; + for(SNR=snr0;SNR<=snr1;SNR=SNR+1){ ack_nack_errors=0; sr_errors=0; @@ -502,13 +534,28 @@ int main(int argc, char **argv) for (trial=0; trialofdm_symbol_size*sizeof(int)); if(format==0){ - nr_generate_pucch0(UE,txdataF,frame_parms,PUCCH_GroupHopping,hopping_id,amp,nr_slot_tx,m0,mcs,nrofSymbols,startingSymbolIndex,startingPRB, 0); + nr_generate_pucch0(UE, + txdataF, + frame_parms, + amp, + nr_slot_tx, + &pucch_tx_pdu); } else if (format == 1){ - nr_generate_pucch1(UE,txdataF,frame_parms,UE->pucch_config_dedicated,actual_payload,amp,nr_slot_tx,m0,nrofSymbols,startingSymbolIndex,startingPRB,startingPRB_intraSlotHopping,0,nr_bit); + nr_generate_pucch1(UE, + txdataF, + frame_parms, + amp, + nr_slot_tx, + &pucch_tx_pdu); } else { - nr_generate_pucch2(UE,0x1234,dmrs_scrambling_id,data_scrambling_id,txdataF,frame_parms,UE->pucch_config_dedicated,actual_payload,amp,nr_slot_tx,nrofSymbols,startingSymbolIndex,nrofPRB,startingPRB,nr_bit); + nr_generate_pucch2(UE, + txdataF, + frame_parms, + amp, + nr_slot_tx, + &pucch_tx_pdu); } int txlev = signal_energy(&txdataF[aa][startingSymbolIndex*frame_parms->ofdm_symbol_size], diff --git a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c index 7004cf7aaf..cb5ee8fee3 100644 --- a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c +++ b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c @@ -3537,6 +3537,83 @@ void get_type0_PDCCH_CSS_config_parameters(NR_Type0_PDCCH_CSS_config_t *type0_PD } +uint16_t compute_pucch_prb_size(uint8_t format, + uint8_t nr_prbs, + uint16_t O_tot, + uint16_t O_csi, + NR_PUCCH_MaxCodeRate_t *maxCodeRate, + uint8_t Qm, + uint8_t n_symb, + uint8_t n_re_ctrl) { + + uint16_t O_crc; + + if (O_tot<12) + O_crc = 0; + else{ + if (O_tot<20) + O_crc = 6; + else { + if (O_tot<360) + O_crc = 11; + else + AssertFatal(1==0,"Case for segmented PUCCH not yet implemented"); + } + } + + int rtimes100; + switch(*maxCodeRate){ + case NR_PUCCH_MaxCodeRate_zeroDot08 : + rtimes100 = 8; + break; + case NR_PUCCH_MaxCodeRate_zeroDot15 : + rtimes100 = 15; + break; + case NR_PUCCH_MaxCodeRate_zeroDot25 : + rtimes100 = 25; + break; + case NR_PUCCH_MaxCodeRate_zeroDot35 : + rtimes100 = 35; + break; + case NR_PUCCH_MaxCodeRate_zeroDot45 : + rtimes100 = 45; + break; + case NR_PUCCH_MaxCodeRate_zeroDot60 : + rtimes100 = 60; + break; + case NR_PUCCH_MaxCodeRate_zeroDot80 : + rtimes100 = 80; + break; + default : + AssertFatal(1==0,"Invalid MaxCodeRate"); + } + + float r = (float)rtimes100/100; + + if (O_csi == O_tot) { + if ((O_tot+O_csi)>(nr_prbs*n_re_ctrl*n_symb*Qm*r)) + AssertFatal(1==0,"MaxCodeRate %.2f can't support %d UCI bits and %d CRC bits with %d PRBs", + r,O_tot,O_crc,nr_prbs); + else + return nr_prbs; + } + + if (format==2){ + // TODO fix this for multiple CSI reports + for (int i=1; i<=nr_prbs; i++){ + if((O_tot+O_crc)<=(i*n_symb*Qm*n_re_ctrl*r) && + (O_tot+O_crc)>((i-1)*n_symb*Qm*n_re_ctrl*r)) + return i; + } + AssertFatal(1==0,"MaxCodeRate %.2f can't support %d UCI bits and %d CRC bits with at most %d PRBs", + r,O_tot,O_crc,nr_prbs); + } + else{ + AssertFatal(1==0,"Not yet implemented"); + } +} + + /* extract UL PTRS values from RRC and validate it based upon 38.214 6.2.3 */ bool set_ul_ptrs_values(NR_PTRS_UplinkConfig_t *ul_ptrs_config, uint16_t rbSize,uint8_t mcsIndex, uint8_t mcsTable, diff --git a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h index c6cb0341ac..cb3d25352b 100644 --- a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h +++ b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h @@ -139,6 +139,15 @@ void get_type0_PDCCH_CSS_config_parameters(NR_Type0_PDCCH_CSS_config_t *type0_PD uint16_t get_ssb_start_symbol(const long band, NR_SubcarrierSpacing_t scs, int i_ssb); +uint16_t compute_pucch_prb_size(uint8_t format, + uint8_t nr_prbs, + uint16_t O_tot, + uint16_t O_csi, + NR_PUCCH_MaxCodeRate_t *maxCodeRate, + uint8_t Qm, + uint8_t n_symb, + uint8_t n_re_ctrl); + int16_t get_N_RA_RB (int delta_f_RA_PRACH,int delta_f_PUSCH); bool set_dl_ptrs_values(NR_PTRS_DownlinkConfig_t *ptrs_config, diff --git a/openair2/LAYER2/NR_MAC_UE/mac_defs.h b/openair2/LAYER2/NR_MAC_UE/mac_defs.h index 2e97e2fa9a..f5953e7845 100755 --- a/openair2/LAYER2/NR_MAC_UE/mac_defs.h +++ b/openair2/LAYER2/NR_MAC_UE/mac_defs.h @@ -302,6 +302,20 @@ typedef struct { } RA_config_t; +typedef struct { + bool active; + bool ack_received; + uint8_t pucch_resource_indicator; + uint16_t feedback_to_ul; + frame_t dl_frame; + int dl_slot; + uint8_t ack; + uint8_t dai; + int n_CCE; + int N_CCE; + int8_t delta_pucch; +} NR_UE_HARQ_STATUS_t; + typedef struct { uint8_t freq_hopping; @@ -311,11 +325,27 @@ typedef struct { } RAR_grant_t; +typedef struct { + int n_HARQ_ACK; + uint32_t ack_payload; + uint8_t sr_payload; + uint32_t csi_part1_payload; + uint32_t csi_part2_payload; + int resource_indicator; + int resource_set_id; + int initial_pucch_id; + NR_PUCCH_Resource_t *pucch_resource; + int n_CCE; + int N_CCE; + int8_t delta_pucch; +} PUCCH_sched_t; + + /*!\brief Top level UE MAC structure */ typedef struct { NR_ServingCellConfigCommon_t *scc; - NR_ServingCellConfigCommonSIB_t *scc_SIB; + NR_ServingCellConfigCommonSIB_t *scc_SIB; NR_CellGroupConfig_t *cg; int servCellIndex; NR_CSI_ReportConfig_t *csirc; @@ -391,6 +421,8 @@ typedef struct { dci_pdu_rel15_t def_dci_pdu_rel15[8]; + NR_UE_HARQ_STATUS_t dl_harq_info[16]; + } NR_UE_MAC_INST_t; typedef enum seach_space_mask_e { diff --git a/openair2/LAYER2/NR_MAC_UE/mac_proto.h b/openair2/LAYER2/NR_MAC_UE/mac_proto.h index 2d00aa0003..328a931add 100755 --- a/openair2/LAYER2/NR_MAC_UE/mac_proto.h +++ b/openair2/LAYER2/NR_MAC_UE/mac_proto.h @@ -37,6 +37,9 @@ #include "PHY/defs_nr_UE.h" #include "RRC/NR_UE/rrc_defs.h" +#define NR_DL_MAX_DAI (4) /* TS 38.213 table 9.1.3-1 Value of counter DAI for DCI format 1_0 and 1_1 */ +#define NR_DL_MAX_NB_CW (2) /* number of downlink code word */ + /**\brief decode mib pdu in NR_UE, from if_module ul_ind with P7 tx_ind message \param module_id module id \param cc_id component carrier id @@ -135,7 +138,7 @@ uint32_t ue_get_SR(module_id_t module_idP, int CC_id, frame_t frameP, int8_t nr_ue_get_SR(module_id_t module_idP, int CC_id, frame_t frameP, uint8_t eNB_id, uint16_t rnti, sub_frame_t subframe); -int8_t nr_ue_process_dci(module_id_t module_id, int cc_id, uint8_t gNB_index, frame_t frame, int slot, dci_pdu_rel15_t *dci, uint16_t rnti, uint8_t dci_format); +int8_t nr_ue_process_dci(module_id_t module_id, int cc_id, uint8_t gNB_index, frame_t frame, int slot, dci_pdu_rel15_t *dci, fapi_nr_dci_indication_pdu_t *dci_ind); int nr_ue_process_dci_indication_pdu(module_id_t module_id, int cc_id, int gNB_index, frame_t frame, int slot, fapi_nr_dci_indication_pdu_t *dci); uint32_t get_ssb_frame(uint32_t test); @@ -197,6 +200,58 @@ int set_tdd_config_nr_ue(fapi_nr_config_request_t *cfg, int mu, int nrofDownlinkSlots, int nrofDownlinkSymbols, int nrofUplinkSlots, int nrofUplinkSymbols); +void set_harq_status(NR_UE_MAC_INST_t *mac, + uint8_t pucch_id, + uint8_t harq_id, + int8_t delta_pucch, + uint8_t data_toul_fb, + uint8_t dai, + int n_CCE, + int N_CCE, + frame_t frame, + int slot); + +void update_harq_status(nr_downlink_indication_t *dl_info, + int pdu_id); + +uint8_t get_downlink_ack(NR_UE_MAC_INST_t *mac, + frame_t frame, + int slot, + PUCCH_sched_t *pucch); + +int find_pucch_resource_set(NR_UE_MAC_INST_t *mac, int uci_size); + +void select_pucch_resource(NR_UE_MAC_INST_t *mac, + PUCCH_sched_t *pucch); + +int16_t get_pucch_tx_power_ue(NR_UE_MAC_INST_t *mac, + NR_PUCCH_Config_t *pucch_Config, + PUCCH_sched_t *pucch, + uint8_t format_type, + uint16_t nb_of_prbs, + uint8_t freq_hop_flag, + uint8_t add_dmrs_flag, + uint8_t N_symb_PUCCH, + int subframe_number, + int O_ACK, int O_SR, + int O_CSI, int O_CRC); + +int get_deltatf(uint16_t nb_of_prbs, + uint8_t N_symb_PUCCH, + uint8_t freq_hop_flag, + uint8_t add_dmrs_flag, + int N_sc_ctrl_RB, + int n_HARQ_ACK, + int O_ACK, int O_SR, + int O_CSI, int O_CRC); + +void nr_ue_configure_pucch(NR_UE_MAC_INST_t *mac, + int slot, + uint16_t rnti, + PUCCH_sched_t *pucch, + fapi_nr_ul_config_pucch_pdu *pucch_pdu, + int O_SR, int O_ACK, int O_CSI); + /** \brief Function for UE/PHY to compute PUSCH transmit power in power-control procedure. @param Mod_id Module id of UE @returns Po_NOMINAL_PUSCH (PREAMBLE_RECEIVED_TARGET_POWER+DELTA_PREAMBLE @@ -226,6 +281,7 @@ and fills the PRACH PDU per each FD occasion. @returns void */ void nr_ue_prach_scheduler(module_id_t module_idP, frame_t frameP, sub_frame_t slotP, int thread_id); +void nr_ue_pucch_scheduler(module_id_t module_idP, frame_t frameP, int slotP, int thread_id); /* \brief This function schedules the Msg3 transmission @param diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c index e2971628ea..753e1577a0 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c @@ -68,6 +68,72 @@ extern uint32_t N_RB_DL; +/* TS 38.213 9.2.5.2 UE procedure for multiplexing HARQ-ACK/SR and CSI in a PUCCH */ +/* this is a counter of number of pucch format 4 per subframe */ +static int nb_pucch_format_4_in_subframes[LTE_NUMBER_OF_SUBFRAMES_PER_FRAME] = { 0 } ; + +/* 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 */ +/* Sequence cyclic shift */ = { 0, 6 }; + +/* TS 36.213 Table 9.2.5-1: Mapping of values for one HARQ-ACK bit and positive SR to sequences */ +static const int sequence_cyclic_shift_1_harq_ack_bit_positive_sr[2] +/* HARQ-ACK Value 0 1 */ +/* Sequence cyclic shift */ = { 3, 9 }; + +/* TS 36.213 Table 9.2.5-2: Mapping of values for two HARQ-ACK bits and positive SR to sequences */ +static const int sequence_cyclic_shift_2_harq_ack_bits_positive_sr[4] +/* HARQ-ACK Value (0,0) (0,1) (1,0) (1,1) */ +/* Sequence cyclic shift */ = { 1, 4, 10, 7 }; + +/* TS 38.213 Table 9.2.3-4: Mapping of values for two HARQ-ACK bits to sequences */ +static const int sequence_cyclic_shift_2_harq_ack_bits[4] +/* HARQ-ACK Value (0,0) (0,1) (1,0) (1,1) */ +/* Sequence cyclic shift */ = { 0, 3, 9, 6 }; + + +/* TS 38.211 Table 6.4.1.3.3.2-1: DM-RS positions for PUCCH format 3 and 4 */ +static const int nb_symbols_excluding_dmrs[11][2][2] += { +/* No additional DMRS Additional DMRS */ +/* PUCCH length No hopping hopping No hopping hopping */ +/* index 0 1 0 1 */ +/* 4 */ {{ 3 , 2 } , { 3 , 2 }}, +/* 5 */ {{ 3 , 3 } , { 3 , 3 }}, +/* 6 */ {{ 4 , 4 } , { 4 , 4 }}, +/* 7 */ {{ 5 , 5 } , { 5 , 5 }}, +/* 8 */ {{ 6 , 6 } , { 6 , 6 }}, +/* 9 */ {{ 7 , 7 } , { 7 , 7 }}, +/* 10 */ {{ 8 , 8 } , { 6 , 6 }}, +/* 11 */ {{ 9 , 9 } , { 7 , 7 }}, +/* 12 */ {{ 10 , 10 } , { 8 , 8 }}, +/* 13 */ {{ 11 , 11 } , { 9 , 9 }}, +/* 14 */ {{ 12 , 12 } , { 10 , 10 }}, +}; + +/* TS 36.213 Table 9.2.1-1: PUCCH resource sets before dedicated PUCCH resource configuration */ +const initial_pucch_resource_t initial_pucch_resource[16] = { +/* format first symbol Number of symbols PRB offset nb index for set of initial CS */ +/* 0 */ { 0, 12, 2, 0, 2, { 0, 3, 0, 0 } }, +/* 1 */ { 0, 12, 2, 0, 3, { 0, 4, 8, 0 } }, +/* 2 */ { 0, 12, 2, 3, 3, { 0, 4, 8, 0 } }, +/* 3 */ { 1, 10, 4, 0, 2, { 0, 6, 0, 0 } }, +/* 4 */ { 1, 10, 4, 0, 4, { 0, 3, 6, 9 } }, +/* 5 */ { 1, 10, 4, 2, 4, { 0, 3, 6, 9 } }, +/* 6 */ { 1, 10, 4, 4, 4, { 0, 3, 6, 9 } }, +/* 7 */ { 1, 4, 10, 0, 2, { 0, 6, 0, 0 } }, +/* 8 */ { 1, 4, 10, 0, 4, { 0, 3, 6, 9 } }, +/* 9 */ { 1, 4, 10, 2, 4, { 0, 3, 6, 9 } }, +/* 10 */ { 1, 4, 10, 4, 4, { 0, 3, 6, 9 } }, +/* 11 */ { 1, 0, 14, 0, 2, { 0, 6, 0, 0 } }, +/* 12 */ { 1, 0, 14, 0, 4, { 0, 3, 6, 9 } }, +/* 13 */ { 1, 0, 14, 2, 4, { 0, 3, 6, 9 } }, +/* 14 */ { 1, 0, 14, 4, 4, { 0, 3, 6, 9 } }, +/* 15 */ { 1, 0, 14, 0, 4, { 0, 3, 6, 9 } }, +}; + + int get_rnti_type(NR_UE_MAC_INST_t *mac, uint16_t rnti){ RA_config_t *ra = &mac->ra; @@ -434,11 +500,13 @@ int nr_ue_process_dci_indication_pdu(module_id_t module_id,int cc_id, int gNB_in int8_t ret = nr_extract_dci_info(mac, dci->dci_format, dci->payloadSize, dci->rnti, (uint64_t *)dci->payloadBits, def_dci_pdu_rel15); if ((ret&1) == 1) return -1; else if (ret == 2) dci->dci_format = NR_UL_DCI_FORMAT_0_0; - return (nr_ue_process_dci(module_id, cc_id, gNB_index, frame, slot, def_dci_pdu_rel15, dci->rnti, dci->dci_format)); + return (nr_ue_process_dci(module_id, cc_id, gNB_index, frame, slot, def_dci_pdu_rel15, dci)); } -int8_t nr_ue_process_dci(module_id_t module_id, int cc_id, uint8_t gNB_index, frame_t frame, int slot, dci_pdu_rel15_t *dci, uint16_t rnti, uint8_t dci_format){ +int8_t nr_ue_process_dci(module_id_t module_id, int cc_id, uint8_t gNB_index, frame_t frame, int slot, dci_pdu_rel15_t *dci, fapi_nr_dci_indication_pdu_t *dci_ind) { + uint16_t rnti = dci_ind->rnti; + uint8_t dci_format = dci_ind->dci_format; int ret = 0; int pucch_res_set_cnt = 0, valid = 0; frame_t frame_tx = 0; @@ -698,8 +766,6 @@ int8_t nr_ue_process_dci(module_id_t module_id, int cc_id, uint8_t gNB_index, fr dlsch_config_pdu_1_0->rv = dci->rv; /* HARQ_PROCESS_NUMBER (only if CRC scrambled by C-RNTI or CS-RNTI or new-RNTI or TC-RNTI)*/ dlsch_config_pdu_1_0->harq_process_nbr = dci->harq_pid; - /* DAI (only if CRC scrambled by C-RNTI or CS-RNTI or new-RNTI or TC-RNTI)*/ - dlsch_config_pdu_1_0->dai = dci->dai[0].val; /* TB_SCALING (only if CRC scrambled by P-RNTI or RA-RNTI) */ // according to TS 38.214 Table 5.1.3.2-3 if (dci->tb_scaling == 0) dlsch_config_pdu_1_0->scaling_factor_S = 1; @@ -712,16 +778,6 @@ int8_t nr_ue_process_dci(module_id_t module_id, int cc_id, uint8_t gNB_index, fr if (dci->tpc == 1) dlsch_config_pdu_1_0->accumulated_delta_PUCCH = 0; if (dci->tpc == 2) dlsch_config_pdu_1_0->accumulated_delta_PUCCH = 1; if (dci->tpc == 3) dlsch_config_pdu_1_0->accumulated_delta_PUCCH = 3; - /* PUCCH_RESOURCE_IND (only if CRC scrambled by C-RNTI or CS-RNTI or new-RNTI)*/ - //if (dci->pucch_resource_indicator == 0) dlsch_config_pdu_1_0->pucch_resource_id = 1; //pucch-ResourceId obtained from the 1st value of resourceList FIXME!!! - //if (dci->pucch_resource_indicator == 1) dlsch_config_pdu_1_0->pucch_resource_id = 2; //pucch-ResourceId obtained from the 2nd value of resourceList FIXME!! - //if (dci->pucch_resource_indicator == 2) dlsch_config_pdu_1_0->pucch_resource_id = 3; //pucch-ResourceId obtained from the 3rd value of resourceList FIXME!! - //if (dci->pucch_resource_indicator == 3) dlsch_config_pdu_1_0->pucch_resource_id = 4; //pucch-ResourceId obtained from the 4th value of resourceList FIXME!! - //if (dci->pucch_resource_indicator == 4) dlsch_config_pdu_1_0->pucch_resource_id = 5; //pucch-ResourceId obtained from the 5th value of resourceList FIXME!! - //if (dci->pucch_resource_indicator == 5) dlsch_config_pdu_1_0->pucch_resource_id = 6; //pucch-ResourceId obtained from the 6th value of resourceList FIXME!! - //if (dci->pucch_resource_indicator == 6) dlsch_config_pdu_1_0->pucch_resource_id = 7; //pucch-ResourceId obtained from the 7th value of resourceList FIXME!! - //if (dci->pucch_resource_indicator == 7) dlsch_config_pdu_1_0->pucch_resource_id = 8; //pucch-ResourceId obtained from the 8th value of resourceList FIXME!! - dlsch_config_pdu_1_0->pucch_resource_id = dci->pucch_resource_indicator; // Sanity check for pucch_resource_indicator value received to check for false DCI. valid = 0; if (mac->ULbwp[0] && @@ -731,7 +787,7 @@ int8_t nr_ue_process_dci(module_id_t module_id, int cc_id, uint8_t gNB_index, fr mac->ULbwp[0]->bwp_Dedicated->pucch_Config->choice.setup->resourceSetToAddModList) { pucch_res_set_cnt = mac->ULbwp[0]->bwp_Dedicated->pucch_Config->choice.setup->resourceSetToAddModList->list.count; for (int id = 0; id < pucch_res_set_cnt; id++) { - if (dlsch_config_pdu_1_0->pucch_resource_id < mac->ULbwp[0]->bwp_Dedicated->pucch_Config->choice.setup->resourceSetToAddModList->list.array[id]->resourceList.list.count) { + if (dci->pucch_resource_indicator < mac->ULbwp[0]->bwp_Dedicated->pucch_Config->choice.setup->resourceSetToAddModList->list.array[id]->resourceList.list.count) { valid = 1; break; } @@ -747,19 +803,25 @@ int8_t nr_ue_process_dci(module_id_t module_id, int cc_id, uint8_t gNB_index, fr mac->cg->spCellConfig->spCellConfigDedicated->uplinkConfig->initialUplinkBWP->pucch_Config->choice.setup->resourceSetToAddModList){ pucch_res_set_cnt = mac->cg->spCellConfig->spCellConfigDedicated->uplinkConfig->initialUplinkBWP->pucch_Config->choice.setup->resourceSetToAddModList->list.count; for (int id = 0; id < pucch_res_set_cnt; id++) { - if (dlsch_config_pdu_1_0->pucch_resource_id < mac->cg->spCellConfig->spCellConfigDedicated->uplinkConfig->initialUplinkBWP->pucch_Config->choice.setup->resourceSetToAddModList->list.array[id]->resourceList.list.count) { + if (dci->pucch_resource_indicator < mac->cg->spCellConfig->spCellConfigDedicated->uplinkConfig->initialUplinkBWP->pucch_Config->choice.setup->resourceSetToAddModList->list.array[id]->resourceList.list.count) { valid = 1; break; } } } else valid=1; if (!valid) { - LOG_W(MAC, "[%d.%d] pucch_resource_indicator value %d is out of bounds. Possibly due to false DCI. Ignoring DCI!\n", frame, slot, dlsch_config_pdu_1_0->pucch_resource_id); + LOG_W(MAC, "[%d.%d] pucch_resource_indicator value %d is out of bounds. Possibly due to false DCI. Ignoring DCI!\n", frame, slot, dci->pucch_resource_indicator); return -1; } - /* PDSCH_TO_HARQ_FEEDBACK_TIME_IND (only if CRC scrambled by C-RNTI or CS-RNTI or new-RNTI)*/ - dlsch_config_pdu_1_0->pdsch_to_harq_feedback_time_ind = 1+dci->pdsch_to_harq_feedback_timing_indicator.val; + // set the harq status at MAC for feedback + set_harq_status(mac,dci->pucch_resource_indicator, + dci->harq_pid, + dlsch_config_pdu_1_0->accumulated_delta_PUCCH, + 1+dci->pdsch_to_harq_feedback_timing_indicator.val, + dci->dai[0].val, + dci_ind->n_CCE,dci_ind->N_CCE, + frame,slot); LOG_D(MAC,"(nr_ue_procedures.c) rnti = %x dl_config->number_pdus = %d\n", dl_config->dl_config_list[dl_config->number_pdus].dlsch_config_pdu.rnti, @@ -778,11 +840,11 @@ int8_t nr_ue_process_dci(module_id_t module_id, int cc_id, uint8_t gNB_index, fr dlsch_config_pdu_1_0->ndi, dlsch_config_pdu_1_0->rv, dlsch_config_pdu_1_0->harq_process_nbr, - dlsch_config_pdu_1_0->dai, + dci->dai[0].val, dlsch_config_pdu_1_0->scaling_factor_S, dlsch_config_pdu_1_0->accumulated_delta_PUCCH, - dlsch_config_pdu_1_0->pucch_resource_id, - dlsch_config_pdu_1_0->pdsch_to_harq_feedback_time_ind); + dci->pucch_resource_indicator, + 1+dci->pdsch_to_harq_feedback_timing_indicator.val); // dl_config->dl_config_list[dl_config->number_pdus].dci_config_pdu.dci_config_rel15.N_RB_BWP = n_RB_DLBWP; @@ -901,36 +963,27 @@ int8_t nr_ue_process_dci(module_id_t module_id, int cc_id, uint8_t gNB_index, fr dlsch_config_pdu_1_1->tb2_rv = dci->rv2.val; /* HARQ_PROCESS_NUMBER */ dlsch_config_pdu_1_1->harq_process_nbr = dci->harq_pid; - /* DAI */ - dlsch_config_pdu_1_1->dai = dci->dai[0].val; /* TPC_PUCCH */ // according to TS 38.213 Table 7.2.1-1 if (dci->tpc == 0) dlsch_config_pdu_1_1->accumulated_delta_PUCCH = -1; if (dci->tpc == 1) dlsch_config_pdu_1_1->accumulated_delta_PUCCH = 0; if (dci->tpc == 2) dlsch_config_pdu_1_1->accumulated_delta_PUCCH = 1; if (dci->tpc == 3) dlsch_config_pdu_1_1->accumulated_delta_PUCCH = 3; - /* PUCCH_RESOURCE_IND */ - dlsch_config_pdu_1_1->pucch_resource_id = dci->pucch_resource_indicator; + // Sanity check for pucch_resource_indicator value received to check for false DCI. valid = 0; pucch_res_set_cnt = mac->ULbwp[0]->bwp_Dedicated->pucch_Config->choice.setup->resourceSetToAddModList->list.count; for (int id = 0; id < pucch_res_set_cnt; id++) { - if (dlsch_config_pdu_1_1->pucch_resource_id < mac->ULbwp[0]->bwp_Dedicated->pucch_Config->choice.setup->resourceSetToAddModList->list.array[id]->resourceList.list.count) { + if (dci->pucch_resource_indicator < mac->ULbwp[0]->bwp_Dedicated->pucch_Config->choice.setup->resourceSetToAddModList->list.array[id]->resourceList.list.count) { valid = 1; break; } } if (!valid) { - LOG_W(MAC, "[%d.%d] pucch_resource_indicator value %d is out of bounds. Possibly due to false DCI. Ignoring DCI!\n", frame, slot, dlsch_config_pdu_1_1->pucch_resource_id); + LOG_W(MAC, "[%d.%d] pucch_resource_indicator value %d is out of bounds. Possibly due to false DCI. Ignoring DCI!\n", frame, slot, dci->pucch_resource_indicator); return -1; } - /* PDSCH_TO_HARQ_FEEDBACK_TIME_IND */ - // according to TS 38.213 Table 9.2.3-1 - NR_BWP_Id_t ul_bwp_id = mac->UL_BWP_Id; - dlsch_config_pdu_1_1->pdsch_to_harq_feedback_time_ind = - mac->ULbwp[ul_bwp_id-1]->bwp_Dedicated->pucch_Config->choice.setup->dl_DataToUL_ACK->list.array[dci->pdsch_to_harq_feedback_timing_indicator.val][0]; - /* ANTENNA_PORTS */ uint8_t n_codewords = 1; // FIXME!!! long *max_length = NULL; @@ -1033,7 +1086,22 @@ int8_t nr_ue_process_dci(module_id_t module_id, int cc_id, uint8_t gNB_index, fr //FIXME!!! // dl_config->dl_config_list[dl_config->number_pdus].dci_config_pdu.dci_config_rel15.N_RB_BWP = n_RB_DLBWP; - + + /* PDSCH_TO_HARQ_FEEDBACK_TIME_IND */ + // according to TS 38.213 Table 9.2.3-1 + NR_BWP_Id_t ul_bwp_id = mac->UL_BWP_Id; + uint8_t feedback_ti = + mac->ULbwp[ul_bwp_id-1]->bwp_Dedicated->pucch_Config->choice.setup->dl_DataToUL_ACK->list.array[dci->pdsch_to_harq_feedback_timing_indicator.val][0]; + + // set the harq status at MAC for feedback + set_harq_status(mac,dci->pucch_resource_indicator, + dci->harq_pid, + dlsch_config_pdu_1_1->accumulated_delta_PUCCH, + feedback_ti, + dci->dai[0].val, + dci_ind->n_CCE,dci_ind->N_CCE, + frame,slot); + dl_config->dl_config_list[dl_config->number_pdus].pdu_type = FAPI_NR_DL_CONFIG_TYPE_DLSCH; LOG_D(MAC,"(nr_ue_procedures.c) pdu_type=%d\n\n",dl_config->dl_config_list[dl_config->number_pdus].pdu_type); @@ -1093,6 +1161,843 @@ int8_t nr_ue_process_dci(module_id_t module_id, int cc_id, uint8_t gNB_index, fr } +void set_harq_status(NR_UE_MAC_INST_t *mac, + uint8_t pucch_id, + uint8_t harq_id, + int8_t delta_pucch, + uint8_t data_toul_fb, + uint8_t dai, + int n_CCE, + int N_CCE, + frame_t frame, + int slot) { + + NR_UE_HARQ_STATUS_t *current_harq = &mac->dl_harq_info[harq_id]; + + current_harq->active = true; + current_harq->ack_received = false; + current_harq->pucch_resource_indicator = pucch_id; + current_harq->feedback_to_ul = data_toul_fb; + current_harq->dai = dai; + current_harq->n_CCE = n_CCE; + current_harq->N_CCE = N_CCE; + current_harq->delta_pucch = delta_pucch; + // FIXME k0 != 0 currently not taken into consideration + current_harq->dl_frame = frame; + current_harq->dl_slot = slot; + +} + + +void update_harq_status(nr_downlink_indication_t *dl_info, int pdu_id) { + + NR_UE_MAC_INST_t *mac = get_mac_inst(dl_info->module_id); + uint8_t harq_pid = dl_info->rx_ind->rx_indication_body[pdu_id].pdsch_pdu.harq_pid; + NR_UE_HARQ_STATUS_t *current_harq = &mac->dl_harq_info[harq_pid]; + + if (current_harq->active) { + current_harq->ack = dl_info->rx_ind->rx_indication_body[pdu_id].pdsch_pdu.ack_nack; + current_harq->ack_received = true; + } + else { + //shouldn't get here + LOG_E(MAC, "Trying to process acknack for an inactive harq process (%d)\n", harq_pid); + } +} + + +void nr_ue_configure_pucch(NR_UE_MAC_INST_t *mac, + int slot, + uint16_t rnti, + PUCCH_sched_t *pucch, + fapi_nr_ul_config_pucch_pdu *pucch_pdu, + int O_SR, int O_ACK, int O_CSI) { + + int O_CRC = 0; //FIXME + uint16_t O_uci = O_CSI + O_ACK; + NR_BWP_Id_t bwp_id = mac->UL_BWP_Id; + NR_PUCCH_FormatConfig_t *pucchfmt; + long *pusch_id = NULL; + long *id0 = NULL; + int scs; + NR_BWP_UplinkCommon_t *initialUplinkBWP; + if (mac->scc) initialUplinkBWP = mac->scc->uplinkConfigCommon->initialUplinkBWP; + else initialUplinkBWP = &mac->scc_SIB->uplinkConfigCommon->initialUplinkBWP; + NR_BWP_Uplink_t *ubwp = mac->ULbwp[0]; + if (mac->cg && ubwp && + mac->cg->spCellConfig && + mac->cg->spCellConfig->spCellConfigDedicated && + mac->cg->spCellConfig->spCellConfigDedicated->uplinkConfig && + mac->cg->spCellConfig->spCellConfigDedicated->uplinkConfig->initialUplinkBWP) { + scs = ubwp->bwp_Common->genericParameters.subcarrierSpacing; + } + else + scs = initialUplinkBWP->genericParameters.subcarrierSpacing; + + int subframe_number = slot / (nr_slots_per_frame[scs]/10); + nb_pucch_format_4_in_subframes[subframe_number] = 0; + + pucch_pdu->rnti = rnti; + + // configure pucch from Table 9.2.1-1 + if (pucch->initial_pucch_id > -1 && + pucch->pucch_resource == NULL) { + + pucch_pdu->format_type = initial_pucch_resource[pucch->initial_pucch_id].format; + pucch_pdu->start_symbol_index = initial_pucch_resource[pucch->initial_pucch_id].startingSymbolIndex; + pucch_pdu->nr_of_symbols = initial_pucch_resource[pucch->initial_pucch_id].nrofSymbols; + + pucch_pdu->bwp_size = NRRIV2BW(mac->scc_SIB->uplinkConfigCommon->initialUplinkBWP.genericParameters.locationAndBandwidth, + MAX_BWP_SIZE); + pucch_pdu->bwp_start = NRRIV2PRBOFFSET(mac->scc_SIB->uplinkConfigCommon->initialUplinkBWP.genericParameters.locationAndBandwidth, + MAX_BWP_SIZE); + + pucch_pdu->prb_size = 1; // format 0 or 1 + int RB_BWP_offset; + if (pucch->initial_pucch_id == 15) + RB_BWP_offset = pucch_pdu->bwp_size>>2; + else + RB_BWP_offset = initial_pucch_resource[pucch->initial_pucch_id].PRB_offset; + + int N_CS = initial_pucch_resource[pucch->initial_pucch_id].nb_CS_indexes; + pucch_pdu->prb_start = RB_BWP_offset + (pucch->initial_pucch_id/N_CS); + if (pucch->initial_pucch_id>>3 == 0) { + pucch_pdu->second_hop_prb = pucch_pdu->bwp_size - 1 - RB_BWP_offset - (pucch->initial_pucch_id/N_CS); + pucch_pdu->initial_cyclic_shift = initial_pucch_resource[pucch->initial_pucch_id].initial_CS_indexes[pucch->initial_pucch_id%N_CS]; + } + else { + pucch_pdu->second_hop_prb = pucch_pdu->bwp_size - 1 - RB_BWP_offset - ((pucch->initial_pucch_id - 8)/N_CS); + pucch_pdu->initial_cyclic_shift = initial_pucch_resource[pucch->initial_pucch_id].initial_CS_indexes[(pucch->initial_pucch_id - 8)%N_CS]; + } + pucch_pdu->freq_hop_flag = 1; + pucch_pdu->time_domain_occ_idx = 0; + } + else if (pucch->pucch_resource != NULL) { + + NR_PUCCH_Resource_t *pucchres = pucch->pucch_resource; + + if (mac->cg && + mac->cg->physicalCellGroupConfig && + (mac->cg->physicalCellGroupConfig->harq_ACK_SpatialBundlingPUCCH != NULL || + mac->cg->physicalCellGroupConfig->pdsch_HARQ_ACK_Codebook != 1)) { + LOG_E(PHY,"PUCCH Unsupported cell group configuration : at line %d in function %s of file %s \n", LINE_FILE , __func__, FILE_NAME); + return; + } + else if (mac->cg && + mac->cg->spCellConfig && + mac->cg->spCellConfig->spCellConfigDedicated && + mac->cg->spCellConfig->spCellConfigDedicated->pdsch_ServingCellConfig && + mac->cg->spCellConfig->spCellConfigDedicated->pdsch_ServingCellConfig->choice.setup && + mac->cg->spCellConfig->spCellConfigDedicated->pdsch_ServingCellConfig->choice.setup->codeBlockGroupTransmission != NULL) { + LOG_E(PHY,"PUCCH Unsupported code block group for serving cell config : at line %d in function %s of file %s \n", LINE_FILE , __func__, FILE_NAME); + return; + } + NR_PUCCH_Config_t *pucch_Config; + if (bwp_id>0 && + mac->ULbwp[bwp_id-1] && + mac->ULbwp[bwp_id-1]->bwp_Dedicated && + mac->ULbwp[bwp_id-1]->bwp_Dedicated->pucch_Config && + mac->ULbwp[bwp_id-1]->bwp_Dedicated->pucch_Config->choice.setup) { + NR_PUSCH_Config_t *pusch_Config = mac->ULbwp[bwp_id-1]->bwp_Dedicated->pusch_Config->choice.setup; + pusch_id = pusch_Config->dataScramblingIdentityPUSCH; + if (pusch_Config->dmrs_UplinkForPUSCH_MappingTypeA != NULL) + id0 = pusch_Config->dmrs_UplinkForPUSCH_MappingTypeA->choice.setup->transformPrecodingDisabled->scramblingID0; + else if (pusch_Config->dmrs_UplinkForPUSCH_MappingTypeB != NULL) + id0 = pusch_Config->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup->transformPrecodingDisabled->scramblingID0; + else *id0 = mac->physCellId; + pucch_Config = mac->ULbwp[bwp_id-1]->bwp_Dedicated->pucch_Config->choice.setup; + pucch_pdu->bwp_size = NRRIV2BW(mac->ULbwp[bwp_id-1]->bwp_Common->genericParameters.locationAndBandwidth,MAX_BWP_SIZE); + pucch_pdu->bwp_start = NRRIV2PRBOFFSET(mac->ULbwp[bwp_id-1]->bwp_Common->genericParameters.locationAndBandwidth,MAX_BWP_SIZE); + } + else if (bwp_id==0 && + mac->cg && + mac->cg->spCellConfig && + mac->cg->spCellConfig->spCellConfigDedicated && + mac->cg->spCellConfig->spCellConfigDedicated->uplinkConfig && + mac->cg->spCellConfig->spCellConfigDedicated->uplinkConfig->initialUplinkBWP && + mac->cg->spCellConfig->spCellConfigDedicated->uplinkConfig->initialUplinkBWP->pucch_Config && + mac->cg->spCellConfig->spCellConfigDedicated->uplinkConfig->initialUplinkBWP->pucch_Config->choice.setup) { + pucch_Config = mac->cg->spCellConfig->spCellConfigDedicated->uplinkConfig->initialUplinkBWP->pucch_Config->choice.setup; + pucch_pdu->bwp_size = NRRIV2BW(mac->scc_SIB->uplinkConfigCommon->initialUplinkBWP.genericParameters.locationAndBandwidth,MAX_BWP_SIZE); + pucch_pdu->bwp_start = NRRIV2PRBOFFSET(mac->scc_SIB->uplinkConfigCommon->initialUplinkBWP.genericParameters.locationAndBandwidth,MAX_BWP_SIZE); + } + else AssertFatal(1==0,"no pucch_Config\n"); + + NR_PUCCH_ConfigCommon_t *pucch_ConfigCommon; + if (mac->scc) pucch_ConfigCommon = mac->scc->uplinkConfigCommon->initialUplinkBWP->pucch_ConfigCommon->choice.setup; + else pucch_ConfigCommon = mac->scc_SIB->uplinkConfigCommon->initialUplinkBWP.pucch_ConfigCommon->choice.setup; + if (pucch_ConfigCommon->hoppingId != NULL) + pucch_pdu->hopping_id = *pucch_ConfigCommon->hoppingId; + else + pucch_pdu->hopping_id = mac->physCellId; + + switch (pucch_ConfigCommon->pucch_GroupHopping){ + case 0 : + // if neither, both disabled + pucch_pdu->group_hop_flag = 0; + pucch_pdu->sequence_hop_flag = 0; + break; + case 1 : + // if enable, group enabled + pucch_pdu->group_hop_flag = 1; + pucch_pdu->sequence_hop_flag = 0; + break; + case 2 : + // if disable, sequence disabled + pucch_pdu->group_hop_flag = 0; + pucch_pdu->sequence_hop_flag = 1; + break; + default: + AssertFatal(1==0,"Group hopping flag undefined (0,1,2) \n"); + } + + pucch_pdu->prb_start = pucchres->startingPRB; + pucch_pdu->freq_hop_flag = pucchres->intraSlotFrequencyHopping!= NULL ? 1 : 0; + pucch_pdu->second_hop_prb = pucchres->secondHopPRB!= NULL ? *pucchres->secondHopPRB : 0; + + if ((O_SR+O_CSI+O_SR) > (sizeof(uint64_t)*8)) { + LOG_E(PHY,"PUCCH number of UCI bits exceeds payload size : at line %d in function %s of file %s \n", LINE_FILE , __func__, FILE_NAME); + return; + } + pucch_pdu->payload = (pucch->csi_part1_payload << (O_ACK + O_SR)) | (pucch->sr_payload << O_ACK) | pucch->ack_payload; + + switch(pucchres->format.present) { + case NR_PUCCH_Resource__format_PR_format0 : + pucch_pdu->format_type = 0; + pucch_pdu->initial_cyclic_shift = pucchres->format.choice.format0->initialCyclicShift; + pucch_pdu->nr_of_symbols = pucchres->format.choice.format0->nrofSymbols; + pucch_pdu->start_symbol_index = pucchres->format.choice.format0->startingSymbolIndex; + if (O_SR == 0 || pucch->sr_payload == 0) { /* only ack is transmitted TS 36.213 9.2.3 UE procedure for reporting HARQ-ACK */ + if (O_ACK == 1) + pucch_pdu->mcs = sequence_cyclic_shift_1_harq_ack_bit[pucch->ack_payload & 0x1]; /* only harq of 1 bit */ + else + pucch_pdu->mcs = sequence_cyclic_shift_2_harq_ack_bits[pucch->ack_payload & 0x3]; /* only harq with 2 bits */ + } + else { /* SR + eventually ack are transmitted TS 36.213 9.2.5.1 UE procedure for multiplexing HARQ-ACK or CSI and SR */ + if (pucch->sr_payload == 1) { /* positive scheduling request */ + if (O_ACK == 1) + pucch_pdu->mcs = sequence_cyclic_shift_1_harq_ack_bit_positive_sr[pucch->ack_payload & 0x1]; /* positive SR and harq of 1 bit */ + else if (O_ACK == 2) + pucch_pdu->mcs = sequence_cyclic_shift_2_harq_ack_bits_positive_sr[pucch->ack_payload & 0x3]; /* positive SR and harq with 2 bits */ + else + pucch_pdu->mcs = 0; /* only positive SR */ + } + } + break; + case NR_PUCCH_Resource__format_PR_format1 : + pucch_pdu->format_type = 1; + pucch_pdu->initial_cyclic_shift = pucchres->format.choice.format1->initialCyclicShift; + pucch_pdu->nr_of_symbols = pucchres->format.choice.format1->nrofSymbols; + pucch_pdu->start_symbol_index = pucchres->format.choice.format1->startingSymbolIndex; + pucch_pdu->time_domain_occ_idx = pucchres->format.choice.format1->timeDomainOCC; + break; + case NR_PUCCH_Resource__format_PR_format2 : + pucch_pdu->format_type = 2; + pucch_pdu->n_bit = O_uci+O_SR; + pucch_pdu->nr_of_symbols = pucchres->format.choice.format2->nrofSymbols; + pucch_pdu->start_symbol_index = pucchres->format.choice.format2->startingSymbolIndex; + pucch_pdu->data_scrambling_id = pusch_id!= NULL ? *pusch_id : mac->physCellId; + pucch_pdu->dmrs_scrambling_id = id0!= NULL ? *id0 : mac->physCellId; + pucch_pdu->prb_size = compute_pucch_prb_size(2,pucchres->format.choice.format2->nrofPRBs, + O_uci+O_SR,O_CSI,pucch_Config->format2->choice.setup->maxCodeRate, + 2,pucchres->format.choice.format2->nrofSymbols,8); + break; + case NR_PUCCH_Resource__format_PR_format3 : + pucch_pdu->format_type = 3; + pucch_pdu->n_bit = O_uci+O_SR; + pucch_pdu->nr_of_symbols = pucchres->format.choice.format3->nrofSymbols; + pucch_pdu->start_symbol_index = pucchres->format.choice.format3->startingSymbolIndex; + pucch_pdu->data_scrambling_id = pusch_id!= NULL ? *pusch_id : mac->physCellId; + if (pucch_Config->format3 == NULL) { + pucch_pdu->pi_2bpsk = 0; + pucch_pdu->add_dmrs_flag = 0; + } + else { + pucchfmt = pucch_Config->format3->choice.setup; + pucch_pdu->pi_2bpsk = pucchfmt->pi2BPSK!= NULL ? 1 : 0; + pucch_pdu->add_dmrs_flag = pucchfmt->additionalDMRS!= NULL ? 1 : 0; + } + int f3_dmrs_symbols; + if (pucchres->format.choice.format3->nrofSymbols==4) + f3_dmrs_symbols = 1<freq_hop_flag; + else { + if(pucchres->format.choice.format3->nrofSymbols<10) + f3_dmrs_symbols = 2; + else + f3_dmrs_symbols = 2<add_dmrs_flag; + } + pucch_pdu->prb_size = compute_pucch_prb_size(3,pucchres->format.choice.format3->nrofPRBs, + O_uci+O_SR,O_CSI,pucch_Config->format3->choice.setup->maxCodeRate, + 2-pucch_pdu->pi_2bpsk,pucchres->format.choice.format3->nrofSymbols-f3_dmrs_symbols,12); + break; + case NR_PUCCH_Resource__format_PR_format4 : + pucch_pdu->format_type = 4; + pucch_pdu->nr_of_symbols = pucchres->format.choice.format4->nrofSymbols; + pucch_pdu->start_symbol_index = pucchres->format.choice.format4->startingSymbolIndex; + pucch_pdu->pre_dft_occ_len = pucchres->format.choice.format4->occ_Length; + pucch_pdu->pre_dft_occ_idx = pucchres->format.choice.format4->occ_Index; + pucch_pdu->data_scrambling_id = pusch_id!= NULL ? *pusch_id : mac->physCellId; + if (pucch_Config->format3 == NULL) { + pucch_pdu->pi_2bpsk = 0; + pucch_pdu->add_dmrs_flag = 0; + } + else { + pucchfmt = pucch_Config->format3->choice.setup; + pucch_pdu->pi_2bpsk = pucchfmt->pi2BPSK!= NULL ? 1 : 0; + pucch_pdu->add_dmrs_flag = pucchfmt->additionalDMRS!= NULL ? 1 : 0; + } + break; + default : + AssertFatal(1==0,"Undefined PUCCH format \n"); + } + pucch_pdu->pucch_tx_power = get_pucch_tx_power_ue(mac, + pucch_Config, + pucch, + pucch_pdu->format_type, + pucch_pdu->prb_size, + pucch_pdu->freq_hop_flag, + pucch_pdu->add_dmrs_flag, + pucch_pdu->nr_of_symbols, + subframe_number, + O_ACK, O_SR, + O_CSI, O_CRC); + } +} + + +int16_t get_pucch_tx_power_ue(NR_UE_MAC_INST_t *mac, + NR_PUCCH_Config_t *pucch_Config, + PUCCH_sched_t *pucch, + uint8_t format_type, + uint16_t nb_of_prbs, + uint8_t freq_hop_flag, + uint8_t add_dmrs_flag, + uint8_t N_symb_PUCCH, + int subframe_number, + int O_ACK, int O_SR, + int O_CSI, int O_CRC) { + + int PUCCH_POWER_DEFAULT = 0; + int16_t P_O_NOMINAL_PUCCH; + if (mac->scc) P_O_NOMINAL_PUCCH = *mac->scc->uplinkConfigCommon->initialUplinkBWP->pucch_ConfigCommon->choice.setup->p0_nominal; + else P_O_NOMINAL_PUCCH = *mac->scc_SIB->uplinkConfigCommon->initialUplinkBWP.pucch_ConfigCommon->choice.setup->p0_nominal; + + struct NR_PUCCH_PowerControl *power_config = pucch_Config->pucch_PowerControl; + int16_t P_O_UE_PUCCH; + int16_t G_b_f_c = 0; + + if (pucch_Config->spatialRelationInfoToAddModList != NULL) { /* FFS TODO NR */ + LOG_E(PHY,"PUCCH Spatial relation infos are not yet implemented : at line %d in function %s of file %s \n", LINE_FILE , __func__, __FILE__); + return (PUCCH_POWER_DEFAULT); + } + + if (power_config->p0_Set != NULL) { + P_O_UE_PUCCH = power_config->p0_Set->list.array[0]->p0_PUCCH_Value; /* get from index 0 if no spatial relation set */ + G_b_f_c = 0; + } + else { + G_b_f_c = pucch->delta_pucch; + LOG_D(PHY,"PUCCH Transmit power control command not yet implemented for NR : at line %d in function %s of file %s \n", LINE_FILE , __func__, __FILE__); + return (PUCCH_POWER_DEFAULT); + } + + int P_O_PUCCH = P_O_NOMINAL_PUCCH + P_O_UE_PUCCH; + + int16_t delta_F_PUCCH; + int DELTA_TF; + uint16_t N_ref_PUCCH; + int N_sc_ctrl_RB = 0; + + /* computing of pucch transmission power adjustment */ + switch (format_type) { + case 0: + N_ref_PUCCH = 2; + DELTA_TF = 10 * log10(N_ref_PUCCH/N_symb_PUCCH); + delta_F_PUCCH = *power_config->deltaF_PUCCH_f0; + break; + case 1: + N_ref_PUCCH = 14; + DELTA_TF = 10 * log10(N_ref_PUCCH/N_symb_PUCCH); + delta_F_PUCCH = *power_config->deltaF_PUCCH_f1; + break; + case 2: + N_sc_ctrl_RB = 10; + DELTA_TF = get_deltatf(nb_of_prbs, + N_symb_PUCCH, + freq_hop_flag, + add_dmrs_flag, + N_sc_ctrl_RB, + pucch->n_HARQ_ACK, + O_ACK, O_SR, + O_CSI, O_CRC); + delta_F_PUCCH = *power_config->deltaF_PUCCH_f2; + break; + case 3: + N_sc_ctrl_RB = 14; + DELTA_TF = get_deltatf(nb_of_prbs, + N_symb_PUCCH, + freq_hop_flag, + add_dmrs_flag, + N_sc_ctrl_RB, + pucch->n_HARQ_ACK, + O_ACK, O_SR, + O_CSI, O_CRC); + delta_F_PUCCH = *power_config->deltaF_PUCCH_f3; + break; + case 4: + N_sc_ctrl_RB = 14/(nb_pucch_format_4_in_subframes[subframe_number]); + DELTA_TF = get_deltatf(nb_of_prbs, + N_symb_PUCCH, + freq_hop_flag, + add_dmrs_flag, + N_sc_ctrl_RB, + pucch->n_HARQ_ACK, + O_ACK, O_SR, + O_CSI, O_CRC); + delta_F_PUCCH = *power_config->deltaF_PUCCH_f4; + break; + default: + { + LOG_E(PHY,"PUCCH unknown pucch format : at line %d in function %s of file %s \n", LINE_FILE , __func__, __FILE__); + return (0); + } + } + + if (*power_config->twoPUCCH_PC_AdjustmentStates > 1) { + LOG_E(PHY,"PUCCH power control adjustment states with 2 states not yet implemented : at line %d in function %s of file %s \n", LINE_FILE , __func__, __FILE__); + return (PUCCH_POWER_DEFAULT); + } + + int16_t pucch_power = P_O_PUCCH + delta_F_PUCCH + DELTA_TF + G_b_f_c; + + NR_TST_PHY_PRINTF("PUCCH ( Tx power : %d dBm ) ( 10Log(...) : %d ) ( from Path Loss : %d ) ( delta_F_PUCCH : %d ) ( DELTA_TF : %d ) ( G_b_f_c : %d ) \n", + pucch_power, contributor, PL, delta_F_PUCCH, DELTA_TF, G_b_f_c); + + return (pucch_power); +} + +int get_deltatf(uint16_t nb_of_prbs, + uint8_t N_symb_PUCCH, + uint8_t freq_hop_flag, + uint8_t add_dmrs_flag, + int N_sc_ctrl_RB, + int n_HARQ_ACK, + int O_ACK, int O_SR, + int O_CSI, int O_CRC){ + + int DELTA_TF; + int O_UCI = O_ACK + O_SR + O_CSI + O_CRC; + int N_symb = nb_symbols_excluding_dmrs[N_symb_PUCCH-4][add_dmrs_flag][freq_hop_flag]; + float N_RE = nb_of_prbs * N_sc_ctrl_RB * N_symb; + float K1 = 6; + if (O_UCI < 12) + DELTA_TF = 10 * log10((double)(((K1 * (n_HARQ_ACK + O_SR + O_CSI))/N_RE))); + else { + float K2 = 2.4; + float BPRE = O_UCI/N_RE; + DELTA_TF = 10 * log10((double)(pow(2,(K2*BPRE)) - 1)); + } + return DELTA_TF; +} + +/******************************************************************* +* +* NAME : find_pucch_resource_set +* +* PARAMETERS : ue context +* gNB_id identifier +* +* +* RETURN : harq process identifier +* +* DESCRIPTION : return tx harq process identifier for given transmission slot +* YS 38.213 9.2.2 PUCCH Formats for UCI transmission +* +*********************************************************************/ + +int find_pucch_resource_set(NR_UE_MAC_INST_t *mac, int uci_size) { + int pucch_resource_set_id = 0; + NR_BWP_Id_t bwp_id = mac->DL_BWP_Id; + + //long *pucch_max_pl_bits = NULL; + + /* from TS 38.331 field maxPayloadMinus1 + -- Maximum number of payload bits minus 1 that the UE may transmit using this PUCCH resource set. In a PUCCH occurrence, the UE + -- chooses the first of its PUCCH-ResourceSet which supports the number of bits that the UE wants to transmit. + -- The field is not present in the first set (Set0) since the maximum Size of Set0 is specified to be 3 bit. + -- The field is not present in the last configured set since the UE derives its maximum payload size as specified in 38.213. + -- This field can take integer values that are multiples of 4. Corresponds to L1 parameter 'N_2' or 'N_3' (see 38.213, section 9.2) + */ + /* look for the first resource set which supports uci_size number of bits for payload */ + while (pucch_resource_set_id < MAX_NB_OF_PUCCH_RESOURCE_SETS) { + if ((bwp_id>0 && + mac->ULbwp[bwp_id-1] && + mac->ULbwp[bwp_id-1]->bwp_Dedicated && + mac->ULbwp[bwp_id-1]->bwp_Dedicated->pucch_Config && + mac->ULbwp[bwp_id-1]->bwp_Dedicated->pucch_Config->choice.setup && + mac->ULbwp[bwp_id-1]->bwp_Dedicated->pucch_Config->choice.setup->resourceSetToAddModList && + mac->ULbwp[bwp_id-1]->bwp_Dedicated->pucch_Config->choice.setup->resourceSetToAddModList->list.array[pucch_resource_set_id] != NULL) || + (bwp_id==0 && + mac->cg && + mac->cg->spCellConfig && + mac->cg->spCellConfig->spCellConfigDedicated && + mac->cg->spCellConfig->spCellConfigDedicated->uplinkConfig && + mac->cg->spCellConfig->spCellConfigDedicated->uplinkConfig->initialUplinkBWP && + mac->cg->spCellConfig->spCellConfigDedicated->uplinkConfig->initialUplinkBWP->pucch_Config && + mac->cg->spCellConfig->spCellConfigDedicated->uplinkConfig->initialUplinkBWP->pucch_Config->choice.setup && + mac->cg->spCellConfig->spCellConfigDedicated->uplinkConfig->initialUplinkBWP->pucch_Config->choice.setup->resourceSetToAddModList && + mac->cg->spCellConfig->spCellConfigDedicated->uplinkConfig->initialUplinkBWP->pucch_Config->choice.setup->resourceSetToAddModList->list.array[pucch_resource_set_id] != NULL)) { + if (uci_size <= 2) { + pucch_resource_set_id = 0; + return (pucch_resource_set_id); + break; + } + else { + pucch_resource_set_id = 1; + return (pucch_resource_set_id); + break; + } + } + pucch_resource_set_id++; + } + + pucch_resource_set_id = MAX_NB_OF_PUCCH_RESOURCE_SETS; + + return (pucch_resource_set_id); +} + + +/******************************************************************* +* +* NAME : select_pucch_format +* +* PARAMETERS : ue context +* processing slots of reception/transmission +* gNB_id identifier +* +* RETURN : TRUE a valid resource has been found +* +* DESCRIPTION : return tx harq process identifier for given transmission slot +* TS 38.213 9.2.1 PUCCH Resource Sets +* TS 38.213 9.2.2 PUCCH Formats for UCI transmission +* In the case of pucch for scheduling request only, resource is already get from scheduling request configuration +* +*********************************************************************/ + +void select_pucch_resource(NR_UE_MAC_INST_t *mac, + PUCCH_sched_t *pucch) { + + NR_PUCCH_ResourceId_t *current_resource_id = NULL; + NR_BWP_Id_t bwp_id = mac->UL_BWP_Id; + int n_list; + + if ((bwp_id ==0 && + mac->cg == NULL) || + (bwp_id == 0 && + mac->cg && + mac->cg->spCellConfig && + mac->cg->spCellConfig->spCellConfigDedicated && + mac->cg->spCellConfig->spCellConfigDedicated->uplinkConfig && + mac->cg->spCellConfig->spCellConfigDedicated->uplinkConfig->initialUplinkBWP && + mac->cg->spCellConfig->spCellConfigDedicated->uplinkConfig->initialUplinkBWP->pucch_Config && + mac->cg->spCellConfig->spCellConfigDedicated->uplinkConfig->initialUplinkBWP->pucch_Config->choice.setup && + mac->cg->spCellConfig->spCellConfigDedicated->uplinkConfig->initialUplinkBWP->pucch_Config->choice.setup->resourceSetToAddModList && + mac->cg->spCellConfig->spCellConfigDedicated->uplinkConfig->initialUplinkBWP->pucch_Config->choice.setup->resourceSetToAddModList->list.array[0] == NULL) || + (mac->ULbwp[bwp_id-1] && + mac->ULbwp[bwp_id-1]->bwp_Dedicated && + mac->ULbwp[bwp_id-1]->bwp_Dedicated->pucch_Config && + mac->ULbwp[bwp_id-1]->bwp_Dedicated->pucch_Config->choice.setup && + mac->ULbwp[bwp_id-1]->bwp_Dedicated->pucch_Config->choice.setup->resourceSetToAddModList && + mac->ULbwp[bwp_id-1]->bwp_Dedicated->pucch_Config->choice.setup->resourceSetToAddModList->list.array[0] == NULL) + ){ + + /* see TS 38.213 9.2.1 PUCCH Resource Sets */ + int delta_PRI = pucch->resource_indicator; + int n_CCE_0 = pucch->n_CCE; + int N_CCE_0 = pucch->N_CCE; + if (N_CCE_0 == 0) { + AssertFatal(1==0,"PUCCH No compatible pucch format found : at line %d in function %s of file %s \n", LINE_FILE , __func__, FILE_NAME); + } + int r_PUCCH = ((2 * n_CCE_0)/N_CCE_0) + (2 * delta_PRI); + pucch->initial_pucch_id = r_PUCCH; + pucch->pucch_resource = NULL; + } + else { + struct NR_PUCCH_Config__resourceSetToAddModList *resourceSetToAddModList = NULL; + struct NR_PUCCH_Config__resourceToAddModList *resourceToAddModList = NULL; + if (bwp_id > 0 && mac->ULbwp[bwp_id-1]) { + AssertFatal(mac->ULbwp[bwp_id-1]->bwp_Dedicated->pucch_Config->choice.setup->resourceSetToAddModList!=NULL, + "mac->ULbwp[bwp_id-1]->bwp_Dedicated->pucch_Config->choice.setup->resourceSetToAddModList is null\n"); + resourceSetToAddModList = mac->ULbwp[bwp_id-1]->bwp_Dedicated->pucch_Config->choice.setup->resourceSetToAddModList; + resourceToAddModList = mac->ULbwp[bwp_id-1]->bwp_Dedicated->pucch_Config->choice.setup->resourceToAddModList; + } + else if (bwp_id == 0 && mac->cg->spCellConfig->spCellConfigDedicated->uplinkConfig->initialUplinkBWP->pucch_Config->choice.setup->resourceSetToAddModList!=NULL) { + resourceSetToAddModList = mac->cg->spCellConfig->spCellConfigDedicated->uplinkConfig->initialUplinkBWP->pucch_Config->choice.setup->resourceSetToAddModList; + resourceToAddModList = mac->cg->spCellConfig->spCellConfigDedicated->uplinkConfig->initialUplinkBWP->pucch_Config->choice.setup->resourceToAddModList; + } + + n_list = resourceSetToAddModList->list.count; + if (pucch->resource_set_id > n_list) { + LOG_E(PHY,"Invalid PUCCH resource set id %d\n",pucch->resource_set_id); + pucch->pucch_resource = NULL; + return; + } + n_list = resourceSetToAddModList->list.array[pucch->resource_set_id]->resourceList.list.count; + if (pucch->resource_indicator > n_list) { + LOG_E(PHY,"Invalid PUCCH resource id %d\n",pucch->resource_indicator); + pucch->pucch_resource = NULL; + return; + } + current_resource_id = resourceSetToAddModList->list.array[pucch->resource_set_id]->resourceList.list.array[pucch->resource_indicator]; + n_list = resourceToAddModList->list.count; + int res_found = 0; + for (int i=0; ilist.array[i]->pucch_ResourceId == *current_resource_id) { + pucch->pucch_resource = resourceToAddModList->list.array[i]; + res_found = 1; + break; + } + } + if (res_found == 0) { + LOG_E(PHY,"Couldn't find PUCCH Resource\n"); + pucch->pucch_resource = NULL; + } + } +} + +/******************************************************************* +* +* NAME : get_downlink_ack +* +* PARAMETERS : ue context +* processing slots of reception/transmission +* gNB_id identifier +* +* RETURN : o_ACK acknowledgment data +* o_ACK_number_bits number of bits for acknowledgment +* +* DESCRIPTION : return acknowledgment value +* TS 38.213 9.1.3 Type-2 HARQ-ACK codebook determination +* +* --+--------+-------+--------+-------+--- ---+-------+-- +* | PDCCH1 | | PDCCH2 |PDCCH3 | | PUCCH | +* --+--------+-------+--------+-------+--- ---+-------+-- +* DAI_DL 1 2 3 ACK for +* V V V PDCCH1, PDDCH2 and PCCH3 +* | | | ^ +* +-----------------+-------+---------------+ +* +* PDCCH1, PDCCH2 and PDCCH3 are PDCCH monitoring occasions +* M is the total of monitoring occasions +* +*********************************************************************/ + +uint8_t get_downlink_ack(NR_UE_MAC_INST_t *mac, + frame_t frame, + int slot, + PUCCH_sched_t *pucch) { + + + uint32_t ack_data[NR_DL_MAX_NB_CW][NR_DL_MAX_DAI] = {{0},{0}}; + uint32_t dai[NR_DL_MAX_NB_CW][NR_DL_MAX_DAI] = {{0},{0}}; /* for serving cell */ + uint32_t dai_total[NR_DL_MAX_NB_CW][NR_DL_MAX_DAI] = {{0},{0}}; /* for multiple cells */ + int number_harq_feedback = 0; + uint32_t dai_current = 0; + uint32_t dai_max = 0; + bool two_transport_blocks = FALSE; + int number_of_code_word = 1; + int U_DAI_c = 0; + int N_m_c_rx = 0; + int V_DAI_m_DL = 0; + NR_UE_HARQ_STATUS_t *current_harq; + int sched_frame,sched_slot; + NR_BWP_UplinkCommon_t *initialUplinkBWP; + if (mac->scc) initialUplinkBWP = mac->scc->uplinkConfigCommon->initialUplinkBWP; + else initialUplinkBWP = &mac->scc_SIB->uplinkConfigCommon->initialUplinkBWP; + int slots_per_frame,scs; + + if (mac->DLbwp[0] && + mac->DLbwp[0]->bwp_Dedicated && + mac->DLbwp[0]->bwp_Dedicated->pdsch_Config && + mac->DLbwp[0]->bwp_Dedicated->pdsch_Config->choice.setup && + mac->DLbwp[0]->bwp_Dedicated->pdsch_Config->choice.setup->maxNrofCodeWordsScheduledByDCI[0] == 2) { + two_transport_blocks = TRUE; + number_of_code_word = 2; + } + else { + number_of_code_word = 1; + } + + NR_BWP_Uplink_t *ubwp = mac->ULbwp[0]; + if (mac->cg && ubwp && + mac->cg->spCellConfig && + mac->cg->spCellConfig->spCellConfigDedicated && + mac->cg->spCellConfig->spCellConfigDedicated->uplinkConfig && + mac->cg->spCellConfig->spCellConfigDedicated->uplinkConfig->initialUplinkBWP) { + scs = ubwp->bwp_Common->genericParameters.subcarrierSpacing; + } + else + scs = initialUplinkBWP->genericParameters.subcarrierSpacing; + + slots_per_frame = nr_slots_per_frame[scs]; + + /* look for dl acknowledgment which should be done on current uplink slot */ + for (int code_word = 0; code_word < number_of_code_word; code_word++) { + + for (int dl_harq_pid = 0; dl_harq_pid < 16; dl_harq_pid++) { + + current_harq = &mac->dl_harq_info[dl_harq_pid]; + + if (current_harq->active) { + + sched_slot = current_harq->dl_slot + current_harq->feedback_to_ul; + sched_frame = current_harq->dl_frame; + if (sched_slot>=slots_per_frame){ + sched_slot %= slots_per_frame; + sched_frame++; + } + + /* check if current tx slot should transmit downlink acknowlegment */ + if (sched_frame == frame && sched_slot == slot) { + + if (current_harq->dai > NR_DL_MAX_DAI) { + LOG_E(PHY,"PUCCH Downlink DAI has an invalid value : at line %d in function %s of file %s \n", LINE_FILE , __func__, FILE_NAME); + } + else { + + if ((pucch->resource_indicator != -1) && (pucch->resource_indicator != current_harq->pucch_resource_indicator)) + LOG_E(PHY, "Value of pucch_resource_indicator %d not matching with what set before %d (Possibly due to a false DCI) \n", + current_harq->pucch_resource_indicator,pucch->resource_indicator); + else{ + dai_current = current_harq->dai+1; // DCI DAI to counter DAI conversion + + if (dai_current == 0) { + LOG_E(PHY,"PUCCH Downlink dai is invalid : at line %d in function %s of file %s \n", LINE_FILE , __func__, FILE_NAME); + return(0); + } else if (dai_current > dai_max) { + dai_max = dai_current; + } + + number_harq_feedback++; + if (current_harq->ack_received) + ack_data[code_word][dai_current - 1] = current_harq->ack; + else + ack_data[code_word][dai_current - 1] = 0; + dai[code_word][dai_current - 1] = dai_current; + + pucch->resource_indicator = current_harq->pucch_resource_indicator; + pucch->n_CCE = current_harq->n_CCE; + pucch->N_CCE = current_harq->N_CCE; + pucch->delta_pucch = current_harq->delta_pucch; + current_harq->active = false; + current_harq->ack_received = false; + } + } + } + } + } + } + + /* no any ack to transmit */ + if (number_harq_feedback == 0) { + pucch->n_HARQ_ACK = 0; + return(0); + } + else if (number_harq_feedback > (sizeof(uint32_t)*8)) { + LOG_E(PHY,"PUCCH number of ack bits exceeds payload size : at line %d in function %s of file %s \n", LINE_FILE , __func__, FILE_NAME); + return(0); + } + + /* for computing n_HARQ_ACK for power */ + V_DAI_m_DL = dai_max; + U_DAI_c = number_harq_feedback/number_of_code_word; + N_m_c_rx = number_harq_feedback; + int N_SPS_c = 0; /* FFS TODO_NR multicells and SPS are not supported at the moment */ + if (mac->cg != NULL && + mac->cg->physicalCellGroupConfig != NULL && + mac->cg->physicalCellGroupConfig->harq_ACK_SpatialBundlingPUCCH != NULL) { + int N_TB_max_DL = mac->DLbwp[0]->bwp_Dedicated->pdsch_Config->choice.setup->maxNrofCodeWordsScheduledByDCI[0]; + pucch->n_HARQ_ACK = (((V_DAI_m_DL - U_DAI_c)%4) * N_TB_max_DL) + N_m_c_rx + N_SPS_c; + NR_TST_PHY_PRINTF("PUCCH power n(%d) = ( V(%d) - U(%d) )mod4 * N_TB(%d) + N(%d) \n", pucch->n_HARQ_ACK, V_DAI_m_DL, U_DAI_c, N_TB_max_DL, N_m_c_rx); + } + + /* + * For a monitoring occasion of a PDCCH with DCI format 1_0 or DCI format 1_1 in at least one serving cell, + * when a UE receives a PDSCH with one transport block and the value of higher layer parameter maxNrofCodeWordsScheduledByDCI is 2, + * the HARQ-ACK response is associated with the first transport block and the UE generates a NACK for the second transport block + * if spatial bundling is not applied (HARQ-ACK-spatial-bundling-PUCCH = FALSE) and generates HARQ-ACK value of ACK for the second + * transport block if spatial bundling is applied. + */ + + for (int code_word = 0; code_word < number_of_code_word; code_word++) { + for (uint32_t i = 0; i < dai_max ; i++ ) { + if (dai[code_word][i] != i + 1) { /* fill table with consistent value for each dai */ + dai[code_word][i] = i + 1; /* it covers case for which PDCCH DCI has not been successfully decoded and so it has been missed */ + ack_data[code_word][i] = 0; /* nack data transport block which has been missed */ + number_harq_feedback++; + } + if (two_transport_blocks == TRUE) { + dai_total[code_word][i] = dai[code_word][i]; /* for a single cell, dai_total is the same as dai of first cell */ + } + } + } + + int M = dai_max; + int j = 0; + uint32_t V_temp = 0; + uint32_t V_temp2 = 0; + int O_ACK = 0; + int o_ACK = 0; + int O_bit_number_cw0 = 0; + int O_bit_number_cw1 = 0; + + for (int m = 0; m < M ; m++) { + + if (dai[0][m] <= V_temp) { + j = j + 1; + } + + V_temp = dai[0][m]; /* value of the counter DAI for format 1_0 and format 1_1 on serving cell c */ + + if (dai_total[0][m] == 0) { + V_temp2 = dai[0][m]; + } else { + V_temp2 = dai[1][m]; /* second code word has been received */ + O_bit_number_cw1 = (8 * j) + 2*(V_temp - 1) + 1; + o_ACK = o_ACK | (ack_data[1][m] << O_bit_number_cw1); + } + + if (two_transport_blocks == TRUE) { + O_bit_number_cw0 = (8 * j) + 2*(V_temp - 1); + } + else { + O_bit_number_cw0 = (4 * j) + (V_temp - 1); + } + + o_ACK = o_ACK | (ack_data[0][m] << O_bit_number_cw0); + } + + if (V_temp2 < V_temp) { + j = j + 1; + } + + if (two_transport_blocks == TRUE) { + O_ACK = 2 * ( 4 * j + V_temp2); /* for two transport blocks */ + } + else { + O_ACK = 4 * j + V_temp2; /* only one transport block */ + } + + if (number_harq_feedback != O_ACK) { + LOG_E(PHY,"PUCCH Error for number of bits for acknowledgment : at line %d in function %s of file %s \n", LINE_FILE , __func__, FILE_NAME); + return (0); + } + + pucch->ack_payload = o_ACK; + return(number_harq_feedback); +} + + int8_t nr_ue_get_SR(module_id_t module_idP, int CC_id, frame_t frameP, uint8_t eNB_id, uint16_t rnti, sub_frame_t subframe){ return 0; diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c index a85aba0130..ae610b75bf 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c @@ -1794,6 +1794,77 @@ void build_ssb_to_ro_map(NR_UE_MAC_INST_t *mac) { LOG_D(NR_MAC,"Map SSB to RO done\n"); } + +void nr_ue_pucch_scheduler(module_id_t module_idP, frame_t frameP, int slotP, int thread_id) { + + NR_UE_MAC_INST_t *mac = get_mac_inst(module_idP); + int O_SR = 0; + int O_ACK = 0; + int O_CSI = 0; + int N_UCI = 0; + + PUCCH_sched_t *pucch = calloc(1,sizeof(*pucch)); + pucch->resource_indicator = -1; + pucch->initial_pucch_id = -1; + uint16_t rnti = mac->crnti; //FIXME not sure this is valid for all pucch instances + + // SR + + + // CSI + + + // ACKNACK + O_ACK = get_downlink_ack(mac, frameP, slotP, pucch); + + NR_BWP_Id_t bwp_id = mac->UL_BWP_Id; + NR_PUCCH_Config_t *pucch_Config; + if (bwp_id>0 && + mac->ULbwp[bwp_id-1] && + mac->ULbwp[bwp_id-1]->bwp_Dedicated && + mac->ULbwp[bwp_id-1]->bwp_Dedicated->pucch_Config && + mac->ULbwp[bwp_id-1]->bwp_Dedicated->pucch_Config->choice.setup) { + pucch_Config = mac->ULbwp[bwp_id-1]->bwp_Dedicated->pucch_Config->choice.setup; + } + else if (bwp_id==0 && + mac->cg && + mac->cg->spCellConfig && + mac->cg->spCellConfig->spCellConfigDedicated && + mac->cg->spCellConfig->spCellConfigDedicated->uplinkConfig && + mac->cg->spCellConfig->spCellConfigDedicated->uplinkConfig->initialUplinkBWP && + mac->cg->spCellConfig->spCellConfigDedicated->uplinkConfig->initialUplinkBWP->pucch_Config && + mac->cg->spCellConfig->spCellConfigDedicated->uplinkConfig->initialUplinkBWP->pucch_Config->choice.setup) { + pucch_Config = mac->cg->spCellConfig->spCellConfigDedicated->uplinkConfig->initialUplinkBWP->pucch_Config->choice.setup; + } + else AssertFatal(1==0,"no pucch_Config\n"); + + + // if multiplexing of HARQ and CSI is not possible, transmit only HARQ bits + if ((O_ACK != 0) && (O_ACK != 0) && (pucch_Config->format2->choice.setup->simultaneousHARQ_ACK_CSI == NULL)) { + O_CSI = 0; + pucch->csi_part1_payload = 0; + pucch->csi_part2_payload = 0; + } + + N_UCI = O_SR + O_ACK + O_CSI; + + if (N_UCI > 0) { + pucch->resource_set_id = find_pucch_resource_set(mac, N_UCI); + select_pucch_resource(mac, pucch); + fapi_nr_ul_config_request_t *ul_config = get_ul_config_request(mac, slotP); + fapi_nr_ul_config_pucch_pdu *pucch_pdu = &ul_config->ul_config_list[ul_config->number_pdus].pucch_config_pdu; + nr_ue_configure_pucch(mac, + slotP, + rnti, + pucch, + pucch_pdu, + O_SR, O_ACK, O_CSI); + fill_ul_config(ul_config, frameP, slotP, FAPI_NR_UL_CONFIG_TYPE_PUCCH); + } + +} + + // This function schedules the PRACH according to prach_ConfigurationIndex and TS 38.211, tables 6.3.3.2.x // PRACH formats 9, 10, 11 are corresponding to dual PRACH format configurations A1/B1, A2/B2, A3/B3. // - todo: diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c index 51a71427c5..eabbd35825 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c @@ -736,15 +736,15 @@ void nr_configure_pdcch(nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu, // This function configures pucch pdu fapi structure void nr_configure_pucch(nfapi_nr_pucch_pdu_t* pucch_pdu, - NR_ServingCellConfigCommon_t *scc, - NR_CellGroupConfig_t *CellGroup, - NR_BWP_Uplink_t *bwp, + NR_ServingCellConfigCommon_t *scc, + NR_CellGroupConfig_t *CellGroup, + NR_BWP_Uplink_t *bwp, uint16_t rnti, uint8_t pucch_resource, uint16_t O_csi, uint16_t O_ack, uint8_t O_sr, - int r_pucch) { + int r_pucch) { NR_PUCCH_Config_t *pucch_Config; NR_PUCCH_Resource_t *pucchres; @@ -808,169 +808,168 @@ void nr_configure_pucch(nfapi_nr_pucch_pdu_t* pucch_pdu, pucch_pdu->cyclic_prefix = (genericParameters->cyclicPrefix==NULL) ? 0 : *genericParameters->cyclicPrefix; if (r_pucch<0 || bwp){ // we have either a dedicated BWP or Dedicated PUCCH configuration on InitialBWP - pucch_Config = bwp ? - bwp->bwp_Dedicated->pucch_Config->choice.setup: - CellGroup->spCellConfig->spCellConfigDedicated->uplinkConfig->initialUplinkBWP->pucch_Config->choice.setup; + pucch_Config = bwp ? + bwp->bwp_Dedicated->pucch_Config->choice.setup: + CellGroup->spCellConfig->spCellConfigDedicated->uplinkConfig->initialUplinkBWP->pucch_Config->choice.setup; - AssertFatal(pucch_Config->resourceSetToAddModList!=NULL, - "PUCCH resourceSetToAddModList is null\n"); + AssertFatal(pucch_Config->resourceSetToAddModList!=NULL, + "PUCCH resourceSetToAddModList is null\n"); - n_set = pucch_Config->resourceSetToAddModList->list.count; - AssertFatal(n_set>0,"PUCCH resourceSetToAddModList is empty\n"); + n_set = pucch_Config->resourceSetToAddModList->list.count; + AssertFatal(n_set>0,"PUCCH resourceSetToAddModList is empty\n"); - LOG_D(NR_MAC, "UCI n_set= %d\n", n_set); + LOG_D(NR_MAC, "UCI n_set= %d\n", n_set); - N2 = 2; - // procedure to select pucch resource id from resource sets according to - // number of uci bits and pucch resource indicator pucch_resource - // ( see table 9.2.3.2 in 38.213) - for (int i=0; iresourceSetToAddModList->list.array[i]; - n_list = pucchresset->resourceList.list.count; - if (pucchresset->pucch_ResourceSetId == 0 && O_uci<3) { - if (pucch_resource < n_list) - resource_id = pucchresset->resourceList.list.array[pucch_resource]; - else - AssertFatal(1==0,"Couldn't fine pucch resource indicator %d in PUCCH resource set %d for %d UCI bits",pucch_resource,i,O_uci); - } - if (pucchresset->pucch_ResourceSetId == 1 && O_uci>2) { + N2 = 2; + // procedure to select pucch resource id from resource sets according to + // number of uci bits and pucch resource indicator pucch_resource + // ( see table 9.2.3.2 in 38.213) + for (int i=0; iresourceSetToAddModList->list.array[i]; + n_list = pucchresset->resourceList.list.count; + if (pucchresset->pucch_ResourceSetId == 0 && O_uci<3) { + if (pucch_resource < n_list) + resource_id = pucchresset->resourceList.list.array[pucch_resource]; + else + AssertFatal(1==0,"Couldn't fine pucch resource indicator %d in PUCCH resource set %d for %d UCI bits",pucch_resource,i,O_uci); + } + if (pucchresset->pucch_ResourceSetId == 1 && O_uci>2) { #if (NR_RRC_VERSION >= MAKE_VERSION(16, 0, 0)) - N3 = pucchresset->maxPayloadSize!= NULL ? *pucchresset->maxPayloadSize : 1706; + N3 = pucchresset->maxPayloadSize!= NULL ? *pucchresset->maxPayloadSize : 1706; #else - N3 = pucchresset->maxPayloadMinus1!= NULL ? *pucchresset->maxPayloadMinus1 : 1706; + N3 = pucchresset->maxPayloadMinus1!= NULL ? *pucchresset->maxPayloadMinus1 : 1706; #endif - if (N2O_uci) { - if (pucch_resource < n_list) - resource_id = pucchresset->resourceList.list.array[pucch_resource]; - else - AssertFatal(1==0,"Couldn't fine pucch resource indicator %d in PUCCH resource set %d for %d UCI bits",pucch_resource,i,O_uci); - } - else N2 = N3; - } - } - - AssertFatal(resource_id!=NULL,"Couldn-t find any matching PUCCH resource in the PUCCH resource sets"); - - AssertFatal(pucch_Config->resourceToAddModList!=NULL, - "PUCCH resourceToAddModList is null\n"); - - n_list = pucch_Config->resourceToAddModList->list.count; - AssertFatal(n_list>0,"PUCCH resourceToAddModList is empty\n"); - - // going through the list of PUCCH resources to find the one indexed by resource_id - for (int i=0; iresourceToAddModList->list.array[i]; - if (pucchres->pucch_ResourceId == *resource_id) { - res_found = 1; - pucch_pdu->prb_start = pucchres->startingPRB; - pucch_pdu->rnti = rnti; - // FIXME why there is only one frequency hopping flag - // what about inter slot frequency hopping? - pucch_pdu->freq_hop_flag = pucchres->intraSlotFrequencyHopping!= NULL ? 1 : 0; - pucch_pdu->second_hop_prb = pucchres->secondHopPRB!= NULL ? *pucchres->secondHopPRB : 0; - switch(pucchres->format.present) { - case NR_PUCCH_Resource__format_PR_format0 : - pucch_pdu->format_type = 0; - pucch_pdu->initial_cyclic_shift = pucchres->format.choice.format0->initialCyclicShift; - pucch_pdu->nr_of_symbols = pucchres->format.choice.format0->nrofSymbols; - pucch_pdu->start_symbol_index = pucchres->format.choice.format0->startingSymbolIndex; - pucch_pdu->sr_flag = O_sr; - break; - case NR_PUCCH_Resource__format_PR_format1 : - pucch_pdu->format_type = 1; - pucch_pdu->initial_cyclic_shift = pucchres->format.choice.format1->initialCyclicShift; - pucch_pdu->nr_of_symbols = pucchres->format.choice.format1->nrofSymbols; - pucch_pdu->start_symbol_index = pucchres->format.choice.format1->startingSymbolIndex; - pucch_pdu->time_domain_occ_idx = pucchres->format.choice.format1->timeDomainOCC; - pucch_pdu->sr_flag = O_sr; - break; - case NR_PUCCH_Resource__format_PR_format2 : - pucch_pdu->format_type = 2; - pucch_pdu->nr_of_symbols = pucchres->format.choice.format2->nrofSymbols; - pucch_pdu->start_symbol_index = pucchres->format.choice.format2->startingSymbolIndex; - pucch_pdu->data_scrambling_id = pusch_id!= NULL ? *pusch_id : *scc->physCellId; - pucch_pdu->dmrs_scrambling_id = id0!= NULL ? *id0 : *scc->physCellId; - pucch_pdu->prb_size = compute_pucch_prb_size(2,pucchres->format.choice.format2->nrofPRBs, - O_uci+O_sr,O_csi,pucch_Config->format2->choice.setup->maxCodeRate, - 2,pucchres->format.choice.format2->nrofSymbols,8); - pucch_pdu->bit_len_csi_part1 = O_csi; - break; - case NR_PUCCH_Resource__format_PR_format3 : - pucch_pdu->format_type = 3; - pucch_pdu->nr_of_symbols = pucchres->format.choice.format3->nrofSymbols; - pucch_pdu->start_symbol_index = pucchres->format.choice.format3->startingSymbolIndex; - pucch_pdu->data_scrambling_id = pusch_id!= NULL ? *pusch_id : *scc->physCellId; - if (pucch_Config->format3 == NULL) { - pucch_pdu->pi_2bpsk = 0; - pucch_pdu->add_dmrs_flag = 0; - } - else { - pucchfmt = pucch_Config->format3->choice.setup; - pucch_pdu->pi_2bpsk = pucchfmt->pi2BPSK!= NULL ? 1 : 0; - pucch_pdu->add_dmrs_flag = pucchfmt->additionalDMRS!= NULL ? 1 : 0; - } - int f3_dmrs_symbols; - if (pucchres->format.choice.format3->nrofSymbols==4) - f3_dmrs_symbols = 1<freq_hop_flag; - else { - if(pucchres->format.choice.format3->nrofSymbols<10) - f3_dmrs_symbols = 2; - else - f3_dmrs_symbols = 2<add_dmrs_flag; - } - pucch_pdu->prb_size = compute_pucch_prb_size(3,pucchres->format.choice.format3->nrofPRBs, - O_uci+O_sr,O_csi,pucch_Config->format3->choice.setup->maxCodeRate, - 2-pucch_pdu->pi_2bpsk,pucchres->format.choice.format3->nrofSymbols-f3_dmrs_symbols,12); - pucch_pdu->bit_len_csi_part1 = O_csi; - break; - case NR_PUCCH_Resource__format_PR_format4 : - pucch_pdu->format_type = 4; - pucch_pdu->nr_of_symbols = pucchres->format.choice.format4->nrofSymbols; - pucch_pdu->start_symbol_index = pucchres->format.choice.format4->startingSymbolIndex; - pucch_pdu->pre_dft_occ_len = pucchres->format.choice.format4->occ_Length; - pucch_pdu->pre_dft_occ_idx = pucchres->format.choice.format4->occ_Index; - pucch_pdu->data_scrambling_id = pusch_id!= NULL ? *pusch_id : *scc->physCellId; - if (pucch_Config->format3 == NULL) { - pucch_pdu->pi_2bpsk = 0; - pucch_pdu->add_dmrs_flag = 0; - } - else { - pucchfmt = pucch_Config->format3->choice.setup; - pucch_pdu->pi_2bpsk = pucchfmt->pi2BPSK!= NULL ? 1 : 0; - pucch_pdu->add_dmrs_flag = pucchfmt->additionalDMRS!= NULL ? 1 : 0; - } - pucch_pdu->bit_len_csi_part1 = O_csi; - break; - default : - AssertFatal(1==0,"Undefined PUCCH format \n"); - } - } - } - AssertFatal(res_found==1,"No PUCCH resource found corresponding to id %ld\n",*resource_id); - } - else { // this is the default PUCCH configuration, PUCCH format 0 or 1 - int rsetindex = *scc->uplinkConfigCommon->initialUplinkBWP->pucch_ConfigCommon->choice.setup->pucch_ResourceCommon; - int prboffset = r_pucch/default_pucch_csset[rsetindex]; - int prboffsetm8 = (r_pucch-8)/default_pucch_csset[rsetindex]; - pucch_pdu->prb_start = (r_pucch>>3)==0 ? - default_pucch_prboffset[rsetindex] + prboffset: - pucch_pdu->bwp_size-1-default_pucch_prboffset[rsetindex]-prboffsetm8; - pucch_pdu->rnti = rnti; - pucch_pdu->freq_hop_flag = 1; - pucch_pdu->second_hop_prb = (r_pucch>>3)==0? - pucch_pdu->bwp_size-1-default_pucch_prboffset[rsetindex]-prboffset: - default_pucch_prboffset[rsetindex] + prboffsetm8; - pucch_pdu->format_type = default_pucch_fmt[rsetindex]; - pucch_pdu->initial_cyclic_shift = r_pucch%default_pucch_csset[rsetindex]; - if (rsetindex==3||rsetindex==7||rsetindex==11) pucch_pdu->initial_cyclic_shift*=6; - else if (rsetindex==1||rsetindex==2) pucch_pdu->initial_cyclic_shift*=3; - else pucch_pdu->initial_cyclic_shift*=4; - pucch_pdu->nr_of_symbols = default_pucch_numbsymb[rsetindex]; - pucch_pdu->start_symbol_index = default_pucch_firstsymb[rsetindex]; - if (pucch_pdu->format_type == 1) pucch_pdu->time_domain_occ_idx = 0; // check this!! - pucch_pdu->sr_flag = O_sr; + if (N2O_uci) { + if (pucch_resource < n_list) + resource_id = pucchresset->resourceList.list.array[pucch_resource]; + else + AssertFatal(1==0,"Couldn't fine pucch resource indicator %d in PUCCH resource set %d for %d UCI bits",pucch_resource,i,O_uci); + } + else N2 = N3; } + } + AssertFatal(resource_id!=NULL,"Couldn-t find any matching PUCCH resource in the PUCCH resource sets"); + + AssertFatal(pucch_Config->resourceToAddModList!=NULL, + "PUCCH resourceToAddModList is null\n"); + + n_list = pucch_Config->resourceToAddModList->list.count; + AssertFatal(n_list>0,"PUCCH resourceToAddModList is empty\n"); + + // going through the list of PUCCH resources to find the one indexed by resource_id + for (int i=0; iresourceToAddModList->list.array[i]; + if (pucchres->pucch_ResourceId == *resource_id) { + res_found = 1; + pucch_pdu->prb_start = pucchres->startingPRB; + pucch_pdu->rnti = rnti; + // FIXME why there is only one frequency hopping flag + // what about inter slot frequency hopping? + pucch_pdu->freq_hop_flag = pucchres->intraSlotFrequencyHopping!= NULL ? 1 : 0; + pucch_pdu->second_hop_prb = pucchres->secondHopPRB!= NULL ? *pucchres->secondHopPRB : 0; + switch(pucchres->format.present) { + case NR_PUCCH_Resource__format_PR_format0 : + pucch_pdu->format_type = 0; + pucch_pdu->initial_cyclic_shift = pucchres->format.choice.format0->initialCyclicShift; + pucch_pdu->nr_of_symbols = pucchres->format.choice.format0->nrofSymbols; + pucch_pdu->start_symbol_index = pucchres->format.choice.format0->startingSymbolIndex; + pucch_pdu->sr_flag = O_sr; + break; + case NR_PUCCH_Resource__format_PR_format1 : + pucch_pdu->format_type = 1; + pucch_pdu->initial_cyclic_shift = pucchres->format.choice.format1->initialCyclicShift; + pucch_pdu->nr_of_symbols = pucchres->format.choice.format1->nrofSymbols; + pucch_pdu->start_symbol_index = pucchres->format.choice.format1->startingSymbolIndex; + pucch_pdu->time_domain_occ_idx = pucchres->format.choice.format1->timeDomainOCC; + pucch_pdu->sr_flag = O_sr; + break; + case NR_PUCCH_Resource__format_PR_format2 : + pucch_pdu->format_type = 2; + pucch_pdu->nr_of_symbols = pucchres->format.choice.format2->nrofSymbols; + pucch_pdu->start_symbol_index = pucchres->format.choice.format2->startingSymbolIndex; + pucch_pdu->data_scrambling_id = pusch_id!= NULL ? *pusch_id : *scc->physCellId; + pucch_pdu->dmrs_scrambling_id = id0!= NULL ? *id0 : *scc->physCellId; + pucch_pdu->prb_size = compute_pucch_prb_size(2,pucchres->format.choice.format2->nrofPRBs, + O_uci+O_sr,O_csi,pucch_Config->format2->choice.setup->maxCodeRate, + 2,pucchres->format.choice.format2->nrofSymbols,8); + pucch_pdu->bit_len_csi_part1 = O_csi; + break; + case NR_PUCCH_Resource__format_PR_format3 : + pucch_pdu->format_type = 3; + pucch_pdu->nr_of_symbols = pucchres->format.choice.format3->nrofSymbols; + pucch_pdu->start_symbol_index = pucchres->format.choice.format3->startingSymbolIndex; + pucch_pdu->data_scrambling_id = pusch_id!= NULL ? *pusch_id : *scc->physCellId; + if (pucch_Config->format3 == NULL) { + pucch_pdu->pi_2bpsk = 0; + pucch_pdu->add_dmrs_flag = 0; + } + else { + pucchfmt = pucch_Config->format3->choice.setup; + pucch_pdu->pi_2bpsk = pucchfmt->pi2BPSK!= NULL ? 1 : 0; + pucch_pdu->add_dmrs_flag = pucchfmt->additionalDMRS!= NULL ? 1 : 0; + } + int f3_dmrs_symbols; + if (pucchres->format.choice.format3->nrofSymbols==4) + f3_dmrs_symbols = 1<freq_hop_flag; + else { + if(pucchres->format.choice.format3->nrofSymbols<10) + f3_dmrs_symbols = 2; + else + f3_dmrs_symbols = 2<add_dmrs_flag; + } + pucch_pdu->prb_size = compute_pucch_prb_size(3,pucchres->format.choice.format3->nrofPRBs, + O_uci+O_sr,O_csi,pucch_Config->format3->choice.setup->maxCodeRate, + 2-pucch_pdu->pi_2bpsk,pucchres->format.choice.format3->nrofSymbols-f3_dmrs_symbols,12); + pucch_pdu->bit_len_csi_part1 = O_csi; + break; + case NR_PUCCH_Resource__format_PR_format4 : + pucch_pdu->format_type = 4; + pucch_pdu->nr_of_symbols = pucchres->format.choice.format4->nrofSymbols; + pucch_pdu->start_symbol_index = pucchres->format.choice.format4->startingSymbolIndex; + pucch_pdu->pre_dft_occ_len = pucchres->format.choice.format4->occ_Length; + pucch_pdu->pre_dft_occ_idx = pucchres->format.choice.format4->occ_Index; + pucch_pdu->data_scrambling_id = pusch_id!= NULL ? *pusch_id : *scc->physCellId; + if (pucch_Config->format3 == NULL) { + pucch_pdu->pi_2bpsk = 0; + pucch_pdu->add_dmrs_flag = 0; + } + else { + pucchfmt = pucch_Config->format3->choice.setup; + pucch_pdu->pi_2bpsk = pucchfmt->pi2BPSK!= NULL ? 1 : 0; + pucch_pdu->add_dmrs_flag = pucchfmt->additionalDMRS!= NULL ? 1 : 0; + } + pucch_pdu->bit_len_csi_part1 = O_csi; + break; + default : + AssertFatal(1==0,"Undefined PUCCH format \n"); + } + } + } + AssertFatal(res_found==1,"No PUCCH resource found corresponding to id %ld\n",*resource_id); + } + else { // this is the default PUCCH configuration, PUCCH format 0 or 1 + int rsetindex = *scc->uplinkConfigCommon->initialUplinkBWP->pucch_ConfigCommon->choice.setup->pucch_ResourceCommon; + int prboffset = r_pucch/default_pucch_csset[rsetindex]; + int prboffsetm8 = (r_pucch-8)/default_pucch_csset[rsetindex]; + pucch_pdu->prb_start = (r_pucch>>3)==0 ? + default_pucch_prboffset[rsetindex] + prboffset: + pucch_pdu->bwp_size-1-default_pucch_prboffset[rsetindex]-prboffsetm8; + pucch_pdu->rnti = rnti; + pucch_pdu->freq_hop_flag = 1; + pucch_pdu->second_hop_prb = (r_pucch>>3)==0? + pucch_pdu->bwp_size-1-default_pucch_prboffset[rsetindex]-prboffset: + default_pucch_prboffset[rsetindex] + prboffsetm8; + pucch_pdu->format_type = default_pucch_fmt[rsetindex]; + pucch_pdu->initial_cyclic_shift = r_pucch%default_pucch_csset[rsetindex]; + if (rsetindex==3||rsetindex==7||rsetindex==11) pucch_pdu->initial_cyclic_shift*=6; + else if (rsetindex==1||rsetindex==2) pucch_pdu->initial_cyclic_shift*=3; + else pucch_pdu->initial_cyclic_shift*=4; + pucch_pdu->nr_of_symbols = default_pucch_numbsymb[rsetindex]; + pucch_pdu->start_symbol_index = default_pucch_firstsymb[rsetindex]; + if (pucch_pdu->format_type == 1) pucch_pdu->time_domain_occ_idx = 0; // check this!! + pucch_pdu->sr_flag = O_sr; + } } diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c index cb3414a1a1..d20a8b6fa0 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c @@ -1101,7 +1101,7 @@ bool nr_acknack_scheduling(int mod_id, int UE_id, frame_t frame, sub_frame_t slot, - int r_pucch) + int r_pucch) { const NR_ServingCellConfigCommon_t *scc = RC.nrmac[mod_id]->common_channels->ServingCellConfigCommon; const int n_slots_frame = nr_slots_per_frame[*scc->ssbSubcarrierSpacing]; @@ -1355,81 +1355,6 @@ void csi_period_offset(const NR_CSI_ReportConfig_t *csirep, } } -uint16_t compute_pucch_prb_size(uint8_t format, - uint8_t nr_prbs, - uint16_t O_tot, - uint16_t O_csi, - NR_PUCCH_MaxCodeRate_t *maxCodeRate, - uint8_t Qm, - uint8_t n_symb, - uint8_t n_re_ctrl) { - - uint16_t O_crc; - - if (O_tot<12) - O_crc = 0; - else{ - if (O_tot<20) - O_crc = 6; - else { - if (O_tot<360) - O_crc = 11; - else - AssertFatal(1==0,"Case for segmented PUCCH not yet implemented"); - } - } - - int rtimes100; - switch(*maxCodeRate){ - case NR_PUCCH_MaxCodeRate_zeroDot08 : - rtimes100 = 8; - break; - case NR_PUCCH_MaxCodeRate_zeroDot15 : - rtimes100 = 15; - break; - case NR_PUCCH_MaxCodeRate_zeroDot25 : - rtimes100 = 25; - break; - case NR_PUCCH_MaxCodeRate_zeroDot35 : - rtimes100 = 35; - break; - case NR_PUCCH_MaxCodeRate_zeroDot45 : - rtimes100 = 45; - break; - case NR_PUCCH_MaxCodeRate_zeroDot60 : - rtimes100 = 60; - break; - case NR_PUCCH_MaxCodeRate_zeroDot80 : - rtimes100 = 80; - break; - default : - AssertFatal(1==0,"Invalid MaxCodeRate"); - } - - float r = (float)rtimes100/100; - - if (O_csi == O_tot) { - if ((O_tot+O_csi)>(nr_prbs*n_re_ctrl*n_symb*Qm*r)) - AssertFatal(1==0,"MaxCodeRate %.2f can't support %d UCI bits and %d CRC bits with %d PRBs", - r,O_tot,O_crc,nr_prbs); - else - return nr_prbs; - } - - if (format==2){ - // TODO fix this for multiple CSI reports - for (int i=1; i<=nr_prbs; i++){ - if((O_tot+O_crc)<=(i*n_symb*Qm*n_re_ctrl*r) && - (O_tot+O_crc)>((i-1)*n_symb*Qm*n_re_ctrl*r)) - return i; - } - AssertFatal(1==0,"MaxCodeRate %.2f can't support %d UCI bits and %d CRC bits with at most %d PRBs", - r,O_tot,O_crc,nr_prbs); - } - else{ - AssertFatal(1==0,"Not yet implemented"); - } -} void nr_sr_reporting(int Mod_idP, frame_t SFN, sub_frame_t slot) { diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h index c23af53eed..9dfeae67d6 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h +++ b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h @@ -327,15 +327,6 @@ int allocate_nr_CCEs(gNB_MAC_INST *nr_mac, int m, int nr_of_candidates); -uint16_t compute_pucch_prb_size(uint8_t format, - uint8_t nr_prbs, - uint16_t O_tot, - uint16_t O_csi, - NR_PUCCH_MaxCodeRate_t *maxCodeRate, - uint8_t Qm, - uint8_t n_symb, - uint8_t n_re_ctrl); - int nr_get_default_pucch_res(int pucch_ResourceCommon); void compute_csi_bitlen(NR_CSI_MeasConfig_t *csi_MeasConfig, NR_UE_info_t *UE_info, int UE_id, module_id_t Mod_idP); diff --git a/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c b/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c index 876bdafd05..5acc413f38 100644 --- a/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c +++ b/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c @@ -81,6 +81,7 @@ int handle_dci(module_id_t module_id, int cc_id, unsigned int gNB_index, frame_t // Note: sdu should always be processed because data and timing advance updates are transmitted by the UE int8_t handle_dlsch (nr_downlink_indication_t *dl_info, NR_UL_TIME_ALIGNMENT_t *ul_time_alignment, int pdu_id){ + update_harq_status(dl_info, pdu_id); nr_ue_send_sdu(dl_info, ul_time_alignment, pdu_id); return 0; @@ -98,9 +99,12 @@ int nr_ue_ul_indication(nr_uplink_indication_t *ul_info){ NR_TDD_UL_DL_ConfigCommon_t *tdd_UL_DL_ConfigurationCommon = mac->scc != NULL ? mac->scc->tdd_UL_DL_ConfigurationCommon : mac->scc_SIB->tdd_UL_DL_ConfigurationCommon; - if (is_nr_UL_slot(tdd_UL_DL_ConfigurationCommon, ul_info->slot_tx, mac->frame_type) /*&& get_softmodem_params()->do_ra*/) + if (is_nr_UL_slot(tdd_UL_DL_ConfigurationCommon, ul_info->slot_tx, mac->frame_type) && !get_softmodem_params()->phy_test) nr_ue_prach_scheduler(module_id, ul_info->frame_tx, ul_info->slot_tx, ul_info->thread_id); + if (is_nr_UL_slot(tdd_UL_DL_ConfigurationCommon, ul_info->slot_tx, mac->frame_type)) + nr_ue_pucch_scheduler(module_id, ul_info->frame_tx, ul_info->slot_tx, ul_info->thread_id); + switch(ret){ case UE_CONNECTION_OK: break; @@ -178,10 +182,10 @@ int nr_ue_dl_indication(nr_downlink_indication_t *dl_info, NR_UL_TIME_ALIGNMENT_ case FAPI_NR_RX_PDU_TYPE_SIB: ret_mask |= (handle_bcch_dlsch(dl_info->module_id, - dl_info->cc_id, dl_info->gNB_index, - (dl_info->rx_ind->rx_indication_body+i)->sib_pdu.sibs_mask, - (dl_info->rx_ind->rx_indication_body+i)->sib_pdu.pdu, - (dl_info->rx_ind->rx_indication_body+i)->sib_pdu.pdu_length)) << FAPI_NR_RX_PDU_TYPE_SIB; + dl_info->cc_id, dl_info->gNB_index, + (dl_info->rx_ind->rx_indication_body+i)->sib_pdu.sibs_mask, + (dl_info->rx_ind->rx_indication_body+i)->sib_pdu.pdu, + (dl_info->rx_ind->rx_indication_body+i)->sib_pdu.pdu_length)) << FAPI_NR_RX_PDU_TYPE_SIB; break; From 5bf3b09a48231ebebc3b456f56dd526862e33d73 Mon Sep 17 00:00:00 2001 From: francescomani Date: Wed, 19 May 2021 10:06:56 +0200 Subject: [PATCH 13/91] adding call to fill_scheduled_response --- openair1/SCHED_NR_UE/fapi_nr_ue_l1.c | 3 ++- openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c | 5 +++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c b/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c index 7fb190931e..e30f2c8bd3 100644 --- a/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c +++ b/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c @@ -150,7 +150,7 @@ int8_t nr_ue_scheduled_response(nr_scheduled_response_t *scheduled_response){ AssertFatal(ul_config->ul_config_list[i].pdu_type <= FAPI_NR_UL_CONFIG_TYPES,"pdu_type %d out of bounds\n",ul_config->ul_config_list[i].pdu_type); LOG_D(PHY, "In %s: processing %s PDU of %d total UL PDUs (ul_config %p) \n", __FUNCTION__, ul_pdu_type[ul_config->ul_config_list[i].pdu_type - 1], ul_config->number_pdus, ul_config); - uint8_t pdu_type = ul_config->ul_config_list[i].pdu_type, pucch_resource_id, current_harq_pid, format, gNB_id = 0; + uint8_t pdu_type = ul_config->ul_config_list[i].pdu_type, current_harq_pid, gNB_id = 0; /* PRACH */ //NR_PRACH_RESOURCES_t *prach_resources; fapi_nr_ul_config_prach_pdu *prach_config_pdu; @@ -199,6 +199,7 @@ int8_t nr_ue_scheduled_response(nr_scheduled_response_t *scheduled_response){ pucch_config_pdu = &ul_config->ul_config_list[i].pucch_config_pdu; for(int j=0; j<2; j++) { if(pucch_vars->active[j] == false) { + LOG_D(PHY,"%d.%d Copying pucch pdu to UE PHY\n",scheduled_response->frame,slot); memcpy((void*)&(pucch_vars->pucch_pdu[j]), (void*)pucch_config_pdu, sizeof(fapi_nr_ul_config_pucch_pdu)); found = true; } diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c index ae610b75bf..d0a56ab9b6 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c @@ -1849,6 +1849,7 @@ void nr_ue_pucch_scheduler(module_id_t module_idP, frame_t frameP, int slotP, in N_UCI = O_SR + O_ACK + O_CSI; if (N_UCI > 0) { + pucch->resource_set_id = find_pucch_resource_set(mac, N_UCI); select_pucch_resource(mac, pucch); fapi_nr_ul_config_request_t *ul_config = get_ul_config_request(mac, slotP); @@ -1860,6 +1861,10 @@ void nr_ue_pucch_scheduler(module_id_t module_idP, frame_t frameP, int slotP, in pucch_pdu, O_SR, O_ACK, O_CSI); fill_ul_config(ul_config, frameP, slotP, FAPI_NR_UL_CONFIG_TYPE_PUCCH); + nr_scheduled_response_t scheduled_response; + fill_scheduled_response(&scheduled_response, NULL, ul_config, NULL, module_idP, 0 /*TBR fix*/, frameP, slotP, thread_id); + if(mac->if_module != NULL && mac->if_module->scheduled_response != NULL) + mac->if_module->scheduled_response(&scheduled_response); } } From f0c0a303d2f4d2e842c478768f0c4f70e7325260 Mon Sep 17 00:00:00 2001 From: francescomani Date: Wed, 19 May 2021 10:15:55 +0200 Subject: [PATCH 14/91] fix compilation in pucch_nr debug case --- openair1/PHY/NR_UE_TRANSPORT/pucch_nr.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/openair1/PHY/NR_UE_TRANSPORT/pucch_nr.c b/openair1/PHY/NR_UE_TRANSPORT/pucch_nr.c index a28ac1bcc2..f3dfa698d0 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/pucch_nr.c +++ b/openair1/PHY/NR_UE_TRANSPORT/pucch_nr.c @@ -836,7 +836,7 @@ inline void nr_pucch2_3_4_scrambling(uint16_t M_bit,uint16_t rnti,uint16_t n_id, c = (uint8_t)((s>>i)&1); btildep[i] = (((B>>i)&1) ^ c); #ifdef DEBUG_NR_PUCCH_TX - printf("\t\t\t btilde[%d]=%lx 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 %d and scrambling %d (%x)\n",i+(iprime<<5),btilde[i],((B>>i)&1),c,s>>i); #endif } M_bit3-=32; @@ -961,7 +961,7 @@ void nr_generate_pucch2(PHY_VARS_NR_UE *ue, int nr_slot_tx, fapi_nr_ul_config_pucch_pdu *pucch_pdu) { #ifdef DEBUG_NR_PUCCH_TX - printf("\t [nr_generate_pucch2] start function at slot(nr_slot_tx)=%d with payload=%lu and nr_bit=%d\n",nr_slot_tx, payload, nr_bit); + printf("\t [nr_generate_pucch2] start function at slot(nr_slot_tx)=%d with payload=%lu and nr_bit=%d\n",nr_slot_tx, pucch_pdu->payload, pucch_pdu->n_bit); #endif // b is the block of bits transmitted on the physical channel after payload coding uint64_t b[16]; // limit to 1024-bit encoded length @@ -1131,7 +1131,7 @@ void nr_generate_pucch3_4(PHY_VARS_NR_UE *ue, int nr_slot_tx, fapi_nr_ul_config_pucch_pdu *pucch_pdu) { #ifdef DEBUG_NR_PUCCH_TX - printf("\t [nr_generate_pucch3_4] start function at slot(nr_slot_tx)=%d with payload=%lu and nr_bit=%d\n", nr_slot_tx, payload, nr_bit); + printf("\t [nr_generate_pucch3_4] start function at slot(nr_slot_tx)=%d with payload=%lu and nr_bit=%d\n", nr_slot_tx, pucch_pdu->payload, pucch_pdu->n_bit); #endif // b is the block of bits transmitted on the physical channel after payload coding uint64_t b[16]; From dbf3b724142ba2faefb868dc360ab28529320d5b Mon Sep 17 00:00:00 2001 From: francescomani Date: Thu, 20 May 2021 10:00:05 +0200 Subject: [PATCH 15/91] putting back downlink_harq_process and some other fixes --- openair1/SCHED_NR_UE/fapi_nr_ue_l1.c | 2 + openair1/SCHED_NR_UE/harq_nr.c | 55 +++++++++++++++++++++ openair1/SCHED_NR_UE/harq_nr.h | 2 +- openair1/SCHED_NR_UE/phy_procedures_nr_ue.c | 11 +++-- 4 files changed, 64 insertions(+), 6 deletions(-) diff --git a/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c b/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c index e30f2c8bd3..5fbd88987e 100644 --- a/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c +++ b/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c @@ -122,6 +122,7 @@ int8_t nr_ue_scheduled_response(nr_scheduled_response_t *scheduled_response){ dlsch0->g_pucch = dlsch_config_pdu->accumulated_delta_PUCCH; dlsch0_harq->Nl=1; dlsch0_harq->mcs_table=dlsch_config_pdu->mcs_table; + downlink_harq_process(dlsch0_harq, dlsch0->current_harq_pid, dlsch_config_pdu->ndi, dlsch0->rnti_type); if (dlsch0_harq->status != ACTIVE) { // dlsch0_harq->status not ACTIVE may be due to false retransmission. Reset the // following flag to skip PDSCH procedures in that case. @@ -201,6 +202,7 @@ int8_t nr_ue_scheduled_response(nr_scheduled_response_t *scheduled_response){ if(pucch_vars->active[j] == false) { LOG_D(PHY,"%d.%d Copying pucch pdu to UE PHY\n",scheduled_response->frame,slot); memcpy((void*)&(pucch_vars->pucch_pdu[j]), (void*)pucch_config_pdu, sizeof(fapi_nr_ul_config_pucch_pdu)); + pucch_vars->active[j] = true; found = true; } } diff --git a/openair1/SCHED_NR_UE/harq_nr.c b/openair1/SCHED_NR_UE/harq_nr.c index 06395c79e8..3f528f02d4 100644 --- a/openair1/SCHED_NR_UE/harq_nr.c +++ b/openair1/SCHED_NR_UE/harq_nr.c @@ -308,4 +308,59 @@ void init_downlink_harq_status(NR_DL_UE_HARQ_t *dl_harq) dl_harq->status = SCH_IDLE; dl_harq->first_tx = 1; dl_harq->round = 0; + dl_harq->ack = DL_ACKNACK_NO_SET; } + +/******************************************************************* +* +* NAME : downlink_harq_process +* +* PARAMETERS : downlink harq context +* harq identifier +* ndi (new data indicator) from DCI +* rnti_type from DCI +* +* RETURN : none +* +* DESCRIPTION : manage downlink information from DCI for downlink transmissions/retransmissions +* TS 38.321 5.3.1 DL Assignment reception +* TS 38.321 5.3.2 HARQ operation +* +*********************************************************************/ + +void downlink_harq_process(NR_DL_UE_HARQ_t *dl_harq, int harq_pid, int ndi, uint8_t rnti_type) { + + if (rnti_type == _CS_RNTI_) { + LOG_E(PHY, "Fatal error in HARQ entity due to not supported CS_RNTI at line %d in function %s of file %s \n", __LINE__ , __func__, __FILE__); + return; + } + else if ((rnti_type != _C_RNTI_) && (rnti_type != _TC_RNTI_)) { + /* harq mechanism is not relevant for other rnti */ + return; + } + + if (dl_harq->first_tx == 1) { + dl_harq->round = 0; + dl_harq->status = ACTIVE; + dl_harq->DCINdi = ndi; + dl_harq->first_tx = 0; + + LOG_D(PHY, "[HARQ-DL-PDSCH harqId : %d] first new reception \n", harq_pid); + } + else if (dl_harq->DCINdi != ndi) { + dl_harq->round = 0; + dl_harq->status = ACTIVE; + dl_harq->DCINdi = ndi; + + LOG_D(PHY, "[HARQ-DL-PDSCH harqId : %d] new reception due to toogle of ndi \n", harq_pid); + } + else { + + dl_harq->round++; + + if (dl_harq->ack) dl_harq->status = SCH_IDLE; + + LOG_D(PHY, "[HARQ-DL-PDSCH harqId : %d] reception of a retransmission \n", harq_pid); + } +} + diff --git a/openair1/SCHED_NR_UE/harq_nr.h b/openair1/SCHED_NR_UE/harq_nr.h index 8b48886d88..47d1de8a11 100644 --- a/openair1/SCHED_NR_UE/harq_nr.h +++ b/openair1/SCHED_NR_UE/harq_nr.h @@ -120,7 +120,7 @@ void init_downlink_harq_status(NR_DL_UE_HARQ_t *dl_harq); @param rnti_type type of rnti @returns retransmission or new transmission */ -harq_result_t downlink_harq_process(NR_DL_UE_HARQ_t *dlsch, int harq_pid, int ndi, uint8_t rnti_type); +void downlink_harq_process(NR_DL_UE_HARQ_t *dlsch, int harq_pid, int ndi, uint8_t rnti_type); #undef EXTERN #undef INIT_VARIABLES_HARQ_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 028009e75b..2b8678da0e 100644 --- a/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c +++ b/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c @@ -1786,13 +1786,14 @@ int phy_procedures_nrUE_RX(PHY_VARS_NR_UE *ue, // do procedures for C-RNTI int ret_pdsch = 0; if (ue->dlsch[proc->thread_id][gNB_id][0]->active == 1) { + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDSCH_PROC_C, VCD_FUNCTION_IN); ret_pdsch = nr_ue_pdsch_procedures(ue, - proc, - gNB_id, - PDSCH, - ue->dlsch[proc->thread_id][gNB_id][0], - NULL); + proc, + gNB_id, + PDSCH, + ue->dlsch[proc->thread_id][gNB_id][0], + NULL); nr_ue_measurement_procedures(2, ue, proc, gNB_id, nr_slot_rx); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDSCH_PROC_C, VCD_FUNCTION_OUT); From 2ffceb333cec7a0befcf7ee5931e65a52ff97d09 Mon Sep 17 00:00:00 2001 From: francescomani Date: Fri, 21 May 2021 18:19:16 +0200 Subject: [PATCH 16/91] function for SR periodicity in mac common --- openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c | 60 +++++++++++++++++ openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h | 2 + .../LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c | 64 +------------------ openair2/LAYER2/NR_MAC_gNB/mac_proto.h | 4 -- 4 files changed, 63 insertions(+), 67 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c index cb5ee8fee3..1801098ffc 100644 --- a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c +++ b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c @@ -3537,6 +3537,66 @@ void get_type0_PDCCH_CSS_config_parameters(NR_Type0_PDCCH_CSS_config_t *type0_PD } +void find_period_offest_SR (NR_SchedulingRequestResourceConfig_t *SchedulingReqRec, int *period, int *offset) { + NR_SchedulingRequestResourceConfig__periodicityAndOffset_PR P_O = SchedulingReqRec->periodicityAndOffset->present; + switch (P_O){ + case NR_SchedulingRequestResourceConfig__periodicityAndOffset_PR_sl1: + *period = 1; + *offset = SchedulingReqRec->periodicityAndOffset->choice.sl1; + break; + case NR_SchedulingRequestResourceConfig__periodicityAndOffset_PR_sl2: + *period = 2; + *offset = SchedulingReqRec->periodicityAndOffset->choice.sl2; + break; + case NR_SchedulingRequestResourceConfig__periodicityAndOffset_PR_sl4: + *period = 4; + *offset = SchedulingReqRec->periodicityAndOffset->choice.sl4; + break; + case NR_SchedulingRequestResourceConfig__periodicityAndOffset_PR_sl5: + *period = 5; + *offset = SchedulingReqRec->periodicityAndOffset->choice.sl5; + break; + case NR_SchedulingRequestResourceConfig__periodicityAndOffset_PR_sl8: + *period = 8; + *offset = SchedulingReqRec->periodicityAndOffset->choice.sl8; + break; + case NR_SchedulingRequestResourceConfig__periodicityAndOffset_PR_sl10: + *period = 10; + *offset = SchedulingReqRec->periodicityAndOffset->choice.sl10; + break; + case NR_SchedulingRequestResourceConfig__periodicityAndOffset_PR_sl16: + *period = 16; + *offset = SchedulingReqRec->periodicityAndOffset->choice.sl16; + break; + case NR_SchedulingRequestResourceConfig__periodicityAndOffset_PR_sl20: + *period = 20; + *offset = SchedulingReqRec->periodicityAndOffset->choice.sl20; + break; + case NR_SchedulingRequestResourceConfig__periodicityAndOffset_PR_sl40: + *period = 40; + *offset = SchedulingReqRec->periodicityAndOffset->choice.sl40; + break; + case NR_SchedulingRequestResourceConfig__periodicityAndOffset_PR_sl80: + *period = 80; + *offset = SchedulingReqRec->periodicityAndOffset->choice.sl80; + break; + case NR_SchedulingRequestResourceConfig__periodicityAndOffset_PR_sl160: + *period = 160; + *offset = SchedulingReqRec->periodicityAndOffset->choice.sl160; + break; + case NR_SchedulingRequestResourceConfig__periodicityAndOffset_PR_sl320: + *period = 320; + *offset = SchedulingReqRec->periodicityAndOffset->choice.sl320; + break; + case NR_SchedulingRequestResourceConfig__periodicityAndOffset_PR_sl640: + *period = 640; + *offset = SchedulingReqRec->periodicityAndOffset->choice.sl640; + break; + default: + AssertFatal(1==0,"No periodicityAndOffset resources found in schedulingrequestresourceconfig"); + } +} + uint16_t compute_pucch_prb_size(uint8_t format, uint8_t nr_prbs, uint16_t O_tot, diff --git a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h index cb3d25352b..088a82d210 100644 --- a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h +++ b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h @@ -150,6 +150,8 @@ uint16_t compute_pucch_prb_size(uint8_t format, int16_t get_N_RA_RB (int delta_f_RA_PRACH,int delta_f_PUSCH); +void find_period_offest_SR (NR_SchedulingRequestResourceConfig_t *SchedulingReqRec, int *period, int *offset); + bool set_dl_ptrs_values(NR_PTRS_DownlinkConfig_t *ptrs_config, uint16_t rbSize, uint8_t mcsIndex, uint8_t mcsTable, uint8_t *K_ptrs, uint8_t *L_ptrs,uint8_t *portIndex, diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c index d20a8b6fa0..8264b76856 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c @@ -1387,7 +1387,7 @@ void nr_sr_reporting(int Mod_idP, frame_t SFN, sub_frame_t slot) int SR_period; int SR_offset; - periodicity__SRR(SchedulingRequestResourceConfig,&SR_period,&SR_offset); + find_period_offest_SR(SchedulingRequestResourceConfig,&SR_period,&SR_offset); // convert to int to avoid underflow of uint int sfn_sf = SFN * n_slots_frame + slot; if ((sfn_sf - SR_offset) % SR_period != 0) @@ -1456,65 +1456,3 @@ void nr_sr_reporting(int Mod_idP, frame_t SFN, sub_frame_t slot) } } - -void periodicity__SRR (NR_SchedulingRequestResourceConfig_t *SchedulingReqRec, int *period, int *offset) -{ - NR_SchedulingRequestResourceConfig__periodicityAndOffset_PR P_O = SchedulingReqRec->periodicityAndOffset->present; - switch (P_O){ - case NR_SchedulingRequestResourceConfig__periodicityAndOffset_PR_sl1: - *period = 1; - *offset = SchedulingReqRec->periodicityAndOffset->choice.sl1; - break; - case NR_SchedulingRequestResourceConfig__periodicityAndOffset_PR_sl2: - *period = 2; - *offset = SchedulingReqRec->periodicityAndOffset->choice.sl2; - break; - case NR_SchedulingRequestResourceConfig__periodicityAndOffset_PR_sl4: - *period = 4; - *offset = SchedulingReqRec->periodicityAndOffset->choice.sl4; - break; - case NR_SchedulingRequestResourceConfig__periodicityAndOffset_PR_sl5: - *period = 5; - *offset = SchedulingReqRec->periodicityAndOffset->choice.sl5; - break; - case NR_SchedulingRequestResourceConfig__periodicityAndOffset_PR_sl8: - *period = 8; - *offset = SchedulingReqRec->periodicityAndOffset->choice.sl8; - break; - case NR_SchedulingRequestResourceConfig__periodicityAndOffset_PR_sl10: - *period = 10; - *offset = SchedulingReqRec->periodicityAndOffset->choice.sl10; - break; - case NR_SchedulingRequestResourceConfig__periodicityAndOffset_PR_sl16: - *period = 16; - *offset = SchedulingReqRec->periodicityAndOffset->choice.sl16; - break; - case NR_SchedulingRequestResourceConfig__periodicityAndOffset_PR_sl20: - *period = 20; - *offset = SchedulingReqRec->periodicityAndOffset->choice.sl20; - break; - case NR_SchedulingRequestResourceConfig__periodicityAndOffset_PR_sl40: - *period = 40; - *offset = SchedulingReqRec->periodicityAndOffset->choice.sl40; - break; - case NR_SchedulingRequestResourceConfig__periodicityAndOffset_PR_sl80: - *period = 80; - *offset = SchedulingReqRec->periodicityAndOffset->choice.sl80; - break; - case NR_SchedulingRequestResourceConfig__periodicityAndOffset_PR_sl160: - *period = 160; - *offset = SchedulingReqRec->periodicityAndOffset->choice.sl160; - break; - case NR_SchedulingRequestResourceConfig__periodicityAndOffset_PR_sl320: - *period = 320; - *offset = SchedulingReqRec->periodicityAndOffset->choice.sl320; - break; - case NR_SchedulingRequestResourceConfig__periodicityAndOffset_PR_sl640: - *period = 640; - *offset = SchedulingReqRec->periodicityAndOffset->choice.sl640; - break; - default: - AssertFatal(1==0,"No periodicityAndOffset resources found in schedulingrequestresourceconfig"); - } -} - diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h index 9dfeae67d6..5734820aaa 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h +++ b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h @@ -416,8 +416,4 @@ bool nr_find_nb_rb(uint16_t Qm, void nr_sr_reporting(int Mod_idP, frame_t frameP, sub_frame_t slotP); -void periodicity__SRR (NR_SchedulingRequestResourceConfig_t *SchedulingReqRecconf, - int *period, - int *offset); - #endif /*__LAYER2_NR_MAC_PROTO_H__*/ From 049c8314f97b9ab72f9e392877e10e4dcb8baf5b Mon Sep 17 00:00:00 2001 From: francescomani Date: Mon, 24 May 2021 10:29:09 +0200 Subject: [PATCH 17/91] triggering SR transmission at UE --- openair1/SCHED_NR_UE/pucch_uci_ue_nr.c | 56 ---------- openair1/SCHED_NR_UE/pucch_uci_ue_nr.h | 8 -- openair2/LAYER2/NR_MAC_UE/mac_proto.h | 18 +--- openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c | 106 ++++++++++++++++--- openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c | 5 + 5 files changed, 101 insertions(+), 92 deletions(-) diff --git a/openair1/SCHED_NR_UE/pucch_uci_ue_nr.c b/openair1/SCHED_NR_UE/pucch_uci_ue_nr.c index cc12589e78..a7ef1f3ae0 100644 --- a/openair1/SCHED_NR_UE/pucch_uci_ue_nr.c +++ b/openair1/SCHED_NR_UE/pucch_uci_ue_nr.c @@ -58,10 +58,6 @@ uint8_t nr_is_cqi_TXOp(PHY_VARS_NR_UE *ue,UE_nr_rxtx_proc_t *proc,uint8_t gNB_id); uint8_t nr_is_ri_TXOp(PHY_VARS_NR_UE *ue,UE_nr_rxtx_proc_t *proc,uint8_t gNB_id); -static const uint16_t scheduling_request_periodicity[NB_SR_PERIOD] -= { 0, 0, 1, 2, 4, 5, 8, 10, 16, 20, 40, 80, 160, 320, 640 } -; - /* TS 36.213 Table 9.2.5.2-1: Code rate corresponding to higher layer parameter PUCCH-F2-maximum-coderate, */ /* or PUCCH-F3-maximum-coderate, or PUCCH-F4-maximum-coderate */ /* add one additional element set to 0 for parsing the array until this end */ @@ -490,59 +486,7 @@ boolean_t check_pucch_format(NR_UE_MAC_INST_t *mac, uint8_t gNB_id, pucch_format } } -/******************************************************************* -* -* NAME : trigger_periodic_scheduling_request -* -* PARAMETERS : pointer to resource set -* -* RETURN : 1 if peridic scheduling request is triggered -* 0 no periodic scheduling request -* -* DESCRIPTION : TS 38.213 9.2.4 UE procedure for reporting SR -* -*********************************************************************/ -int trigger_periodic_scheduling_request(PHY_VARS_NR_UE *ue, uint8_t gNB_id, UE_nr_rxtx_proc_t *proc) -{ - const int max_sr_periodicity[NB_NUMEROLOGIES_NR] = { 80, 160, 320, 640, 640 }; - - int active_scheduling_request = ue->scheduling_request_config_nr[gNB_id].active_sr_id; - - /* is there any valid scheduling request configuration */ - if (ue->scheduling_request_config_nr[gNB_id].sr_ResourceConfig[active_scheduling_request] == NULL) { - return (0); - } - - if (ue->scheduling_request_config_nr[gNB_id].sr_ResourceConfig[active_scheduling_request]->periodicity < 2) { - LOG_W(PHY,"PUCCH Not supported scheduling request period smaller than 1 slot : at line %d in function %s of file %s \n", LINE_FILE , __func__, FILE_NAME); - return (0); - } - - int16_t SR_periodicity = scheduling_request_periodicity[ue->scheduling_request_config_nr[gNB_id].sr_ResourceConfig[active_scheduling_request]->periodicity]; - uint16_t SR_offset = ue->scheduling_request_config_nr[gNB_id].sr_ResourceConfig[active_scheduling_request]->offset; - - if (SR_periodicity > max_sr_periodicity[ue->frame_parms.numerology_index]) { - LOG_W(PHY,"PUCCH Invalid scheduling request period : at line %d in function %s of file %s \n", LINE_FILE , __func__, FILE_NAME); - return (0); - } - - if (SR_offset > SR_periodicity) { - LOG_E(PHY,"PUCCH SR offset %d is greater than SR periodicity %d : at line %d in function %s of file %s \n", SR_offset, SR_periodicity, LINE_FILE , __func__, FILE_NAME); - return (0); - } - else if (SR_periodicity == 1) { - return (1); /* period is slot */ - } - - int16_t N_slot_frame = ue->frame_parms.slots_per_frame; - if (((proc->frame_tx * N_slot_frame) + proc->nr_slot_tx - SR_offset)%SR_periodicity == 0) { - return (1); - } - else { - return (0); - } -} /******************************************************************* * diff --git a/openair1/SCHED_NR_UE/pucch_uci_ue_nr.h b/openair1/SCHED_NR_UE/pucch_uci_ue_nr.h index b218cf2b38..101b80fb8d 100644 --- a/openair1/SCHED_NR_UE/pucch_uci_ue_nr.h +++ b/openair1/SCHED_NR_UE/pucch_uci_ue_nr.h @@ -76,14 +76,6 @@ void pucch_procedures_ue_nr(PHY_VARS_NR_UE *ue, boolean_t check_pucch_format(NR_UE_MAC_INST_t *mac, uint8_t gNB_id, pucch_format_nr_t format_pucch, int nb_symbols_for_tx, int uci_size); -/** \brief This function selects a pucch resource - @param ue context - @param gNB_id identity - @param slots for rx and tx - @returns TRUE a scheduling request is triggered */ - -int trigger_periodic_scheduling_request(PHY_VARS_NR_UE *ue, uint8_t gNB_id, UE_nr_rxtx_proc_t *proc); - /** \brief This function reads current CSI @param ue context @param gNB_id identity diff --git a/openair2/LAYER2/NR_MAC_UE/mac_proto.h b/openair2/LAYER2/NR_MAC_UE/mac_proto.h index 328a931add..6915a62061 100755 --- a/openair2/LAYER2/NR_MAC_UE/mac_proto.h +++ b/openair2/LAYER2/NR_MAC_UE/mac_proto.h @@ -125,25 +125,17 @@ void fill_scheduled_response(nr_scheduled_response_t *scheduled_response, int slot, int thread_id); -/* \brief Get SR payload (0,1) from UE MAC -@param Mod_id Instance id of UE in machine -@param CC_id Component Carrier index -@param eNB_id Index of eNB that UE is attached to -@param rnti C_RNTI of UE -@param subframe subframe number -@returns 0 for no SR, 1 for SR -*/ -uint32_t ue_get_SR(module_id_t module_idP, int CC_id, frame_t frameP, - uint8_t eNB_id, rnti_t rnti, sub_frame_t subframe); - -int8_t nr_ue_get_SR(module_id_t module_idP, int CC_id, frame_t frameP, uint8_t eNB_id, uint16_t rnti, sub_frame_t subframe); +int8_t nr_ue_get_SR(module_id_t module_idP, frame_t frameP, int slotP); int8_t nr_ue_process_dci(module_id_t module_id, int cc_id, uint8_t gNB_index, frame_t frame, int slot, dci_pdu_rel15_t *dci, fapi_nr_dci_indication_pdu_t *dci_ind); int nr_ue_process_dci_indication_pdu(module_id_t module_id, int cc_id, int gNB_index, frame_t frame, int slot, fapi_nr_dci_indication_pdu_t *dci); uint32_t get_ssb_frame(uint32_t test); -uint32_t mr_ue_get_SR(module_id_t module_idP, int CC_id, frame_t frameP, uint8_t eNB_id, uint16_t rnti, sub_frame_t subframe); +bool trigger_periodic_scheduling_request(NR_UE_MAC_INST_t *mac, + PUCCH_sched_t *pucch, + frame_t frame, + int slot); /* \brief Get payload (MAC PDU) from UE PHY @param dl_info pointer to dl indication diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c index 753e1577a0..a709e6f5fd 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c @@ -1289,7 +1289,7 @@ void nr_ue_configure_pucch(NR_UE_MAC_INST_t *mac, mac->cg->spCellConfig->spCellConfigDedicated->pdsch_ServingCellConfig && mac->cg->spCellConfig->spCellConfigDedicated->pdsch_ServingCellConfig->choice.setup && mac->cg->spCellConfig->spCellConfigDedicated->pdsch_ServingCellConfig->choice.setup->codeBlockGroupTransmission != NULL) { - LOG_E(PHY,"PUCCH Unsupported code block group for serving cell config : at line %d in function %s of file %s \n", LINE_FILE , __func__, FILE_NAME); + LOG_E(MAC,"PUCCH Unsupported code block group for serving cell config : at line %d in function %s of file %s \n", LINE_FILE , __func__, FILE_NAME); return; } NR_PUCCH_Config_t *pucch_Config; @@ -1356,7 +1356,7 @@ void nr_ue_configure_pucch(NR_UE_MAC_INST_t *mac, pucch_pdu->second_hop_prb = pucchres->secondHopPRB!= NULL ? *pucchres->secondHopPRB : 0; if ((O_SR+O_CSI+O_SR) > (sizeof(uint64_t)*8)) { - LOG_E(PHY,"PUCCH number of UCI bits exceeds payload size : at line %d in function %s of file %s \n", LINE_FILE , __func__, FILE_NAME); + LOG_E(MAC,"PUCCH number of UCI bits exceeds payload size : at line %d in function %s of file %s \n", LINE_FILE , __func__, FILE_NAME); return; } pucch_pdu->payload = (pucch->csi_part1_payload << (O_ACK + O_SR)) | (pucch->sr_payload << O_ACK) | pucch->ack_payload; @@ -1487,7 +1487,7 @@ int16_t get_pucch_tx_power_ue(NR_UE_MAC_INST_t *mac, int16_t G_b_f_c = 0; if (pucch_Config->spatialRelationInfoToAddModList != NULL) { /* FFS TODO NR */ - LOG_E(PHY,"PUCCH Spatial relation infos are not yet implemented : at line %d in function %s of file %s \n", LINE_FILE , __func__, __FILE__); + LOG_E(MAC,"PUCCH Spatial relation infos are not yet implemented : at line %d in function %s of file %s \n", LINE_FILE , __func__, __FILE__); return (PUCCH_POWER_DEFAULT); } @@ -1497,7 +1497,7 @@ int16_t get_pucch_tx_power_ue(NR_UE_MAC_INST_t *mac, } else { G_b_f_c = pucch->delta_pucch; - LOG_D(PHY,"PUCCH Transmit power control command not yet implemented for NR : at line %d in function %s of file %s \n", LINE_FILE , __func__, __FILE__); + LOG_D(MAC,"PUCCH Transmit power control command not yet implemented for NR : at line %d in function %s of file %s \n", LINE_FILE , __func__, __FILE__); return (PUCCH_POWER_DEFAULT); } @@ -1558,13 +1558,13 @@ int16_t get_pucch_tx_power_ue(NR_UE_MAC_INST_t *mac, break; default: { - LOG_E(PHY,"PUCCH unknown pucch format : at line %d in function %s of file %s \n", LINE_FILE , __func__, __FILE__); + LOG_E(MAC,"PUCCH unknown pucch format : at line %d in function %s of file %s \n", LINE_FILE , __func__, __FILE__); return (0); } } if (*power_config->twoPUCCH_PC_AdjustmentStates > 1) { - LOG_E(PHY,"PUCCH power control adjustment states with 2 states not yet implemented : at line %d in function %s of file %s \n", LINE_FILE , __func__, __FILE__); + LOG_E(MAC,"PUCCH power control adjustment states with 2 states not yet implemented : at line %d in function %s of file %s \n", LINE_FILE , __func__, __FILE__); return (PUCCH_POWER_DEFAULT); } @@ -1738,13 +1738,13 @@ void select_pucch_resource(NR_UE_MAC_INST_t *mac, n_list = resourceSetToAddModList->list.count; if (pucch->resource_set_id > n_list) { - LOG_E(PHY,"Invalid PUCCH resource set id %d\n",pucch->resource_set_id); + LOG_E(MAC,"Invalid PUCCH resource set id %d\n",pucch->resource_set_id); pucch->pucch_resource = NULL; return; } n_list = resourceSetToAddModList->list.array[pucch->resource_set_id]->resourceList.list.count; if (pucch->resource_indicator > n_list) { - LOG_E(PHY,"Invalid PUCCH resource id %d\n",pucch->resource_indicator); + LOG_E(MAC,"Invalid PUCCH resource id %d\n",pucch->resource_indicator); pucch->pucch_resource = NULL; return; } @@ -1759,7 +1759,7 @@ void select_pucch_resource(NR_UE_MAC_INST_t *mac, } } if (res_found == 0) { - LOG_E(PHY,"Couldn't find PUCCH Resource\n"); + LOG_E(MAC,"Couldn't find PUCCH Resource\n"); pucch->pucch_resource = NULL; } } @@ -1861,18 +1861,18 @@ uint8_t get_downlink_ack(NR_UE_MAC_INST_t *mac, if (sched_frame == frame && sched_slot == slot) { if (current_harq->dai > NR_DL_MAX_DAI) { - LOG_E(PHY,"PUCCH Downlink DAI has an invalid value : at line %d in function %s of file %s \n", LINE_FILE , __func__, FILE_NAME); + LOG_E(MAC,"PUCCH Downlink DAI has an invalid value : at line %d in function %s of file %s \n", LINE_FILE , __func__, FILE_NAME); } else { if ((pucch->resource_indicator != -1) && (pucch->resource_indicator != current_harq->pucch_resource_indicator)) - LOG_E(PHY, "Value of pucch_resource_indicator %d not matching with what set before %d (Possibly due to a false DCI) \n", + LOG_E(MAC, "Value of pucch_resource_indicator %d not matching with what set before %d (Possibly due to a false DCI) \n", current_harq->pucch_resource_indicator,pucch->resource_indicator); else{ dai_current = current_harq->dai+1; // DCI DAI to counter DAI conversion if (dai_current == 0) { - LOG_E(PHY,"PUCCH Downlink dai is invalid : at line %d in function %s of file %s \n", LINE_FILE , __func__, FILE_NAME); + LOG_E(MAC,"PUCCH Downlink dai is invalid : at line %d in function %s of file %s \n", LINE_FILE , __func__, FILE_NAME); return(0); } else if (dai_current > dai_max) { dai_max = dai_current; @@ -1904,7 +1904,7 @@ uint8_t get_downlink_ack(NR_UE_MAC_INST_t *mac, return(0); } else if (number_harq_feedback > (sizeof(uint32_t)*8)) { - LOG_E(PHY,"PUCCH number of ack bits exceeds payload size : at line %d in function %s of file %s \n", LINE_FILE , __func__, FILE_NAME); + LOG_E(MAC,"PUCCH number of ack bits exceeds payload size : at line %d in function %s of file %s \n", LINE_FILE , __func__, FILE_NAME); return(0); } @@ -1989,7 +1989,7 @@ uint8_t get_downlink_ack(NR_UE_MAC_INST_t *mac, } if (number_harq_feedback != O_ACK) { - LOG_E(PHY,"PUCCH Error for number of bits for acknowledgment : at line %d in function %s of file %s \n", LINE_FILE , __func__, FILE_NAME); + LOG_E(MAC,"PUCCH Error for number of bits for acknowledgment : at line %d in function %s of file %s \n", LINE_FILE , __func__, FILE_NAME); return (0); } @@ -1998,8 +1998,84 @@ uint8_t get_downlink_ack(NR_UE_MAC_INST_t *mac, } -int8_t nr_ue_get_SR(module_id_t module_idP, int CC_id, frame_t frameP, uint8_t eNB_id, uint16_t rnti, sub_frame_t subframe){ +bool trigger_periodic_scheduling_request(NR_UE_MAC_INST_t *mac, + PUCCH_sched_t *pucch, + frame_t frame, + int slot) { + NR_BWP_Id_t bwp_id = mac->UL_BWP_Id; + NR_PUCCH_Config_t *pucch_Config = NULL; + int scs; + NR_BWP_Uplink_t *ubwp = mac->ULbwp[0]; + NR_BWP_UplinkCommon_t *initialUplinkBWP; + if (mac->scc) initialUplinkBWP = mac->scc->uplinkConfigCommon->initialUplinkBWP; + else initialUplinkBWP = &mac->scc_SIB->uplinkConfigCommon->initialUplinkBWP; + + if (mac->cg && ubwp && + mac->cg->spCellConfig && + mac->cg->spCellConfig->spCellConfigDedicated && + mac->cg->spCellConfig->spCellConfigDedicated->uplinkConfig && + mac->cg->spCellConfig->spCellConfigDedicated->uplinkConfig->initialUplinkBWP) { + scs = ubwp->bwp_Common->genericParameters.subcarrierSpacing; + } + else + scs = initialUplinkBWP->genericParameters.subcarrierSpacing; + + const int n_slots_frame = nr_slots_per_frame[scs]; + + if (bwp_id>0 && + mac->ULbwp[bwp_id-1] && + mac->ULbwp[bwp_id-1]->bwp_Dedicated && + mac->ULbwp[bwp_id-1]->bwp_Dedicated->pucch_Config && + mac->ULbwp[bwp_id-1]->bwp_Dedicated->pucch_Config->choice.setup) { + pucch_Config = mac->ULbwp[bwp_id-1]->bwp_Dedicated->pucch_Config->choice.setup; + } + else if (bwp_id==0 && + mac->cg && + mac->cg->spCellConfig && + mac->cg->spCellConfig->spCellConfigDedicated && + mac->cg->spCellConfig->spCellConfigDedicated->uplinkConfig && + mac->cg->spCellConfig->spCellConfigDedicated->uplinkConfig->initialUplinkBWP && + mac->cg->spCellConfig->spCellConfigDedicated->uplinkConfig->initialUplinkBWP->pucch_Config && + mac->cg->spCellConfig->spCellConfigDedicated->uplinkConfig->initialUplinkBWP->pucch_Config->choice.setup) { + pucch_Config = mac->cg->spCellConfig->spCellConfigDedicated->uplinkConfig->initialUplinkBWP->pucch_Config->choice.setup; + } + if(!pucch_Config || pucch_Config->schedulingRequestResourceToAddModList->list.count==0) + return false; // SR not configured + + for (int SR_resource_id =0; SR_resource_id < pucch_Config->schedulingRequestResourceToAddModList->list.count;SR_resource_id++) { + NR_SchedulingRequestResourceConfig_t *SchedulingRequestResourceConfig = pucch_Config->schedulingRequestResourceToAddModList->list.array[SR_resource_id]; + int SR_period; int SR_offset; + + find_period_offest_SR(SchedulingRequestResourceConfig,&SR_period,&SR_offset); + int sfn_sf = frame * n_slots_frame + slot; + + if ((sfn_sf - SR_offset) % SR_period == 0) { + LOG_D(MAC, "Scheduling Request active in frame %d slot %d \n", frame, slot); + NR_PUCCH_ResourceId_t *PucchResourceId = SchedulingRequestResourceConfig->resource; + + int found = -1; + NR_PUCCH_ResourceSet_t *pucchresset = pucch_Config->resourceSetToAddModList->list.array[0]; // set with formats 0,1 + int n_list = pucchresset->resourceList.list.count; + for (int i=0; iresourceList.list.array[i] == *PucchResourceId ) { + found = i; + break; + } + } + if (found == -1) { + LOG_E(MAC,"Couldn't find PUCCH resource for SR\n"); + return false; + } + pucch->resource_indicator = found; + return true; + } + } + return false; +} + + +int8_t nr_ue_get_SR(module_id_t module_idP, frame_t frameP, int slotP){ return 0; } diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c index d0a56ab9b6..1c89f866d2 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c @@ -1809,6 +1809,11 @@ void nr_ue_pucch_scheduler(module_id_t module_idP, frame_t frameP, int slotP, in uint16_t rnti = mac->crnti; //FIXME not sure this is valid for all pucch instances // SR + if(trigger_periodic_scheduling_request(mac, pucch, frameP, slotP)) + /* sr_payload = 1 means that this is a positive SR, sr_payload = 0 means that it is a negative SR */ + pucch->sr_payload = nr_ue_get_SR(module_idP, + frameP, + slotP); // CSI From 30c2746b9b997ac39630a32a8430afd101febe13 Mon Sep 17 00:00:00 2001 From: Sakthivel Velumani Date: Mon, 24 May 2021 20:07:43 +0200 Subject: [PATCH 18/91] call ul_indication again for PUCCH --- executables/nr-ue.c | 5 +++++ openair1/PHY/defs_nr_UE.h | 1 + openair1/SCHED_NR_UE/phy_procedures_nr_ue.c | 1 + openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c | 7 ++++++- openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.h | 9 +++++++++ 5 files changed, 22 insertions(+), 1 deletion(-) diff --git a/executables/nr-ue.c b/executables/nr-ue.c index 3ffbc621bc..78019f9d97 100644 --- a/executables/nr-ue.c +++ b/executables/nr-ue.c @@ -307,6 +307,7 @@ void processSlotTX(void *arg) { ul_indication.frame_tx = proc->frame_tx; ul_indication.slot_tx = proc->nr_slot_tx; ul_indication.thread_id = proc->thread_id; + ul_indication.ue_sched_mode = rxtxD->ue_sched_mode; UE->if_inst->ul_indication(&ul_indication); } @@ -358,6 +359,9 @@ void processSlotRX(void *arg) { nr_pdcp_tick(proc->frame_rx, proc->nr_slot_rx / UE->frame_parms.slots_per_subframe); } } + // calling UL_indication to schedule things other than PUSCH (eg, PUCCH) + rxtxD->ue_sched_mode = NOT_PUSCH; + processSlotTX(rxtxD); // Wait for PUSCH processing to finish notifiedFIFO_elt_t *res; @@ -365,6 +369,7 @@ void processSlotRX(void *arg) { delNotifiedFIFO_elt(res); } else { + rxtxD->ue_sched_mode = SCHED_ALL; processSlotTX(rxtxD); } diff --git a/openair1/PHY/defs_nr_UE.h b/openair1/PHY/defs_nr_UE.h index c9f29e2266..cc2f58805d 100644 --- a/openair1/PHY/defs_nr_UE.h +++ b/openair1/PHY/defs_nr_UE.h @@ -1084,6 +1084,7 @@ typedef struct { typedef struct nr_rxtx_thread_data_s { UE_nr_rxtx_proc_t proc; PHY_VARS_NR_UE *UE; + NR_UE_SCHED_MODE_t ue_sched_mode; notifiedFIFO_t txFifo; } nr_rxtx_thread_data_t; diff --git a/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c b/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c index 2b8678da0e..6842411440 100644 --- a/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c +++ b/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c @@ -1778,6 +1778,7 @@ int phy_procedures_nrUE_RX(PHY_VARS_NR_UE *ue, nr_rxtx_thread_data_t *curMsg=(nr_rxtx_thread_data_t *)NotifiedFifoData(newElt); curMsg->proc = *proc; curMsg->UE = ue; + curMsg->ue_sched_mode = ONLY_PUSCH; pushTpool(&(get_nrUE_params()->Tpool), newElt); #if UE_TIMING_TRACE diff --git a/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c b/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c index 5acc413f38..3421e72625 100644 --- a/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c +++ b/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c @@ -94,7 +94,12 @@ int nr_ue_ul_indication(nr_uplink_indication_t *ul_info){ module_id_t module_id = ul_info->module_id; NR_UE_MAC_INST_t *mac = get_mac_inst(module_id); - ret = nr_ue_scheduler(NULL, ul_info); + if (ul_info->ue_sched_mode == PUSCH) { + ret = nr_ue_scheduler(NULL, ul_info); + return 0; + } + else if (ul_info->ue_sched_mode == SCHED_ALL) + ret = nr_ue_scheduler(NULL, ul_info); NR_TDD_UL_DL_ConfigCommon_t *tdd_UL_DL_ConfigurationCommon = mac->scc != NULL ? mac->scc->tdd_UL_DL_ConfigurationCommon : mac->scc_SIB->tdd_UL_DL_ConfigurationCommon; diff --git a/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.h b/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.h index 449c7bf890..1ab9954344 100755 --- a/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.h +++ b/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.h @@ -39,6 +39,12 @@ typedef struct NR_UL_TIME_ALIGNMENT NR_UL_TIME_ALIGNMENT_t; +typedef enum { + ONLY_PUSCH, + NOT_PUSCH, + SCHED_ALL, +} NR_UE_SCHED_MODE_t; + typedef struct { /// module id module_id_t module_id; @@ -100,6 +106,9 @@ typedef struct { /// dci reception indication structure fapi_nr_dci_indication_t *dci_ind; + + NR_UE_SCHED_MODE_t ue_sched_mode; + } nr_uplink_indication_t; // Downlink subframe P7 From 99f69b87a129bf07e6b9996415133587fa197349 Mon Sep 17 00:00:00 2001 From: Sakthivel Velumani Date: Tue, 25 May 2021 17:59:17 +0200 Subject: [PATCH 19/91] fix bug --- 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 3421e72625..0e8d6532d4 100644 --- a/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c +++ b/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c @@ -94,7 +94,7 @@ int nr_ue_ul_indication(nr_uplink_indication_t *ul_info){ module_id_t module_id = ul_info->module_id; NR_UE_MAC_INST_t *mac = get_mac_inst(module_id); - if (ul_info->ue_sched_mode == PUSCH) { + if (ul_info->ue_sched_mode == ONLY_PUSCH) { ret = nr_ue_scheduler(NULL, ul_info); return 0; } From 5ec7f39adf3817fe5285ae361dee7bb4bb8d73b7 Mon Sep 17 00:00:00 2001 From: Sakthivel Velumani Date: Wed, 26 May 2021 10:12:58 +0200 Subject: [PATCH 20/91] fixed PUSCH tx issue --- executables/nr-ue.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/executables/nr-ue.c b/executables/nr-ue.c index 78019f9d97..3215bd91d1 100644 --- a/executables/nr-ue.c +++ b/executables/nr-ue.c @@ -312,7 +312,7 @@ void processSlotTX(void *arg) { UE->if_inst->ul_indication(&ul_indication); } - if (UE->mode != loop_through_memory) { + if ((UE->mode != loop_through_memory) && (rxtxD->ue_sched_mode != NOT_PUSCH)) { phy_procedures_nrUE_TX(UE,proc,0); } } From cf0659abe9c384158c4bb046795c1bc7fa1922a7 Mon Sep 17 00:00:00 2001 From: Mahesh Date: Mon, 31 May 2021 02:13:19 +0530 Subject: [PATCH 21/91] Cleanup --- ci-scripts/ran.py | 1 - ci-scripts/runTestOnVM.sh | 27 +- ci-scripts/xml_files/benetel_nsa_base.xml | 162 - ci-scripts/xml_files/fr1_nsa_base_ref.xml | 161 - executables/nr-gnb.c | 33 +- executables/nr-ru.c | 38 +- executables/nr-ru_Original.c | 2514 --- nfapi/oai_integration/nfapi_pnf.c | 40 +- nfapi/oai_integration/nfapi_pnf.h | 1 - nfapi/oai_integration/nfapi_vnf.c | 2 +- nfapi/open-nFAPI/common/src/debug.c | 152 +- .../nfapi/public_inc/fapi_nr_ue_interface.h | 8 +- .../nfapi/public_inc/nfapi_nr_interface_scf.h | 9 +- nfapi/open-nFAPI/nfapi/src/nfapi_p7.c | 17074 ++++++++-------- .../pnf/public_inc/nfapi_pnf_interface.h | 1 + nfapi/open-nFAPI/pnf/src/pnf_p7.c | 27 +- nfapi/open-nFAPI/pnf/src/pnf_p7_interface.c | 72 +- nfapi/open-nFAPI/pnf_sim/src/fapi_stub.cpp | 4 +- nfapi/open-nFAPI/vnf/inc/vnf_p7.h | 2 + nfapi/open-nFAPI/vnf/src/vnf_p7.c | 764 +- nfapi/open-nFAPI/vnf/src/vnf_p7_interface.c | 12 - .../NR_ESTIMATION/nr_ul_channel_estimation.c | 2 + openair1/PHY/NR_TRANSPORT/nr_dlsch_tools.c | 22 +- openair1/PHY/NR_TRANSPORT/nr_ulsch_decoding.c | 13 +- openair1/PHY/NR_TRANSPORT/pucch_rx.c | 11 +- .../PHY/NR_UE_TRANSPORT/nr_dlsch_decoding.c | 4 +- .../nr_dlsch_llr_computation.c | 52 +- .../PHY/NR_UE_TRANSPORT/nr_ulsch_coding.c | 14 +- openair1/SCHED_NR/fapi_nr_l1.c | 16 +- openair1/SCHED_NR/phy_procedures_nr_gNB.c | 6 +- openair1/SCHED_NR_UE/fapi_nr_ue_l1.c | 2 +- openair1/SCHED_NR_UE/harq_nr.c | 2 +- openair1/SIMULATION/NR_PHY/dlsim.c | 15 - openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c | 5 +- .../LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c | 20 - .../NR_MAC_gNB/gNB_scheduler_primitives.c | 8 - .../LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c | 149 +- openair2/NR_PHY_INTERFACE/NR_IF_Module.c | 37 +- targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp | 4 +- 39 files changed, 9565 insertions(+), 11921 deletions(-) delete mode 100644 ci-scripts/xml_files/benetel_nsa_base.xml delete mode 100644 ci-scripts/xml_files/fr1_nsa_base_ref.xml delete mode 100644 executables/nr-ru_Original.c diff --git a/ci-scripts/ran.py b/ci-scripts/ran.py index 31027d7234..83945b3c17 100644 --- a/ci-scripts/ran.py +++ b/ci-scripts/ran.py @@ -246,7 +246,6 @@ class RANManagement(): while (count > 0) and buildOAIprocess: mySSH.command('ps aux | grep --color=never build_ | grep -v grep', '\$', 6) result = re.search('build_oai', mySSH.getBefore()) - print(result) if result is None: buildOAIprocess = False else: diff --git a/ci-scripts/runTestOnVM.sh b/ci-scripts/runTestOnVM.sh index 7bd261fa0a..fc35370e0a 100755 --- a/ci-scripts/runTestOnVM.sh +++ b/ci-scripts/runTestOnVM.sh @@ -2204,43 +2204,26 @@ function run_test_on_vm { mkdir --parents $ARCHIVES_LOC fi - CN_CONFIG="noS1" - S1_NOS1_CFG=0 + local try_cnt=0 + NR_STATUS=0 ######### start of RA TEST loop - # for the moment only TDD - TRANS_MODES=("tdd") - for TMODE in ${TRANS_MODES[@]} + while [ $try_cnt -lt 5 ] #5 because it hardly succeed within CI do - if [[ $TMODE =~ .*fdd.* ]] - then - CONF_FILE=gnb.band66.tm1.106PRB.usrpn300.conf - PRB=106 - FREQUENCY=37000 - else - CONF_FILE=gnb.band78.tm1.106PRB.usrpn300.conf - PRB=106 - FREQUENCY=3510 - fi - local try_cnt=0 - NR_STATUS=0 - while [ $try_cnt -lt 5 ] #5 because it hardly succeed within CI - - do SYNC_STATUS=0 RA_FR2_STATUS=0 rm -f $ARCHIVES_LOC/tdd_${PRB}prb_${CN_CONFIG}*ra_fr2_test.log echo "############################################################" - echo "${CN_CONFIG} : Starting the gNB in ${TMODE} mode (RA TEST)" + echo "${CN_CONFIG} : Starting the gNB" echo "############################################################" CURRENT_GNB_LOG_FILE=tdd_${PRB}prb_${CN_CONFIG}_gnb_ra_fr2_test.log #last argument = 1 is to enable --do-ra for RA test start_rf_sim_gnb $GNB_VM_CMDS "$GNB_VM_IP_ADDR" $CURRENT_GNB_LOG_FILE $PRB $CONF_FILE $S1_NOS1_CFG 1 echo "############################################################" - echo "${CN_CONFIG} : Starting the NR-UE in ${TMODE} mode (RA TEST)" + echo "${CN_CONFIG} : Starting the NR-UE" echo "############################################################" CURRENT_NR_UE_LOG_FILE=tdd_${PRB}prb_${CN_CONFIG}_ue_ra_fr2_test.log #last argument = 1 is to enable --do-ra for RA test diff --git a/ci-scripts/xml_files/benetel_nsa_base.xml b/ci-scripts/xml_files/benetel_nsa_base.xml deleted file mode 100644 index 0aed28dffa..0000000000 --- a/ci-scripts/xml_files/benetel_nsa_base.xml +++ /dev/null @@ -1,162 +0,0 @@ - - - TEST-FR1-TM1 - FR1 - tasks - - 010000 - 030000 - 040000 - 010001 - 000001 - 050000 - 050001 - 000001 - 060000 - 060001 - 000001 - 070000 - 070001 - 010002 - 000001 - 080001 - 080000 - 010003 - - - - - Initialize_UE - Initialize UE - - - - Terminate_UE - Terminate UE - - - - Attach_UE - Attach UE - - - - Detach_UE - Detach UE - - - - - Initialize_eNB - Initialize eNB - -O ci-scripts/conf_files/benetel-4g.conf - 0 - 0 - lte - - - - - Initialize_eNB - Initialize gNB - -O ci-scripts/conf_files/benetel-5g.conf - 1 - 1 - nr - - - - IdleSleep - Sleep - 20 - - - - Ping - Ping: 20pings in 20sec - -c 20 - 50 - - - - Ping - Ping: 100pings in 20sec - -c 100 -i 0.2 - 50 - - - - - Iperf - iperf (DL/2.5Mbps/UDP)(60 sec)(single-ue profile) - -u -b 2.5M -t 60 -i 1 - 50 - single-ue - - - - Iperf - iperf (UL/1.5Mbps/UDP)(60 sec)(single-ue profile) - -u -b 1.5M -t 60 -i 1 -R - 50 - single-ue - - - - - Iperf - iperf (DL/20Mbps/UDP)(20 sec)(single-ue profile) - -u -b 20M -t 20 -i 1 - 50 - single-ue - - - - Iperf - iperf (UL/3Mbps/UDP)(20 sec)(single-ue profile) - -u -b 3M -t 20 -i 1 -R - 50 - single-ue - - - - - - Terminate_eNB - Terminate eNB - 0 - 0 - lte - - - - Terminate_eNB - Terminate gNB - 1 - 1 - nr - - - - diff --git a/ci-scripts/xml_files/fr1_nsa_base_ref.xml b/ci-scripts/xml_files/fr1_nsa_base_ref.xml deleted file mode 100644 index fd47db10b2..0000000000 --- a/ci-scripts/xml_files/fr1_nsa_base_ref.xml +++ /dev/null @@ -1,161 +0,0 @@ - - - TEST-NSA-FR1-TM1 - NSA FULL - tasks - - 010000 - 030000 - 040000 - 010001 - 000001 - 050000 - 050001 - 000001 - 060000 - 060001 - 000001 - 070000 - 010002 - 000001 - 080001 - 080000 - 010003 - - - - - Initialize_UE - Initialize UE - - - - Terminate_UE - Terminate UE - - - - Attach_UE - Attach UE - - - - Detach_UE - Detach UE - - - - - Initialize_eNB - Initialize eNB - -O ci-scripts/conf_files/enb.band7.tm1.fr1.25PRB.usrpb210.conf - 0 - 0 - lte - - - - - Initialize_eNB - Initialize gNB - -O ci-scripts/conf_files/gnb.band78.tm1.fr1.106PRB.usrpb210.conf -E - 1 - 1 - nr - - - - IdleSleep - Sleep - 20 - - - - Ping - Ping: 20pings in 20sec - -c 20 - 50 - - - - Ping - Ping: 100pings in 20sec - -c 100 -i 0.2 - 50 - - - - - Iperf - iperf (DL/3Mbps/UDP)(20 sec)(single-ue profile) - -u -b 3M -t 20 -i 1 - 50 - single-ue - - - - Iperf - iperf (UL/1Mbps/UDP)(20 sec)(single-ue profile) - -u -b 1M -t 20 -i 1 -R - 50 - single-ue - - - - - Iperf - iperf (DL/20Mbps/UDP)(20 sec)(single-ue profile) - -u -b 20M -t 20 -i 1 - 50 - single-ue - - - - Iperf - iperf (UL/3Mbps/UDP)(20 sec)(single-ue profile) - -u -b 3M -t 20 -i 1 -R - 50 - single-ue - - - - - - Terminate_eNB - Terminate eNB - 0 - 0 - lte - - - - Terminate_eNB - Terminate gNB - 1 - 1 - nr - - - - diff --git a/executables/nr-gnb.c b/executables/nr-gnb.c index 5e46f0b6f8..576c10229c 100644 --- a/executables/nr-gnb.c +++ b/executables/nr-gnb.c @@ -229,34 +229,9 @@ void rx_func(void *param) { if (pthread_mutex_unlock(&rnti_to_remove_mutex)) exit(1); // RX processing - int tx_slot_type; int rx_slot_type; - if(NFAPI_MODE != NFAPI_MONOLITHIC) { //slot selection routines not working properly in nfapi, so temporarily hardcoding - if ((slot_tx==8) || (slot_tx==9) || (slot_tx==18) || (slot_tx==19)) { //tx slot config - tx_slot_type = NR_UPLINK_SLOT; - } - else if ((slot_tx==7) || (slot_tx==17)) { - tx_slot_type = NR_MIXED_SLOT; - } - else { - tx_slot_type = NR_DOWNLINK_SLOT;; - } + int tx_slot_type = nr_slot_select(cfg,frame_tx,slot_tx); + int rx_slot_type = nr_slot_select(cfg,frame_rx,slot_rx); - if ((slot_rx==8) || (slot_rx==9) || (slot_rx==18) || (slot_rx==19)) { // rx slot config - rx_slot_type = NR_UPLINK_SLOT; - } - else if ((slot_rx==7) || (slot_rx==17)) { - rx_slot_type = NR_MIXED_SLOT; - } - else { - rx_slot_type = NR_DOWNLINK_SLOT;; - } - - - } - else { - tx_slot_type = nr_slot_select(cfg,frame_tx,slot_tx); - rx_slot_type = nr_slot_select(cfg,frame_rx,slot_rx); - } if (rx_slot_type == NR_UPLINK_SLOT || rx_slot_type == NR_MIXED_SLOT) { // UE-specific RX processing for subframe n // TODO: check if this is correct for PARALLEL_RU_L1_TRX_SPLIT @@ -281,7 +256,8 @@ void rx_func(void *param) { // Call the scheduler - start_meas(&gNB->ul_indication_stats); + if (NFAPI_MODE == NFAPI_MONOLITHIC){ + start_meas(&gNB->ul_indication_stats); pthread_mutex_lock(&gNB->UL_INFO_mutex); gNB->UL_INFO.frame = frame_rx; gNB->UL_INFO.slot = slot_rx; @@ -290,6 +266,7 @@ void rx_func(void *param) { gNB->if_inst->NR_UL_indication(&gNB->UL_INFO); pthread_mutex_unlock(&gNB->UL_INFO_mutex); stop_meas(&gNB->ul_indication_stats); + } notifiedFIFO_elt_t *res; diff --git a/executables/nr-ru.c b/executables/nr-ru.c index 5eff0f35b8..360bd97287 100644 --- a/executables/nr-ru.c +++ b/executables/nr-ru.c @@ -97,8 +97,6 @@ static int DEFBFW[] = {0x00007fff}; extern volatile int oai_exit; -extern struct timespec timespec_sub(struct timespec lhs, struct timespec rhs); -extern struct timespec timespec_add(struct timespec lhs, struct timespec rhs); extern void nr_phy_free_RU(RU_t *); extern void nr_phy_config_request(NR_PHY_Config_t *gNB); #include "executables/thread-common.h" @@ -710,8 +708,7 @@ void rx_rf(RU_t *ru,int *frame,int *slot) { } -void tx_rf(RU_t *ru,int frame,int slot, uint64_t timestamp) { - +void tx_rf(RU_t *ru,int frame,int slot, uint64_t timestamp) { RU_proc_t *proc = &ru->proc; NR_DL_FRAME_PARMS *fp = ru->nr_frame_parms; nfapi_nr_config_request_scf_t *cfg = &ru->config; @@ -1302,35 +1299,10 @@ 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); - struct timespec slot_duration; - slot_duration.tv_sec = 0; - //slot_duration.tv_nsec = 0.5e6; - slot_duration.tv_nsec = 0.5e6; - - - while (!oai_exit) { // these are local subframe/frame counters to check that we are in synch with the fronthaul timing. // They are set on the first rx/tx in the underly FH routines. - slot_start = timespec_add(slot_start,slot_duration); - struct timespec curr_time; - clock_gettime(CLOCK_MONOTONIC, &curr_time); - - struct timespec sleep_time; - - if((slot_start.tv_sec > curr_time.tv_sec) || (slot_start.tv_sec == curr_time.tv_sec && slot_start.tv_nsec > curr_time.tv_nsec)){ - sleep_time = timespec_sub(slot_start,curr_time); - - usleep(sleep_time.tv_nsec * 1e-3); - } - else{//continue - } - - // clock_gettime(CLOCK_MONOTONIC, &curr_time); - //printf("sfn:%d, slot:%d, start time %d.%d slot start %d.%d \n",frame,slot,curr_time.tv_sec,curr_time.tv_nsec,slot_start.tv_sec,slot_start.tv_nsec); if (slot==(fp->slots_per_frame-1)) { slot=0; frame++; @@ -1359,13 +1331,7 @@ void *ru_thread( void *param ) { // do RX front-end processing (frequency-shift, dft) if needed - //int slot_type = nr_slot_select(cfg,proc->frame_rx,proc->tti_rx); - //if (NFAPI_MODE == NFAPI_MODE_PNF) - int slot_type; - if (slot ==7) - slot_type = NR_MIXED_SLOT; - if (slot == 8) - slot_type = NR_UPLINK_SLOT; + int slot_type = nr_slot_select(cfg,proc->frame_rx,proc->tti_rx); if (slot_type == NR_UPLINK_SLOT || slot_type == NR_MIXED_SLOT) { if (ru->feprx) { diff --git a/executables/nr-ru_Original.c b/executables/nr-ru_Original.c deleted file mode 100644 index 73421d8ed7..0000000000 --- a/executables/nr-ru_Original.c +++ /dev/null @@ -1,2514 +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 - */ - -#define _GNU_SOURCE -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#undef MALLOC //there are two conflicting definitions, so we better make sure we don't use it at all - -#include "common/utils/assertions.h" -#include "common/utils/system.h" -#include "msc.h" - -#include "../../ARCH/COMMON/common_lib.h" -#include "../../ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.h" - -#include "PHY/LTE_TRANSPORT/if4_tools.h" -#include "PHY/LTE_TRANSPORT/if5_tools.h" - -#include "PHY/types.h" -#include "PHY/defs_nr_common.h" -#include "PHY/phy_extern.h" -#include "PHY/LTE_TRANSPORT/transport_proto.h" -#include "PHY/NR_TRANSPORT/nr_transport_proto.h" -#include "PHY/INIT/phy_init.h" -#include "SCHED/sched_eNB.h" -#include "SCHED_NR/sched_nr.h" - -#include "LAYER2/NR_MAC_COMMON/nr_mac_extern.h" -#include "RRC/LTE/rrc_extern.h" -#include "PHY_INTERFACE/phy_interface.h" - -#include "common/utils/LOG/log.h" -#include "common/utils/LOG/vcd_signal_dumper.h" - -#include "enb_config.h" -#include - -#ifdef SMBV -#include "PHY/TOOLS/smbv.h" -unsigned short config_frames[4] = {2,9,11,13}; -#endif - -/* these variables have to be defined before including ENB_APP/enb_paramdef.h and GNB_APP/gnb_paramdef.h */ -static int DEFBANDS[] = {7}; -static int DEFENBS[] = {0}; -static int DEFBFW[] = {0x00007fff}; - -//static int DEFNRBANDS[] = {7}; -//static int DEFGNBS[] = {0}; - -#include "ENB_APP/enb_paramdef.h" -#include "GNB_APP/gnb_paramdef.h" -#include "common/config/config_userapi.h" - -#ifndef OPENAIR2 - #include "UTIL/OTG/otg_extern.h" -#endif - -#include "s1ap_eNB.h" -#include "SIMULATION/ETH_TRANSPORT/proto.h" - - - -#include "T.h" -#include "nfapi_interface.h" - -extern volatile int oai_exit; - - -extern void nr_phy_free_RU(RU_t *); -extern void nr_phy_config_request(NR_PHY_Config_t *gNB); -#include "executables/thread-common.h" -//extern PARALLEL_CONF_t get_thread_parallel_conf(void); -//extern WORKER_CONF_t get_thread_worker_conf(void); - -void init_NR_RU(char *); -void stop_RU(int nb_ru); -void do_ru_sync(RU_t *ru); - -void configure_ru(int idx, void *arg); -void configure_rru(int idx, void *arg); -int attach_rru(RU_t *ru); -int connect_rau(RU_t *ru); - -uint16_t sf_ahead; -uint16_t slot_ahead; -uint16_t sl_ahead; - -extern int emulate_rf; -extern int numerology; -extern int usrp_tx_thread; - -/*************************************************************/ -/* Functions to attach and configure RRU */ - -extern void wait_gNBs(void); - -int attach_rru(RU_t *ru) -{ - ssize_t msg_len,len; - 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; - LOG_I(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); - - // wait for answer with timeout - if ((len = ru->ifdevice.trx_ctlrecv_func(&ru->ifdevice, - &rru_config_msg, - msg_len))<0) { - LOG_I(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]); - received_capabilities=1; - } else { - LOG_E(PHY,"Received incorrect message %d from RRU %d\n",rru_config_msg.type,ru->idx); - } - } - - configure_ru(ru->idx, - (RRU_capabilities_t *)&rru_config_msg.msg[0]); - 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]); - 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) { - 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"); - } else { - LOG_E(PHY,"Received incorrect message %d from RRU %d\n",rru_config_msg.type,ru->idx); - } - - return 0; -} - -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; - - // wait for RAU_tick - 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) { - 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); - } - } - - // 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); - - switch (ru->function) { - case NGFI_RRU_IF4p5: - cap->FH_fmt = OAI_IF4p5_only; - break; - - case NGFI_RRU_IF5: - cap->FH_fmt = OAI_IF5_only; - break; - - case MBP_RRU_IF5: - cap->FH_fmt = MBP_IF5; - break; - - default: - AssertFatal(1==0,"RU_function is unknown %d\n",RC.ru[0]->function); - break; - } - - cap->num_bands = ru->num_bands; - - for (i=0; inum_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]; - cap->nb_rx[i] = ru->nb_rx; - cap->nb_tx[i] = ru->nb_tx; - cap->max_pdschReferenceSignalPower[i] = ru->max_pdschReferenceSignalPower; - cap->max_rxgain[i] = ru->max_rxgain; - } - - AssertFatal((ru->ifdevice.trx_ctlsend_func(&ru->ifdevice,&rru_config_msg,rru_config_msg.len)!=-1), - "RU %d failed send capabilities to RAU\n",ru->idx); - // wait for configuration - rru_config_msg.len = sizeof(RRU_CONFIG_msg_t)-MAX_RRU_CONFIG_SIZE+sizeof(RRU_config_t); - - while (configuration_received == 0) { - if ((len = ru->ifdevice.trx_ctlrecv_func(&ru->ifdevice, - &rru_config_msg, - rru_config_msg.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->idx, - (void *)&rru_config_msg.msg[0]); - configuration_received = 1; - } - } - - return 0; -} -/*************************************************************/ -/* Southbound Fronthaul functions, RCC/RAU */ - -// 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 ); - - send_IF5(ru, timestamp, slot, &ru->seqno, IF5_RRH_GW_DL); -} - -// 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 ); - - 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) - send_IF4p5(ru,frame, slot, IF4p5_PDLFFT); -} - -/*************************************************************/ -/* Input Fronthaul from south RCC/RAU */ - -// Synchronous if5 from south -void fh_if5_south_in(RU_t *ru, - int *frame, - int *tti) -{ - NR_DL_FRAME_PARMS *fp = ru->nr_frame_parms; - RU_proc_t *proc = &ru->proc; - recv_IF5(ru, &proc->timestamp_rx, *tti, IF5_RRH_GW_UL); - proc->frame_rx = (proc->timestamp_rx / (fp->samples_per_subframe*10))&1023; - uint32_t idx_sf = proc->timestamp_rx / fp->samples_per_subframe; - proc->tti_rx = (idx_sf * fp->slots_per_subframe + (int)round((float)(proc->timestamp_rx % fp->samples_per_subframe) / fp->samples_per_slot0))%(fp->slots_per_frame); - - if (proc->first_rx == 0) { - if (proc->tti_rx != *tti) { - LOG_E(PHY,"Received Timestamp doesn't correspond to the time we think it is (proc->tti_rx %d, subframe %d)\n",proc->tti_rx,*tti); - exit_fun("Exiting"); - } - - if (proc->frame_rx != *frame) { - LOG_E(PHY,"Received Timestamp doesn't correspond to the time we think it is (proc->frame_rx %d frame %d)\n",proc->frame_rx,*frame); - exit_fun("Exiting"); - } - } else { - proc->first_rx = 0; - *frame = proc->frame_rx; - *tti = proc->tti_rx; - } - - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TS, proc->timestamp_rx&0xffffffff ); -} - -// Synchronous if4p5 from south -void fh_if4p5_south_in(RU_t *ru, - int *frame, - int *slot) -{ - NR_DL_FRAME_PARMS *fp = ru->nr_frame_parms; - RU_proc_t *proc = &ru->proc; - int f,sl; - uint16_t packet_type; - 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) && (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) { - // nothing in RU for RAU - } - - LOG_D(PHY,"rx_fh_if4p5: subframe %d symbol mask %x\n",*slot,proc->symbol_mask[sl]); - } while(proc->symbol_mask[sl] != symbol_mask_full); - - //caculate timestamp_rx, timestamp_tx based on frame and subframe - proc->tti_rx = sl; - proc->frame_rx = f; - 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+(fp->slots_per_subframe*sf_ahead))%fp->slots_per_frame; - proc->frame_tx = (sl>(fp->slots_per_frame-1-(fp->slots_per_subframe*sf_ahead))) ? (f+1)&1023 : f; - - if (proc->first_rx == 0) { - if (proc->tti_rx != *slot) { - LOG_E(PHY,"Received Timestamp (IF4p5) doesn't correspond to the time we think it is (proc->tti_rx %d, subframe %d)\n",proc->tti_rx,*slot); - exit_fun("Exiting"); - } - - if (proc->frame_rx != *frame) { - LOG_E(PHY,"Received Timestamp (IF4p5) doesn't correspond to the time we think it is (proc->frame_rx %d frame %d)\n",proc->frame_rx,*frame); - exit_fun("Exiting"); - } - } else { - proc->first_rx = 0; - *frame = proc->frame_rx; - *slot = proc->tti_rx; - } - - if (ru == RC.ru[0]) { - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_RX0_RU, f ); - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TTI_NUMBER_RX0_RU, sl); - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_TX0_RU, proc->frame_tx ); - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TTI_NUMBER_TX0_RU, proc->tti_tx ); - } - - proc->symbol_mask[proc->tti_rx] = 0; - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TS, proc->timestamp_rx&0xffffffff ); - LOG_D(PHY,"RU %d: fh_if4p5_south_in sleeping ...\n",ru->idx); -} - -// asynchronous inbound if4p5 fronthaul from south -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; - - 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; - proc->first_rx = 0; - } else { - if (proc->frame_rx != *frame) { - 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 -} - - - - - -/*************************************************************/ -/* Input Fronthaul from North RRU */ - -// RRU IF4p5 TX fronthaul receiver. Assumes an if_device on input and if or rf device on output -// receives one subframe's worth of IF4p5 OFDM symbols and OFDM modulates -void fh_if4p5_north_in(RU_t *ru,int *frame,int *slot) { - uint32_t symbol_number=0; - uint32_t symbol_mask, symbol_mask_full; - uint16_t packet_type; - /// **** incoming IF4p5 from remote RCC/RAU **** /// - symbol_number = 0; - symbol_mask = 0; - symbol_mask_full = (1<<(ru->nr_frame_parms->symbols_per_slot))-1; - - do { - recv_IF4p5(ru, frame, slot, &packet_type, &symbol_number); - symbol_mask = symbol_mask | (1<nr_frame_parms; - RU_proc_t *proc = &ru->proc; - int tti_tx,frame_tx; - openair0_timestamp timestamp_tx; - recv_IF5(ru, ×tamp_tx, *slot, IF5_RRH_GW_DL); - // printf("Received subframe %d (TS %llu) from RCC\n",tti_tx,timestamp_tx); - 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) { - NR_DL_FRAME_PARMS *fp = ru->nr_frame_parms; - 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; - int slot_tx,frame_tx; - LOG_D(PHY, "%s(ru:%p frame, subframe)\n", __FUNCTION__, ru); - symbol_number = 0; - 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); - - 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); - - if (proc->first_tx != 0) { - *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); - AssertFatal(slot_tx == *slot, - "slot_tx %d is not what we expect %d\n",slot_tx,*slot); - } - - if (packet_type == IF4p5_PDLFFT) { - symbol_mask = symbol_mask | (1<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; - - 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); - - // dump VCD output for first RU in list - if (ru == RC.ru[0]) { - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_TX0_RU, frame_tx ); - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TTI_NUMBER_TX0_RU, slot_tx ); - } - - if (ru->feptx_ofdm) ru->feptx_ofdm(ru,frame_tx,slot_tx); - - if (ru->fh_south_out) ru->fh_south_out(ru,frame_tx,slot_tx,proc->timestamp_tx); -} - -void fh_if5_north_out(RU_t *ru) { - RU_proc_t *proc=&ru->proc; - uint8_t seqno=0; - /// **** send_IF5 of rxdata to BBU **** /// - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_SEND_IF5, 1 ); - send_IF5(ru, proc->timestamp_rx, proc->tti_rx, &seqno, IF5_RRH_GW_UL); - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_SEND_IF5, 0 ); -} - -// RRU IF4p5 northbound interface (RX) -void fh_if4p5_north_out(RU_t *ru) { - RU_proc_t *proc=&ru->proc; - - //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); -} - -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; -} - -void rx_rf(RU_t *ru,int *frame,int *slot) { - RU_proc_t *proc = &ru->proc; - NR_DL_FRAME_PARMS *fp = ru->nr_frame_parms; - void *rxp[ru->nb_rx]; - unsigned int rxs; - int i; - uint32_t samples_per_slot = fp->get_samples_per_slot(*slot,fp); - uint32_t samples_per_slot_prev ; - openair0_timestamp ts,old_ts; - AssertFatal(*slotslots_per_frame && *slot>=0, "slot %d is illegal (%d)\n",*slot,fp->slots_per_frame); - - for (i=0; inb_rx; i++) - rxp[i] = (void *)&ru->common.rxdata[i][fp->get_samples_slot_timestamp(*slot,fp,0)]; - - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ, 1 ); - old_ts = proc->timestamp_rx; - LOG_D(PHY,"Reading %d samples for slot %d (%p)\n",samples_per_slot,*slot,rxp[0]); - - 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, - ru->nb_rx); - } - - - 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); - - if (proc->first_rx == 1) { - ru->ts_offset = proc->timestamp_rx; - proc->timestamp_rx = 0; - } else { - samples_per_slot_prev = fp->get_samples_per_slot((*slot-1)%fp->slots_per_frame,fp); - if (proc->timestamp_rx - old_ts != samples_per_slot_prev) { - LOG_D(PHY,"rx_rf: rfdevice timing drift of %"PRId64" samples (ts_off %"PRId64")\n",proc->timestamp_rx - old_ts - samples_per_slot_prev,ru->ts_offset); - ru->ts_offset += (proc->timestamp_rx - old_ts - samples_per_slot_prev); - proc->timestamp_rx = ts-ru->ts_offset; - } - } - - 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 %llu (off %d), frame %d, slot %d.%d / %d\n", - ru->idx, - 0, - (unsigned long long int)proc->timestamp_rx, - (int)ru->ts_offset,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]) { - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_RX0_RU, proc->frame_rx ); - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TTI_NUMBER_RX0_RU, proc->tti_rx ); - } - - 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); - 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, slot %d)\n",(long long unsigned int)proc->timestamp_rx,proc->frame_rx,*frame,proc->tti_rx,*slot); - exit_fun("Exiting"); - } - } else { - proc->first_rx = 0; - *frame = proc->frame_rx; - *slot = proc->tti_rx; - } - - //printf("timestamp_rx %lu, frame %d(%d), subframe %d(%d)\n",ru->timestamp_rx,proc->frame_rx,frame,proc->tti_rx,subframe); - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TS, proc->timestamp_rx&0xffffffff ); - - if (rxs != samples_per_slot) { - //exit_fun( "problem receiving samples" ); - LOG_E(PHY, "problem receiving samples\n"); - } -} - - -void tx_rf(RU_t *ru,int frame,int slot, uint64_t timestamp) { - RU_proc_t *proc = &ru->proc; - NR_DL_FRAME_PARMS *fp = ru->nr_frame_parms; - nfapi_nr_config_request_scf_t *cfg = &ru->config; - void *txp[ru->nb_tx]; - unsigned int txs; - int i,txsymb; - T(T_ENB_PHY_OUTPUT_SIGNAL, T_INT(0), T_INT(0), T_INT(frame), T_INT(slot), - T_INT(0), T_BUFFER(&ru->common.txdata[0][fp->get_samples_slot_timestamp(slot,fp,0)], fp->samples_per_subframe * 4)); - - int slot_type = nr_slot_select(cfg,frame,slot%fp->slots_per_frame); - int prevslot_type = nr_slot_select(cfg,frame,(slot+(fp->slots_per_frame-1))%fp->slots_per_frame); - int nextslot_type = nr_slot_select(cfg,frame,(slot+1)%fp->slots_per_frame); - int sf_extension = 0; //sf_extension = ru->sf_extension; - int siglen=fp->get_samples_per_slot(slot,fp); - int flags=1; - - //nr_subframe_t SF_type = nr_slot_select(cfg,slot%fp->slots_per_frame); - if (slot_type == NR_DOWNLINK_SLOT || slot_type == NR_MIXED_SLOT || IS_SOFTMODEM_RFSIM) { - - if (cfg->cell_config.frame_duplex_type.value == TDD){ - if(slot_type == NR_MIXED_SLOT) { - txsymb = 0; - for(int symbol_count = 0; symbol_counttdd_table.max_tdd_periodicity_list[slot].max_num_of_symbol_per_slot_list[symbol_count].slot_config.value == 0) - txsymb++; - } - AssertFatal(txsymb>0,"illegal txsymb %d\n",txsymb); - if(slot%(fp->slots_per_subframe/2)) - siglen = txsymb * (fp->ofdm_symbol_size + fp->nb_prefix_samples); - else - siglen = (fp->ofdm_symbol_size + fp->nb_prefix_samples0) + (txsymb - 1) * (fp->ofdm_symbol_size + fp->nb_prefix_samples); - //+ ru->end_of_burst_delay; - flags = 3; // end of burst - } - - if (slot_type == NR_DOWNLINK_SLOT && prevslot_type == NR_UPLINK_SLOT) - flags = 2; // start of burst - - if (slot_type == NR_DOWNLINK_SLOT && nextslot_type == NR_UPLINK_SLOT) - flags = 3; // end of burst - } - - if (fp->freq_range==nr_FR2) { - // the beam index is written in bits 8-10 of the flags - // bit 11 enables the gpio programming - int beam=0; - //if (slot==0) beam = 11; //3 for boresight & 8 to enable - /* - if (slot==0 || slot==40) beam=0&8; - if (slot==10 || slot==50) beam=1&8; - if (slot==20 || slot==60) beam=2&8; - if (slot==30 || slot==70) beam=3&8; - */ - flags |= beam<<8; - } - - 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 ); - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TTI_NUMBER_TX0_RU, slot ); - for (i=0; inb_tx; i++) - txp[i] = (void *)&ru->common.txdata[i][fp->get_samples_slot_timestamp(slot,fp,0)-sf_extension]; - - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TST, (timestamp-ru->openair0_cfg.tx_sample_advance)&0xffffffff ); - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE, 1 ); - // prepare tx buffer pointers - txs = ru->rfdevice.trx_write_func(&ru->rfdevice, - timestamp+ru->ts_offset-ru->openair0_cfg.tx_sample_advance-sf_extension, - txp, - siglen+sf_extension, - ru->nb_tx, - flags); - LOG_D(PHY,"[TXPATH] RU %d tx_rf, writing to TS %llu, frame %d, unwrapped_frame %d, slot %di, returned %d\n",ru->idx, - (long long unsigned int)timestamp,frame,proc->frame_tx_unwrap,slot, txs); - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE, 0 ); - //AssertFatal(txs == 0,"trx write function error %d\n", txs); - } -} - - - -/*! - * \brief The Asynchronous RX/TX FH thread of RAU/RCC/gNB/RRU. - * This handles the RX FH for an asynchronous RRU/UE - * \param param is a \ref gNB_L1_proc_t structure which contains the info what to process. - * \returns a pointer to an int. The storage is not on the heap and must not be freed. - */ -void *ru_thread_asynch_rxtx( void *param ) { - static int ru_thread_asynch_rxtx_status; - RU_t *ru = (RU_t *)param; - RU_proc_t *proc = &ru->proc; - nfapi_nr_config_request_scf_t *cfg = &ru->config; - int slot=0, frame=0; - // wait for top-level synchronization and do one acquisition to get timestamp for setting frame/subframe - wait_sync("ru_thread_asynch_rxtx"); - // wait for top-level synchronization and do one acquisition to get timestamp for setting frame/subframe - printf( "waiting for devices (ru_thread_asynch_rx)\n"); - wait_on_condition(&proc->mutex_asynch_rxtx,&proc->cond_asynch_rxtx,&proc->instance_cnt_asynch_rxtx,"thread_asynch"); - printf( "devices ok (ru_thread_asynch_rx)\n"); - - while (!oai_exit) { - - if (slot==ru->nr_frame_parms->slots_per_frame) { - slot=0; - frame++; - frame&=1023; - } else { - slot++; - } - - LOG_D(PHY,"ru_thread_asynch_rxtx: Waiting on incoming fronthaul\n"); - - // asynchronous receive from north (RRU IF4/IF5) - if (ru->fh_north_asynch_in) { - if ((nr_slot_select(cfg,frame,slot) & NR_DOWNLINK_SLOT)>0) - ru->fh_north_asynch_in(ru,&frame,&slot); - } else AssertFatal(1==0,"Unknown function in ru_thread_asynch_rxtx\n"); - } - - ru_thread_asynch_rxtx_status=0; - return(&ru_thread_asynch_rxtx_status); -} - - - - -/*! - * \brief The prach receive thread of RU. - * \param param is a \ref RU_proc_t structure which contains the info what to process. - * \returns a pointer to an int. The storage is not on the heap and must not be freed. - */ -void *ru_thread_prach( void *param ) { - static int ru_thread_prach_status; - RU_t *ru = (RU_t *)param; - RU_proc_t *proc = (RU_proc_t *)&ru->proc; - // set default return value - ru_thread_prach_status = 0; - - while (RC.ru_mask>0) { - usleep(1e6); - LOG_I(PHY,"%s() RACH waiting for RU to be configured\n", __FUNCTION__); - } - - LOG_I(PHY,"%s() RU configured - RACH processing thread running\n", __FUNCTION__); - - while (!oai_exit) { - - - if (wait_on_condition(&proc->mutex_prach,&proc->cond_prach,&proc->instance_cnt_prach,"ru_prach_thread") < 0) break; - - /*VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_RU_PRACH_RX, 1 ); - - if (ru->gNB_list[0]){ - prach_procedures( - ru->gNB_list[0],0 - ); - } - else { - rx_prach(NULL, - ru, - NULL, - NULL, - NULL, - proc->frame_prach, - 0,0 - ); - } - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_RU_PRACH_RX, 0 );*/ - if (release_thread(&proc->mutex_prach,&proc->instance_cnt_prach,"ru_prach_thread") < 0) break; - } - - LOG_I(PHY, "Exiting RU thread PRACH\n"); - ru_thread_prach_status = 0; - return &ru_thread_prach_status; -} - - -int wakeup_synch(RU_t *ru) { - struct timespec wait; - wait.tv_sec=0; - wait.tv_nsec=5000000L; - - // wake up synch thread - // lock the synch mutex and make sure the thread is ready - if (pthread_mutex_timedlock(&ru->proc.mutex_synch,&wait) != 0) { - LOG_E( PHY, "[RU] ERROR pthread_mutex_lock for RU synch thread (IC %d)\n", ru->proc.instance_cnt_synch ); - exit_fun( "error locking mutex_synch" ); - return(-1); - } - - ++ru->proc.instance_cnt_synch; - - // the thread can now be woken up - if (pthread_cond_signal(&ru->proc.cond_synch) != 0) { - LOG_E( PHY, "[RU] ERROR pthread_cond_signal for RU synch thread\n"); - exit_fun( "ERROR pthread_cond_signal" ); - return(-1); - } - - pthread_mutex_unlock( &ru->proc.mutex_synch ); - return(0); -} - -void do_ru_synch(RU_t *ru) { - NR_DL_FRAME_PARMS *fp = ru->nr_frame_parms; - RU_proc_t *proc = &ru->proc; - int i; - void *rxp[2],*rxp2[2]; - int32_t dummy_rx[ru->nb_rx][fp->samples_per_subframe] __attribute__((aligned(32))); - int rxs; - int ic; - - // initialize the synchronization buffer to the common_vars.rxdata - for (int i=0; inb_rx; i++) - rxp[i] = &ru->common.rxdata[i][0]; - - double temp_freq1 = ru->rfdevice.openair0_cfg->rx_freq[0]; - double temp_freq2 = ru->rfdevice.openair0_cfg->tx_freq[0]; - - for (i=0; i<4; i++) { - ru->rfdevice.openair0_cfg->rx_freq[i] = ru->rfdevice.openair0_cfg->tx_freq[i]; - ru->rfdevice.openair0_cfg->tx_freq[i] = temp_freq1; - } - - ru->rfdevice.trx_set_freq_func(&ru->rfdevice,ru->rfdevice.openair0_cfg,0); - - while ((ru->in_synch ==0)&&(!oai_exit)) { - // read in frame - rxs = ru->rfdevice.trx_read_func(&ru->rfdevice, - &(proc->timestamp_rx), - rxp, - fp->samples_per_subframe*10, - ru->nb_rx); - - if (rxs != fp->samples_per_subframe*10) LOG_E(PHY,"requested %d samples, got %d\n",fp->samples_per_subframe*10,rxs); - - // wakeup synchronization processing thread - wakeup_synch(ru); - ic=0; - - while ((ic>=0)&&(!oai_exit)) { - // continuously read in frames, 1ms at a time, - // until we are done with the synchronization procedure - for (i=0; inb_rx; i++) - rxp2[i] = (void *)&dummy_rx[i][0]; - - for (i=0; i<10; i++) - rxs = ru->rfdevice.trx_read_func(&ru->rfdevice, - &(proc->timestamp_rx), - rxp2, - fp->samples_per_subframe, - ru->nb_rx); - - pthread_mutex_lock(&ru->proc.mutex_synch); - ic = ru->proc.instance_cnt_synch; - pthread_mutex_unlock(&ru->proc.mutex_synch); - } // ic>=0 - } // in_synch==0 - - // read in rx_offset samples - LOG_I(PHY,"Resynchronizing by %d samples\n",ru->rx_offset); - rxs = ru->rfdevice.trx_read_func(&ru->rfdevice, - &(proc->timestamp_rx), - rxp, - ru->rx_offset, - ru->nb_rx); - - for (i=0; i<4; i++) { - ru->rfdevice.openair0_cfg->rx_freq[i] = temp_freq1; - ru->rfdevice.openair0_cfg->tx_freq[i] = temp_freq2; - } - - ru->rfdevice.trx_set_freq_func(&ru->rfdevice,ru->rfdevice.openair0_cfg,0); -} - - - -void wakeup_gNB_L1s(RU_t *ru) { - int i; - PHY_VARS_gNB **gNB_list = ru->gNB_list; - LOG_D(PHY,"wakeup_gNB_L1s (num %d) for RU %d ru->gNB_top:%p\n",ru->num_gNB,ru->idx, ru->gNB_top); - - if (ru->num_gNB==1 && ru->gNB_top!=0 && get_thread_parallel_conf() == PARALLEL_SINGLE_THREAD) { - // call gNB function directly - char string[20]; - sprintf(string,"Incoming RU %u",ru->idx); - LOG_D(PHY,"RU %d Call gNB_top\n",ru->idx); - ru->gNB_top(gNB_list[0],ru->proc.frame_rx,ru->proc.tti_rx,string,ru); - } else { - LOG_D(PHY,"ru->num_gNB:%d\n", ru->num_gNB); - - for (i=0; inum_gNB; i++) { - LOG_D(PHY,"ru->wakeup_rxtx:%p\n", ru->nr_wakeup_rxtx); - - if (ru->nr_wakeup_rxtx!=0 && ru->nr_wakeup_rxtx(gNB_list[i],ru) < 0) { - LOG_E(PHY,"could not wakeup gNB rxtx process for subframe %d\n", ru->proc.tti_rx); - } - } - } -} - -int wakeup_prach_ru(RU_t *ru) { - struct timespec wait; - wait.tv_sec=0; - wait.tv_nsec=5000000L; - - if (pthread_mutex_timedlock(&ru->proc.mutex_prach,&wait) !=0) { - LOG_E( PHY, "[RU] ERROR pthread_mutex_lock for RU prach thread (IC %d)\n", ru->proc.instance_cnt_prach); - exit_fun( "error locking mutex_rxtx" ); - return(-1); - } - - if (ru->proc.instance_cnt_prach==-1) { - ++ru->proc.instance_cnt_prach; - ru->proc.frame_prach = ru->proc.frame_rx; - ru->proc.subframe_prach = ru->proc.tti_rx; - - // DJP - think prach_procedures() is looking at gNB frame_prach - if (ru->gNB_list[0]) { - ru->gNB_list[0]->proc.frame_prach = ru->proc.frame_rx; - ru->gNB_list[0]->proc.slot_prach = ru->proc.tti_rx; - } - - LOG_I(PHY,"RU %d: waking up PRACH thread\n",ru->idx); - // the thread can now be woken up - AssertFatal(pthread_cond_signal(&ru->proc.cond_prach) == 0, "ERROR pthread_cond_signal for RU prach thread\n"); - } else LOG_W(PHY,"RU prach thread busy, skipping\n"); - - pthread_mutex_unlock( &ru->proc.mutex_prach ); - return(0); -} - -// this is for RU with local RF unit -void fill_rf_config(RU_t *ru, char *rf_config_file) { - int i; - NR_DL_FRAME_PARMS *fp = ru->nr_frame_parms; - nfapi_nr_config_request_scf_t *config = &ru->config; //tmp index - openair0_config_t *cfg = &ru->openair0_cfg; - int mu = config->ssb_config.scs_common.value; - int N_RB = config->carrier_config.dl_grid_size[config->ssb_config.scs_common.value].value; - - if (mu == NR_MU_0) { //or if LTE - if(N_RB == 100) { - if (fp->threequarter_fs) { - cfg->sample_rate=23.04e6; - cfg->samples_per_frame = 230400; - cfg->tx_bw = 10e6; - cfg->rx_bw = 10e6; - } else { - cfg->sample_rate=30.72e6; - cfg->samples_per_frame = 307200; - cfg->tx_bw = 10e6; - cfg->rx_bw = 10e6; - } - } else if(N_RB == 50) { - cfg->sample_rate=15.36e6; - cfg->samples_per_frame = 153600; - cfg->tx_bw = 5e6; - cfg->rx_bw = 5e6; - } else if (N_RB == 25) { - cfg->sample_rate=7.68e6; - cfg->samples_per_frame = 76800; - cfg->tx_bw = 2.5e6; - cfg->rx_bw = 2.5e6; - } else if (N_RB == 6) { - cfg->sample_rate=1.92e6; - cfg->samples_per_frame = 19200; - cfg->tx_bw = 1.5e6; - cfg->rx_bw = 1.5e6; - } else AssertFatal(1==0,"Unknown N_RB %d\n",N_RB); - } else if (mu == NR_MU_1) { - if(N_RB == 273) { - if (fp->threequarter_fs) { - AssertFatal(0 == 1,"three quarter sampling not supported for N_RB 273\n"); - } else { - cfg->sample_rate=122.88e6; - cfg->samples_per_frame = 1228800; - cfg->tx_bw = 100e6; - cfg->rx_bw = 100e6; - } - } else if(N_RB == 217) { - if (fp->threequarter_fs) { - cfg->sample_rate=92.16e6; - cfg->samples_per_frame = 921600; - cfg->tx_bw = 80e6; - cfg->rx_bw = 80e6; - } else { - cfg->sample_rate=122.88e6; - cfg->samples_per_frame = 1228800; - cfg->tx_bw = 80e6; - cfg->rx_bw = 80e6; - } - } else if(N_RB == 106) { - if (fp->threequarter_fs) { - cfg->sample_rate=46.08e6; - cfg->samples_per_frame = 460800; - cfg->tx_bw = 40e6; - cfg->rx_bw = 40e6; - } - else { - cfg->sample_rate=61.44e6; - cfg->samples_per_frame = 614400; - cfg->tx_bw = 40e6; - cfg->rx_bw = 40e6; - } - } else { - AssertFatal(0==1,"N_RB %d not yet supported for numerology %d\n",N_RB,mu); - } - } else if (mu == NR_MU_3) { - if (N_RB == 66) { - cfg->sample_rate = 122.88e6; - cfg->samples_per_frame = 1228800; - cfg->tx_bw = 100e6; - cfg->rx_bw = 100e6; - } else if(N_RB == 32) { - cfg->sample_rate=61.44e6; - cfg->samples_per_frame = 614400; - cfg->tx_bw = 50e6; - cfg->rx_bw = 50e6; - } - } else { - AssertFatal(0 == 1,"Numerology %d not supported for the moment\n",mu); - } - - if (config->cell_config.frame_duplex_type.value==TDD) - cfg->duplex_mode = duplex_mode_TDD; - else //FDD - cfg->duplex_mode = duplex_mode_FDD; - - cfg->Mod_id = 0; - cfg->num_rb_dl=N_RB; - cfg->tx_num_channels=ru->nb_tx; - cfg->rx_num_channels=ru->nb_rx; - - for (i=0; inb_tx; i++) { - if (ru->if_frequency == 0) { - cfg->tx_freq[i] = (double)fp->dl_CarrierFreq; - cfg->rx_freq[i] = (double)fp->ul_CarrierFreq; - } else if (ru->if_freq_offset){ - cfg->tx_freq[i] = (double)(ru->if_frequency); - cfg->rx_freq[i] = (double)(ru->if_frequency + ru->if_freq_offset); - LOG_I(PHY, "Setting IF TX frequency to %lu Hz with IF RX frequency offset %d Hz\n", ru->if_frequency, ru->if_freq_offset); - } else { - cfg->tx_freq[i] = (double)ru->if_frequency; - cfg->rx_freq[i] = (double)(ru->if_frequency+fp->ul_CarrierFreq-fp->dl_CarrierFreq); - } - cfg->tx_gain[i] = ru->att_tx; - cfg->rx_gain[i] = ru->max_rxgain-ru->att_rx; - cfg->configFilename = rf_config_file; - LOG_I(PHY, "Channel %d: setting tx_gain offset %f, rx_gain offset %f, tx_freq %lu Hz, rx_freq %lu Hz\n", - i, cfg->tx_gain[i], - cfg->rx_gain[i], - (unsigned long)cfg->tx_freq[i], - (unsigned long)cfg->rx_freq[i]); - } -} - -/* this function maps the RU tx and rx buffers to the available rf chains. - Each rf chain is is addressed by the card number and the chain on the card. The - rf_map specifies for each antenna port, on which rf chain the mapping should start. Multiple - antennas are mapped to successive RF chains on the same card. */ -int setup_RU_buffers(RU_t *ru) { - int i,j; - int card,ant; - //uint16_t N_TA_offset = 0; - NR_DL_FRAME_PARMS *frame_parms; - nfapi_nr_config_request_scf_t *config = &ru->config; - - if (ru) { - frame_parms = ru->nr_frame_parms; - printf("setup_RU_buffers: frame_parms = %p\n",frame_parms); - } else { - printf("ru pointer is NULL\n"); - 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; - - - if (config->cell_config.frame_duplex_type.value == TDD) { - int N_TA_offset = config->carrier_config.uplink_frequency.value < 6000000 ? 400 : 431; // reference samples for 25600Tc @ 30.72 Ms/s for FR1, same @ 61.44 Ms/s for FR2 - - double factor=1; - - switch (mu) { - case 0: //15 kHz scs - AssertFatal(N_TA_offset == 400,"scs_common 15kHz only for FR1\n"); - if (N_RB <= 25) factor = .25; // 7.68 Ms/s - else if (N_RB <=50) factor = .5; // 15.36 Ms/s - else if (N_RB <=75) factor = 1.0; // 30.72 Ms/s - else if (N_RB <=100) factor = 1.0; // 30.72 Ms/s - else AssertFatal(1==0,"Too many PRBS for mu=0\n"); - break; - case 1: //30 kHz sc - AssertFatal(N_TA_offset == 400,"scs_common 30kHz only for FR1\n"); - if (N_RB <= 106) factor = 2.0; // 61.44 Ms/s - else if (N_RB <= 275) factor = 4.0; // 122.88 Ms/s - break; - case 2: //60 kHz scs - AssertFatal(1==0,"scs_common should not be 60 kHz\n"); - break; - case 3: //120 kHz scs - AssertFatal(N_TA_offset == 431,"scs_common 120kHz only for FR2\n"); - break; - case 4: //240 kHz scs - AssertFatal(1==0,"scs_common should not be 60 kHz\n"); - if (N_RB <= 32) factor = 1.0; // 61.44 Ms/s - else if (N_RB <= 66) factor = 2.0; // 122.88 Ms/s - else AssertFatal(1==0,"N_RB %d is too big for curretn FR2 implementation\n",N_RB); - break; - - if (N_RB == 100) ru->N_TA_offset = 624; - else if (N_RB == 50) ru->N_TA_offset = 624/2; - else if (N_RB == 25) ru->N_TA_offset = 624/4; - } - if (frame_parms->threequarter_fs == 1) factor = factor*.75; - ru->N_TA_offset = (int)(N_TA_offset * factor); - LOG_I(PHY,"RU %d Setting N_TA_offset to %d samples (factor %f, UL Freq %d, N_RB %d)\n",ru->idx,ru->N_TA_offset,factor, - config->carrier_config.uplink_frequency.value, N_RB); - } - else ru->N_TA_offset = 0; - - - if (ru->openair0_cfg.mmapped_dma == 1) { - // replace RX signal buffers with mmaped HW versions - for (i=0; inb_rx; i++) { - card = i/4; - ant = i%4; - printf("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]; - printf("rxdata[%d] @ %p\n",i,ru->common.rxdata[i]); - - for (j=0; j<16; j++) { - printf("rxbuffer %d: %x\n",j,ru->common.rxdata[i][j]); - ru->common.rxdata[i][j] = 16-j; - } - } - - for (i=0; inb_tx; i++) { - card = i/4; - ant = i%4; - printf("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]; - printf("txdata[%d] @ %p\n",i,ru->common.txdata[i]); - - for (j=0; j<16; j++) { - printf("txbuffer %d: %x\n",j,ru->common.txdata[i][j]); - ru->common.txdata[i][j] = 16-j; - } - } - } else { // not memory-mapped DMA - //nothing to do, everything already allocated in lte_init - } - - 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 (opp_enabled == 1) { - - if (ru->feprx) print_meas(&ru->ofdm_demod_stats,"feprx",NULL,NULL); - - if (ru->feptx_ofdm) { - print_meas(&ru->precoding_stats,"feptx_prec",NULL,NULL); - print_meas(&ru->txdataF_copy_stats,"txdataF_copy",NULL,NULL); - print_meas(&ru->ofdm_mod_stats,"feptx_ofdm",NULL,NULL); - print_meas(&ru->ofdm_total_stats,"feptx_total",NULL,NULL); - } - - if (ru->fh_north_asynch_in) print_meas(&ru->rx_fhaul,"rx_fhaul",NULL,NULL); - - 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_thread_tx( void *param ) { - RU_t *ru = (RU_t *)param; - RU_proc_t *proc = &ru->proc; - NR_DL_FRAME_PARMS *fp = ru->nr_frame_parms; - PHY_VARS_gNB *gNB; - gNB_L1_proc_t *gNB_proc; - gNB_L1_rxtx_proc_t *L1_proc; - char filename[40]; - int print_frame = 8; - int i = 0; - int ret; - - - wait_on_condition(&proc->mutex_FH1,&proc->cond_FH1,&proc->instance_cnt_FH1,"ru_thread_tx"); - printf( "ru_thread_tx ready\n"); - - while (!oai_exit) { - - LOG_D(PHY,"ru_thread_tx: Waiting for TX processing\n"); - // wait until eNBs are finished subframe RX n and TX n+4 - - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_RU_TX_WAIT, 1 ); - wait_on_condition(&proc->mutex_gNBs,&proc->cond_gNBs,&proc->instance_cnt_gNBs,"ru_thread_tx"); - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_RU_TX_WAIT, 0 ); - - ret = pthread_mutex_lock(&proc->mutex_gNBs); - AssertFatal(ret == 0,"mutex_lock return %d\n",ret); - int frame_tx=proc->frame_tx; - int tti_tx =proc->tti_tx; - uint64_t timestamp_tx = proc->timestamp_tx; - - ret = pthread_mutex_unlock(&proc->mutex_gNBs); - AssertFatal(ret == 0,"mutex_lock returns %d\n",ret); - - if (oai_exit) break; - - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_TX0_RU, frame_tx ); - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TTI_NUMBER_TX0_RU, tti_tx ); - - // do TX front-end processing if needed (precoding and/or IDFTs) - if (ru->feptx_prec) ru->feptx_prec(ru,frame_tx,tti_tx); - - // do OFDM with/without TX front-end processing if needed - if ((ru->fh_north_asynch_in == NULL) && (ru->feptx_ofdm)) ru->feptx_ofdm(ru,frame_tx,tti_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,tti_tx,timestamp_tx); - - if (ru->fh_north_out) ru->fh_north_out(ru); - } else { - if(proc->frame_tx == print_frame) { - for (i=0; inb_tx; i++) { - - if(proc->tti_tx == 0) { - sprintf(filename,"gNBdataF_frame%d_sl%d.m", print_frame, proc->tti_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, proc->tti_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, proc->tti_tx); - LOG_M(filename,"txdataF_BF_frame",&ru->common.txdataF_BF[i][0],fp->samples_per_subframe_wCP, 1, 1); - } - - if(proc->tti_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(proc->tti_tx == 9) - }//for (i=0; inb_tx; i++) - }//if(proc->frame_tx == print_frame) - }//else emulate_rf - - release_thread(&proc->mutex_gNBs,&proc->instance_cnt_gNBs,"ru_thread_tx"); - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_RX1_UE, proc->instance_cnt_gNBs); - - for(i = 0; inum_gNB; i++) { - gNB = ru->gNB_list[i]; - gNB_proc = &gNB->proc; - L1_proc = (get_thread_parallel_conf() == PARALLEL_RU_L1_TRX_SPLIT)? &gNB_proc->L1_proc_tx : &gNB_proc->L1_proc; - ret = pthread_mutex_lock(&gNB_proc->mutex_RU_tx); - AssertFatal(ret == 0,"mutex_lock returns %d\n",ret); - - for (int j=0; jnum_RU; j++) { - if (ru == gNB->RU_list[j]) { - if ((gNB_proc->RU_mask_tx&(1< 0) - LOG_E(PHY,"gNB %d frame %d, subframe %d : previous information from RU tx %d (num_RU %d,mask %x) has not been served yet!\n", - gNB->Mod_id,gNB_proc->frame_rx,gNB_proc->slot_rx,ru->idx,gNB->num_RU,gNB_proc->RU_mask_tx); - - gNB_proc->RU_mask_tx |= (1<RU_mask_tx != (1<num_RU)-1) { // not all RUs have provided their information so return - ret = pthread_mutex_unlock(&gNB_proc->mutex_RU_tx); - AssertFatal(ret == 0,"mutex_unlock returns %d\n",ret); - } else { // all RUs TX are finished so send the ready signal to gNB processing - gNB_proc->RU_mask_tx = 0; - ret = pthread_mutex_unlock(&gNB_proc->mutex_RU_tx); - AssertFatal(ret == 0,"mutex_unlock returns %d\n",ret); - - ret = pthread_mutex_lock(&L1_proc->mutex_RUs_tx); - AssertFatal(ret == 0,"mutex_lock returns %d\n",ret); - // the thread can now be woken up - if (L1_proc->instance_cnt_RUs == -1) { - L1_proc->instance_cnt_RUs = 0; - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_RX0_UE,L1_proc->instance_cnt_RUs); - AssertFatal(pthread_cond_signal(&L1_proc->cond_RUs) == 0, - "ERROR pthread_cond_signal for gNB_L1_thread\n"); - } //else AssertFatal(1==0,"gNB TX thread is not ready\n"); - ret = pthread_mutex_unlock(&L1_proc->mutex_RUs_tx); - AssertFatal(ret == 0,"mutex_unlock returns %d\n",ret); - } - } - } - - release_thread(&proc->mutex_FH1,&proc->instance_cnt_FH1,"ru_thread_tx"); - return 0; -} - -void *ru_thread( void *param ) { - static int ru_thread_status; - RU_t *ru = (RU_t *)param; - RU_proc_t *proc = &ru->proc; - NR_DL_FRAME_PARMS *fp = ru->nr_frame_parms; - int ret; - int slot = fp->slots_per_frame-1; - int frame = 1023; - char filename[40], threadname[40]; - int print_frame = 8; - int i = 0; - int aa; - - nfapi_nr_config_request_scf_t *cfg = &ru->config; - - // set default return value - ru_thread_status = 0; - // set default return value - sprintf(threadname,"ru_thread %u",ru->idx); - - - LOG_I(PHY,"Starting RU %d (%s,%s),\n",ru->idx,NB_functions[ru->function],NB_timing[ru->if_timing]); - - memcpy((void*)&ru->config,(void*)&RC.gNB[0]->gNB_config,sizeof(ru->config)); - - if(emulate_rf) { - fill_rf_config(ru,ru->rf_config_file); - nr_init_frame_parms(&ru->config, fp); - nr_dump_frame_parms(fp); - nr_phy_init_RU(ru); - - if (setup_RU_buffers(ru)!=0) { - printf("Exiting, cannot initialize RU Buffers\n"); - exit(-1); - } - } else { - // Start IF device if any - if (ru->nr_start_if) { - LOG_I(PHY,"Starting IF interface for RU %d\n",ru->idx); - AssertFatal(ru->nr_start_if(ru,NULL) == 0, "Could not start the IF device\n"); - - if (ru->if_south == LOCAL_RF) ret = connect_rau(ru); - else ret = attach_rru(ru); - - AssertFatal(ret==0,"Cannot connect to remote radio\n"); - } - - if (ru->if_south == LOCAL_RF) { // configure RF parameters only - nr_init_frame_parms(&ru->config, fp); - nr_dump_frame_parms(fp); - fill_rf_config(ru,ru->rf_config_file); - nr_phy_init_RU(ru); - ret = openair0_device_load(&ru->rfdevice,&ru->openair0_cfg); - AssertFatal(ret==0,"Cannot connect to local radio\n"); - } - - if (setup_RU_buffers(ru)!=0) { - printf("Exiting, cannot initialize RU Buffers\n"); - exit(-1); - } - } - - sf_ahead = (uint16_t) ceil((float)6/(0x01<numerology_index)); - LOG_I(PHY, "Signaling main thread that RU %d is ready\n",ru->idx); - pthread_mutex_lock(&RC.ru_mutex); - RC.ru_mask &= ~(1<idx); - pthread_cond_signal(&RC.ru_cond); - 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); - - // if an asnych_rxtx thread exists - // wakeup the thread because the devices are ready at this point - - if ((ru->fh_south_asynch_in)||(ru->fh_north_asynch_in)) { - pthread_mutex_lock(&proc->mutex_asynch_rxtx); - proc->instance_cnt_asynch_rxtx=0; - pthread_mutex_unlock(&proc->mutex_asynch_rxtx); - pthread_cond_signal(&proc->cond_asynch_rxtx); - } else LOG_I(PHY,"RU %d no asynch_south interface\n",ru->idx); - - // if this is a slave RRU, try to synchronize on the DL frequency - if ((ru->is_slave) && (ru->if_south == LOCAL_RF)) do_ru_synch(ru); - - // 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"); - } - } - } - } - - pthread_mutex_lock(&proc->mutex_FH1); - proc->instance_cnt_FH1 = 0; - pthread_mutex_unlock(&proc->mutex_FH1); - pthread_cond_signal(&proc->cond_FH1); - - // This is a forever while loop, it loops over subframes which are scheduled by incoming samples from HW devices - while (!oai_exit) { - // these are local subframe/frame counters to check that we are in synch with the fronthaul timing. - // They are set on the first rx/tx in the underly FH routines. - if (slot==(fp->slots_per_frame-1)) { - slot=0; - frame++; - frame&=1023; - } else { - slot++; - } - - // 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"); - - LOG_D(PHY,"AFTER fh_south_in - SFN/SL:%d%d RU->proc[RX:%d.%d TX:%d.%d] RC.gNB[0]:[RX:%d%d TX(SFN):%d]\n", - frame,slot, - proc->frame_rx,proc->tti_rx, - proc->frame_tx,proc->tti_tx, - RC.gNB[0]->proc.frame_rx,RC.gNB[0]->proc.slot_rx, - RC.gNB[0]->proc.frame_tx); - /* - LOG_D(PHY,"RU thread (do_prach %d, is_prach_subframe %d), received frame %d, subframe %d\n", - ru->do_prach, - is_prach_subframe(fp, proc->frame_rx, proc->tti_rx), - proc->frame_rx,proc->tti_rx); - - if ((ru->do_prach>0) && (is_prach_subframe(fp, proc->frame_rx, proc->tti_rx)==1)) { - wakeup_prach_ru(ru); - }*/ - - // adjust for timing offset between RU - //printf("~~~~~~~~~~~~~~~~~~~~~~~~~~%d.%d in ru_thread is in process\n", proc->frame_rx, proc->tti_rx); - if (ru->idx!=0) proc->frame_tx = (proc->frame_tx+proc->frame_offset)&1023; - - // do RX front-end processing (frequency-shift, dft) if needed - - int slot_type = nr_slot_select(cfg,proc->frame_rx,proc->tti_rx); - if (slot_type == NR_UPLINK_SLOT || slot_type == NR_MIXED_SLOT) { - //if (proc->tti_rx==8) { - - if (ru->feprx) { - ru->feprx(ru,proc->tti_rx); - //LOG_M("rxdata.m","rxs",ru->common.rxdata[0],1228800,1,1); - - LOG_D(PHY,"RU proc: frame_rx = %d, tti_rx = %d\n", proc->frame_rx, proc->tti_rx); - LOG_D(PHY,"Copying rxdataF from RU to gNB\n"); - - for (aa=0;aanb_rx;aa++) - memcpy((void*)RC.gNB[0]->common_vars.rxdataF[aa], - (void*)ru->common.rxdataF[aa], fp->symbols_per_slot*fp->ofdm_symbol_size*sizeof(int32_t)); - - // Do PRACH RU processing - - int prach_id=find_nr_prach_ru(ru,proc->frame_rx,proc->tti_rx,SEARCH_EXIST); - uint8_t prachStartSymbol,N_dur; - if (prach_id>=0) { - N_dur = get_nr_prach_duration(ru->prach_list[prach_id].fmt); - /* - get_nr_prach_info_from_index(ru->config.prach_config.prach_ConfigurationIndex.value, - proc->frame_rx,proc->tti_rx, - ru->config.carrier_config.dl_frequency.value, - fp->numerology_index, - fp->frame_type, - &format, - &start_symbol, - &N_t_slot, - &N_dur, - &RA_sfn_index, - &N_RA_slot, - &config_period); - */ - for (int prach_oc = 0; prach_ocprach_list[prach_id].num_prach_ocas; prach_oc++) { - prachStartSymbol = ru->prach_list[prach_id].prachStartSymbol+prach_oc*N_dur; - //comment FK: the standard 38.211 section 5.3.2 has one extra term +14*N_RA_slot. This is because there prachStartSymbol is given wrt to start of the 15kHz slot or 60kHz slot. Here we work slot based, so this function is anyway only called in slots where there is PRACH. Its up to the MAC to schedule another PRACH PDU in the case there are there N_RA_slot \in {0,1}. - - rx_nr_prach_ru(ru, - ru->prach_list[prach_id].fmt, //could also use format - ru->prach_list[prach_id].numRA, - prachStartSymbol, - prach_oc, - proc->frame_rx,proc->tti_rx); - } - free_nr_ru_prach_entry(ru,prach_id); - } - } - } - - // At this point, all information for subframe has been received on FH interface - - // wakeup all gNB processes waiting for this RU - if (ru->num_gNB>0) wakeup_gNB_L1s(ru); - - if(get_thread_parallel_conf() == PARALLEL_SINGLE_THREAD || ru->num_gNB==0) { - // do TX front-end processing if needed (precoding and/or IDFTs) - if (ru->feptx_prec) ru->feptx_prec(ru,proc->frame_tx,proc->tti_tx); - - // do OFDM with/without TX front-end processing if needed - if ((ru->fh_north_asynch_in == NULL) && (ru->feptx_ofdm)) ru->feptx_ofdm(ru,proc->frame_tx,proc->tti_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,proc->frame_tx,proc->tti_tx,proc->timestamp_tx); - - if (ru->fh_north_out) ru->fh_north_out(ru); - } else { - if(proc->frame_tx == print_frame) { - for (i=0; inb_tx; i++) { - sprintf(filename,"tx%ddataF_frame%d_sl%d.m", i, print_frame, proc->tti_tx); - LOG_M(filename,"txdataF_frame",&ru->common.txdataF_BF[i][0],fp->samples_per_slot_wCP, 1, 1); - - if(proc->tti_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(proc->tti_tx == 9) - }//for (i=0; inb_tx; i++) - }//if(proc->frame_tx == print_frame) - }//else emulate_rf - - proc->emulate_rf_busy = 0; - }//if(get_thread_parallel_conf() == PARALLEL_SINGLE_THREAD) - } - - printf( "Exiting ru_thread \n"); - - 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); - } - - ru_thread_status = 0; - return &ru_thread_status; -} -/* -// This thread run the initial synchronization like a UE -void *ru_thread_synch(void *arg) { - - RU_t *ru = (RU_t*)arg; - NR_DL_FRAME_PARMS *fp=ru->nr_frame_parms; - int32_t sync_pos,sync_pos2; - uint32_t peak_val; - uint32_t sync_corr[307200] __attribute__((aligned(32))); - static int ru_thread_synch_status; - - - - wait_sync("ru_thread_synch"); - - // initialize variables for PSS detection - lte_sync_time_init(ru->nr_frame_parms); - - while (!oai_exit) { - - // wait to be woken up - if (wait_on_condition(&ru->proc.mutex_synch,&ru->proc.cond_synch,&ru->proc.instance_cnt_synch,"ru_thread_synch")<0) break; - - // if we're not in synch, then run initial synch - if (ru->in_synch == 0) { - // run intial synch like UE - LOG_I(PHY,"Running initial synchronization\n"); - - sync_pos = lte_sync_time_gNB(ru->common.rxdata, - fp, - fp->samples_per_subframe*5, - &peak_val, - sync_corr); - LOG_I(PHY,"RU synch: %d, val %d\n",sync_pos,peak_val); - - if (sync_pos >= 0) { - if (sync_pos >= fp->nb_prefix_samples) - sync_pos2 = sync_pos - fp->nb_prefix_samples; - else - sync_pos2 = sync_pos + (fp->samples_per_subframe*10) - fp->nb_prefix_samples; - - if (fp->frame_type == FDD) { - - // PSS is hypothesized in last symbol of first slot in Frame - int sync_pos_slot = (fp->samples_per_subframe>>1) - fp->ofdm_symbol_size - fp->nb_prefix_samples; - - if (sync_pos2 >= sync_pos_slot) - ru->rx_offset = sync_pos2 - sync_pos_slot; - else - ru->rx_offset = (fp->samples_per_subframe*10) + sync_pos2 - sync_pos_slot; - } - else { - - } - - LOG_I(PHY,"Estimated sync_pos %d, peak_val %d => timing offset %d\n",sync_pos,peak_val,ru->rx_offset); - - if ((peak_val > 300000) && (sync_pos > 0)) { - // if (sync_pos++ > 3) { - write_output("ru_sync.m","sync",(void*)&sync_corr[0],fp->samples_per_subframe*5,1,2); - write_output("ru_rx.m","rxs",(void*)ru->ru_time.rxdata[0][0],fp->samples_per_subframe*10,1,1); - exit(-1); - } - - ru->in_synch=1; - } - } - - if (release_thread(&ru->proc.mutex_synch,&ru->proc.instance_cnt_synch,"ru_synch_thread") < 0) break; - } // oai_exit - - ru_thread_synch_status = 0; - return &ru_thread_synch_status; - -} -*/ - -int nr_start_if(struct RU_t_s *ru, struct PHY_VARS_gNB_s *gNB) { - return(ru->ifdevice.trx_start_func(&ru->ifdevice)); -} - -int start_rf(RU_t *ru) { - return(ru->rfdevice.trx_start_func(&ru->rfdevice)); -} - -int stop_rf(RU_t *ru) { - ru->rfdevice.trx_end_func(&ru->rfdevice); - return 0; -} - -int start_write_thread(RU_t *ru) { - return(ru->rfdevice.trx_write_init(&ru->rfdevice)); -} - -void init_RU_proc(RU_t *ru) { - int i=0; - RU_proc_t *proc; - char name[100]; - LOG_I(PHY,"Initializing RU proc %d (%s,%s),\n",ru->idx,NB_functions[ru->function],NB_timing[ru->if_timing]); - proc = &ru->proc; - memset((void *)proc,0,sizeof(RU_proc_t)); - proc->ru = ru; - proc->instance_cnt_prach = -1; - proc->instance_cnt_synch = -1; - proc->instance_cnt_FH = -1; - proc->instance_cnt_FH1 = -1; - proc->instance_cnt_gNBs = -1; - proc->instance_cnt_asynch_rxtx = -1; - 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; - proc->feptx_mask = 0; - - for (i=0; i<10; i++) proc->symbol_mask[i]=0; - - pthread_mutex_init( &proc->mutex_prach, NULL); - pthread_mutex_init( &proc->mutex_asynch_rxtx, NULL); - 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_gNBs, 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_gNBs, NULL); - threadCreate( &proc->pthread_FH, ru_thread, (void *)ru, "thread_FH", -1, OAI_PRIORITY_RT_MAX ); - - if (get_thread_parallel_conf() == PARALLEL_RU_L1_SPLIT || get_thread_parallel_conf() == PARALLEL_RU_L1_TRX_SPLIT) - threadCreate( &proc->pthread_FH1, ru_thread_tx, (void *)ru, "thread_FH1", -1, OAI_PRIORITY_RT ); - - if(emulate_rf) - threadCreate( &proc->pthread_emulateRF, emulatedRF_thread, (void *)proc, "emulateRF", -1, OAI_PRIORITY_RT ); - - if (ru->function == NGFI_RRU_IF4p5) { - threadCreate( &proc->pthread_prach, ru_thread_prach, (void *)ru, "RACH", -1, OAI_PRIORITY_RT ); - ///tmp deactivation of synch thread - // if (ru->is_slave == 1) pthread_create( &proc->pthread_synch, attr_synch, ru_thread_synch, (void*)ru); - - if ((ru->if_timing == synch_to_other) || - (ru->function == NGFI_RRU_IF5) || - (ru->function == NGFI_RRU_IF4p5)) threadCreate( &proc->pthread_asynch_rxtx, ru_thread_asynch_rxtx, (void *)ru, "asynch_rxtx", -1, OAI_PRIORITY_RT ); - - snprintf( name, sizeof(name), "ru_thread_FH %d", ru->idx ); - pthread_setname_np( proc->pthread_FH, name ); - } else if (ru->function == gNodeB_3GPP && ru->if_south == LOCAL_RF) { // DJP - need something else to distinguish between monolithic and PNF - LOG_I(PHY,"%s() DJP - added creation of pthread_prach\n", __FUNCTION__); - threadCreate( &proc->pthread_prach, ru_thread_prach, (void *)ru,"RACH", -1, OAI_PRIORITY_RT ); - } - - if (get_thread_worker_conf() == WORKER_ENABLE) { - if (ru->feprx) nr_init_feprx_thread(ru); - - if (ru->feptx_ofdm) nr_init_feptx_thread(ru); - } - - if (opp_enabled == 1) threadCreate(&ru->ru_stats_thread,ru_stats_thread,(void *)ru, "emulateRF", -1, OAI_PRIORITY_RT_LOW); -} - -void kill_NR_RU_proc(int inst) { - RU_t *ru = RC.ru[inst]; - RU_proc_t *proc = &ru->proc; - pthread_mutex_lock(&proc->mutex_FH); - proc->instance_cnt_FH = 0; - pthread_mutex_unlock(&proc->mutex_FH); - pthread_cond_signal(&proc->cond_FH); - pthread_mutex_lock(&proc->mutex_prach); - proc->instance_cnt_prach = 0; - pthread_mutex_unlock(&proc->mutex_prach); - pthread_cond_signal(&proc->cond_prach); - pthread_mutex_lock(&proc->mutex_synch); - proc->instance_cnt_synch = 0; - pthread_mutex_unlock(&proc->mutex_synch); - pthread_cond_signal(&proc->cond_synch); - pthread_mutex_lock(&proc->mutex_gNBs); - proc->instance_cnt_gNBs = 0; - pthread_mutex_unlock(&proc->mutex_gNBs); - pthread_cond_signal(&proc->cond_gNBs); - pthread_mutex_lock(&proc->mutex_asynch_rxtx); - proc->instance_cnt_asynch_rxtx = 0; - pthread_mutex_unlock(&proc->mutex_asynch_rxtx); - pthread_cond_signal(&proc->cond_asynch_rxtx); - LOG_D(PHY, "Joining pthread_FH\n"); - pthread_join(proc->pthread_FH, NULL); - - if (ru->function == NGFI_RRU_IF4p5) { - LOG_D(PHY, "Joining pthread_prach\n"); - pthread_join(proc->pthread_prach, NULL); - - if (ru->is_slave) { - LOG_D(PHY, "Joining pthread_\n"); - pthread_join(proc->pthread_synch, NULL); - } - - if ((ru->if_timing == synch_to_other) || - (ru->function == NGFI_RRU_IF5) || - (ru->function == NGFI_RRU_IF4p5)) { - LOG_D(PHY, "Joining pthread_asynch_rxtx\n"); - pthread_join(proc->pthread_asynch_rxtx, NULL); - } - } - - if (get_nprocs() >= 2) { - if (ru->feprx) { - pthread_mutex_lock(&proc->mutex_fep); - proc->instance_cnt_fep = 0; - pthread_mutex_unlock(&proc->mutex_fep); - pthread_cond_signal(&proc->cond_fep); - LOG_D(PHY, "Joining pthread_fep\n"); - pthread_join(proc->pthread_fep, NULL); - pthread_mutex_destroy(&proc->mutex_fep); - pthread_cond_destroy(&proc->cond_fep); - } - - if (ru->feptx_ofdm) { - pthread_mutex_lock(&proc->mutex_feptx); - proc->instance_cnt_feptx = 0; - pthread_mutex_unlock(&proc->mutex_feptx); - pthread_cond_signal(&proc->cond_feptx); - LOG_D(PHY, "Joining pthread_feptx\n"); - pthread_join(proc->pthread_feptx, NULL); - pthread_mutex_destroy(&proc->mutex_feptx); - pthread_cond_destroy(&proc->cond_feptx); - } - } - - if (opp_enabled) { - LOG_D(PHY, "Joining ru_stats_thread\n"); - pthread_join(ru->ru_stats_thread, NULL); - } - - pthread_mutex_destroy(&proc->mutex_prach); - pthread_mutex_destroy(&proc->mutex_asynch_rxtx); - pthread_mutex_destroy(&proc->mutex_synch); - pthread_mutex_destroy(&proc->mutex_FH); - pthread_mutex_destroy(&proc->mutex_gNBs); - pthread_cond_destroy(&proc->cond_prach); - pthread_cond_destroy(&proc->cond_FH); - pthread_cond_destroy(&proc->cond_asynch_rxtx); - pthread_cond_destroy(&proc->cond_synch); - pthread_cond_destroy(&proc->cond_gNBs); -} - -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; - break; - } - } - - if (found_band == 0) { - LOG_I(PHY,"Couldn't find target NR band %d on RRU %d\n",ru->nr_frame_parms->nr_band,ru->idx); - return(-1); - } - - switch (ru->if_south) { - case LOCAL_RF: - AssertFatal(1==0, "This RU should not have a local RF, exiting\n"); - return(0); - break; - - case REMOTE_IF5: - 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); - - break; - - case REMOTE_MBP_IF5: - if (fmt == MBP_IF5) return(0); - - break; - - default: - LOG_I(PHY,"No compatible Fronthaul interface found for RRU %d\n", ru->idx); - return(-1); - } - - return(-1); -} - - -char rru_format_options[4][20] = {"OAI_IF5_only","OAI_IF4p5_only","OAI_IF5_and_IF4p5","MBP_IF5"}; - -char rru_formats[3][20] = {"OAI_IF5","MBP_IF5","OAI_IF4p5"}; -char ru_if_formats[4][20] = {"LOCAL_RF","REMOTE_OAI_IF5","REMOTE_MBP_IF5","REMOTE_OAI_IF4p5"}; - -void configure_ru(int idx, - void *arg) -{ - RU_t *ru = RC.ru[idx]; - 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",idx); - - 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", idx, ret); - // take antenna capabilities of RRU - 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]);*/ - nr_init_frame_parms(&ru->config, ru->nr_frame_parms); - nr_phy_init_RU(ru); -} - -void configure_rru(int idx, - void *arg) { - RRU_config_t *config = (RRU_config_t *)arg; - RU_t *ru = RC.ru[idx]; - 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]; - - 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]; - } else - cfg->cell_config.frame_duplex_type.value = FDD; - - 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]; - - //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]; */ - } - - fill_rf_config(ru,ru->rf_config_file); - nr_init_frame_parms(&ru->config, ru->nr_frame_parms); - nr_phy_init_RU(ru); -} - -/* -void init_precoding_weights(PHY_VARS_gNB *gNB) { - - int layer,ru_id,aa,re,ue,tb; - LTE_DL_FRAME_PARMS *fp=&gNB->frame_parms; - RU_t *ru; - LTE_gNB_DLSCH_t *dlsch; - - // init precoding weigths - for (ue=0;uedlsch[ue][tb]; - for (layer=0; layer<4; layer++) { - int nb_tx=0; - for (ru_id=0;ru_idnb_tx; - } - dlsch->ue_spec_bf_weights[layer] = (int32_t**)malloc16(nb_tx*sizeof(int32_t*)); - - for (aa=0; aaue_spec_bf_weights[layer][aa] = (int32_t *)malloc16(fp->ofdm_symbol_size*sizeof(int32_t)); - for (re=0;reofdm_symbol_size; re++) { - dlsch->ue_spec_bf_weights[layer][aa][re] = 0x00007fff; - } - } - } - } - } -}*/ - -void set_function_spec_param(RU_t *ru) { - int ret; - - switch (ru->if_south) { - case LOCAL_RF: // this is an RU with integrated RF (RRU, gNB) - if (ru->function == NGFI_RRU_IF5) { // IF5 RRU - ru->do_prach = 0; // no prach processing in RU - ru->fh_north_in = NULL; // no shynchronous incoming fronthaul from north - ru->fh_north_out = fh_if5_north_out; // need only to do send_IF5 reception - ru->fh_south_out = tx_rf; // send output to RF - ru->fh_north_asynch_in = fh_if5_north_asynch_in; // TX packets come asynchronously - ru->feprx = NULL; // nothing (this is a time-domain signal) - ru->feptx_ofdm = NULL; // nothing (this is a time-domain signal) - ru->feptx_prec = NULL; // nothing (this is a time-domain signal) - ru->nr_start_if = nr_start_if; // need to start the if interface for if5 - ru->ifdevice.host_type = RRU_HOST; - ru->rfdevice.host_type = RRU_HOST; - ru->ifdevice.eth_params = &ru->eth_params; - reset_meas(&ru->rx_fhaul); - reset_meas(&ru->tx_fhaul); - reset_meas(&ru->compression); - reset_meas(&ru->transport); - ret = openair0_transport_load(&ru->ifdevice,&ru->openair0_cfg,&ru->eth_params); - printf("openair0_transport_init returns %d for ru_id %u\n", ret, ru->idx); - - if (ret<0) { - printf("Exiting, cannot initialize transport protocol\n"); - exit(-1); - } - } else if (ru->function == NGFI_RRU_IF4p5) { - ru->do_prach = 1; // do part of prach processing in RU - ru->fh_north_in = NULL; // no synchronous incoming fronthaul from north - ru->fh_north_out = fh_if4p5_north_out; // send_IF4p5 on reception - ru->fh_south_out = tx_rf; // send output to RF - ru->fh_north_asynch_in = fh_if4p5_north_asynch_in; // TX packets come asynchronously - ru->feprx = (get_thread_worker_conf() == WORKER_ENABLE) ? nr_fep_full_2thread : nr_fep_full; // RX DFTs - ru->feptx_ofdm = (get_thread_worker_conf() == WORKER_ENABLE) ? nr_feptx_ofdm_2thread : nr_feptx_ofdm; // this is fep with idft only (no precoding in RRU) - ru->feptx_prec = NULL; - ru->nr_start_if = nr_start_if; // need to start the if interface for if4p5 - ru->ifdevice.host_type = RRU_HOST; - ru->rfdevice.host_type = RRU_HOST; - ru->ifdevice.eth_params = &ru->eth_params; - reset_meas(&ru->rx_fhaul); - reset_meas(&ru->tx_fhaul); - reset_meas(&ru->compression); - reset_meas(&ru->transport); - ret = openair0_transport_load(&ru->ifdevice,&ru->openair0_cfg,&ru->eth_params); - printf("openair0_transport_init returns %d for ru_id %u\n", ret, ru->idx); - - if (ret<0) { - printf("Exiting, cannot initialize transport protocol\n"); - exit(-1); - } - - malloc_IF4p5_buffer(ru); - } else if (ru->function == gNodeB_3GPP) { - ru->do_prach = 0; // no prach processing in RU - ru->feprx = (get_thread_worker_conf() == WORKER_ENABLE) ? nr_fep_full_2thread : nr_fep_full; // RX DFTs - ru->feptx_ofdm = (get_thread_worker_conf() == WORKER_ENABLE) ? nr_feptx_ofdm_2thread : nr_feptx_ofdm; // this is fep with idft and precoding - ru->feptx_prec = (get_thread_worker_conf() == WORKER_ENABLE) ? NULL : nr_feptx_prec; // this is fep with idft and precoding - ru->fh_north_in = NULL; // no incoming fronthaul from north - ru->fh_north_out = NULL; // no outgoing fronthaul to north - ru->nr_start_if = NULL; // no if interface - ru->rfdevice.host_type = RAU_HOST; - - // FK this here looks messed up. The following lines should be part of the if (ru->function == gNodeB_3GPP), shouldn't they? - - ru->fh_south_in = rx_rf; // local synchronous RF RX - ru->fh_south_out = tx_rf; // local synchronous RF TX - ru->start_rf = start_rf; // need to start the local RF interface - ru->stop_rf = stop_rf; - ru->start_write_thread = start_write_thread; // starting RF TX in different thread - printf("configuring ru_id %u (start_rf %p)\n", ru->idx, start_rf); - } - - /* - printf("configuring ru_id %u (start_rf %p)\n", ru->idx, start_rf); - 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) { - printf("Exiting, cannot initialize RU Buffers\n"); - exit(-1); - } - */ - break; - - case REMOTE_IF5: // the remote unit is IF5 RRU - ru->do_prach = 0; - ru->feprx = (get_thread_worker_conf() == WORKER_ENABLE) ? nr_fep_full_2thread : nr_fep_full; // this is frequency-shift + DFTs - ru->feptx_prec = (get_thread_worker_conf() == WORKER_ENABLE) ? NULL : nr_feptx_prec; // need to do transmit Precoding + IDFTs - ru->feptx_ofdm = (get_thread_worker_conf() == WORKER_ENABLE) ? nr_feptx_ofdm_2thread : nr_feptx_ofdm; // need to do transmit Precoding + IDFTs - ru->fh_south_in = fh_if5_south_in; // synchronous IF5 reception - ru->fh_south_out = fh_if5_south_out; // synchronous IF5 transmission - ru->fh_south_asynch_in = NULL; // no asynchronous UL - ru->start_rf = NULL; // no local RF - ru->stop_rf = NULL; - ru->start_write_thread = NULL; - ru->nr_start_if = nr_start_if; // need to start if interface for IF5 - ru->ifdevice.host_type = RAU_HOST; - ru->ifdevice.eth_params = &ru->eth_params; - ru->ifdevice.configure_rru = configure_ru; - ret = openair0_transport_load(&ru->ifdevice,&ru->openair0_cfg,&ru->eth_params); - printf("openair0_transport_init returns %d for ru_id %u\n", ret, ru->idx); - - if (ret<0) { - printf("Exiting, cannot initialize transport protocol\n"); - exit(-1); - } - - break; - - case REMOTE_IF4p5: - ru->do_prach = 0; - ru->feprx = NULL; // DFTs - ru->feptx_prec = nr_feptx_prec; // Precoding operation - ru->feptx_ofdm = NULL; // no OFDM mod - ru->fh_south_in = fh_if4p5_south_in; // synchronous IF4p5 reception - ru->fh_south_out = fh_if4p5_south_out; // synchronous IF4p5 transmission - ru->fh_south_asynch_in = (ru->if_timing == synch_to_other) ? fh_if4p5_south_in : NULL; // asynchronous UL if synch_to_other - ru->fh_north_out = NULL; - ru->fh_north_asynch_in = NULL; - ru->start_rf = NULL; // no local RF - ru->stop_rf = NULL; - ru->start_write_thread = NULL; - ru->nr_start_if = nr_start_if; // need to start if interface for IF4p5 - ru->ifdevice.host_type = RAU_HOST; - ru->ifdevice.eth_params = &ru->eth_params; - ru->ifdevice.configure_rru = configure_ru; - ret = openair0_transport_load(&ru->ifdevice, &ru->openair0_cfg, &ru->eth_params); - printf("openair0_transport_init returns %d for ru_id %u\n", ret, ru->idx); - - if (ret<0) { - printf("Exiting, cannot initialize transport protocol\n"); - exit(-1); - } - - if (ru->ifdevice.get_internal_parameter != NULL) { - 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; - } - - malloc_IF4p5_buffer(ru); - break; - - default: - LOG_E(PHY,"RU with invalid or unknown southbound interface type %d\n",ru->if_south); - break; - } // switch on interface type -} - -void init_NR_RU(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); - pthread_cond_init(&RC.ru_cond,NULL); - // read in configuration file) - printf("configuring RU from file\n"); - RCconfig_RU(); - 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; - // use gNB_list[0] as a reference for RU frame parameters - // NOTE: multiple CC_id are not handled here yet! - - if (ru->num_gNB > 0) { - LOG_D(PHY, "%s() RC.ru[%d].num_gNB:%d ru->gNB_list[0]:%p RC.gNB[0]:%p rf_config_file:%s\n", __FUNCTION__, ru_id, ru->num_gNB, ru->gNB_list[0], RC.gNB[0], ru->rf_config_file); - - if (ru->gNB_list[0] == 0) { - LOG_E(PHY,"%s() DJP - ru->gNB_list ru->num_gNB are not initialized - so do it manually\n", __FUNCTION__); - ru->gNB_list[0] = RC.gNB[0]; - ru->num_gNB=1; - // - // DJP - feptx_prec() / feptx_ofdm() parses the gNB_list (based on num_gNB) and copies the txdata_F to txdata in RU - // - } else { - LOG_E(PHY,"DJP - delete code above this %s:%d\n", __FILE__, __LINE__); - } - } - - gNB_RC = RC.gNB[0]; - gNB0 = ru->gNB_list[0]; - fp = ru->nr_frame_parms; - 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!=NULL,"gNB0 is null!\n"); - - if (gNB0 && gNB_RC) { - LOG_I(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); - memset((void *)fp, 0, sizeof(NR_DL_FRAME_PARMS)); - 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)); - // 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++) { - gNB0 = ru->gNB_list[i]; - gNB0->RU_list[gNB0->num_RU++] = ru; - } - } - } - - //LOG_I(PHY,"Initializing RRU descriptor %d : (%s,%s,%d)\n",ru_id,ru_if_types[ru->if_south],NB_timing[ru->if_timing],ru->function); - set_function_spec_param(ru); - LOG_I(PHY,"Starting ru_thread %d\n",ru_id); - init_RU_proc(ru); - } // for ru_id - - // sleep(1); - LOG_D(HW,"[nr-softmodem.c] RU threads created\n"); -} - - -void stop_RU(int nb_ru) -{ - for (int inst = 0; inst < nb_ru; inst++) { - LOG_I(PHY, "Stopping RU %d processing threads\n", inst); - kill_NR_RU_proc(inst); - } -} - - -/* --------------------------------------------------------*/ -/* from here function to use configuration module */ -void RCconfig_RU(void) -{ - int i = 0, j = 0; - paramdef_t RUParams[] = RUPARAMS_DESC; - paramlist_def_t RUParamList = {CONFIG_STRING_RU_LIST,NULL,0}; - config_getlist( &RUParamList, RUParams, sizeof(RUParams)/sizeof(paramdef_t), NULL); - - if ( RUParamList.numelt > 0) { - RC.ru = (RU_t **)malloc(RC.nb_RU*sizeof(RU_t *)); - RC.ru_mask=(1<idx = j; - RC.ru[j]->nr_frame_parms = (NR_DL_FRAME_PARMS *)malloc(sizeof(NR_DL_FRAME_PARMS)); - RC.ru[j]->frame_parms = (LTE_DL_FRAME_PARMS *)malloc(sizeof(LTE_DL_FRAME_PARMS)); - printf("Creating RC.ru[%d]:%p\n", j, RC.ru[j]); - RC.ru[j]->if_timing = synch_to_ext_device; - - 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 (i=0; inum_gNB; i++) RC.ru[j]->gNB_list[i] = RC.gNB[RUParamList.paramarray[j][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(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_D(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_D(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_D(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)); - } - } - else { - RC.ru[j]->openair0_cfg.clock_source = unset; - } - - 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_D(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_D(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_D(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)); - } - } - else { - RC.ru[j]->openair0_cfg.time_source = unset; - } - - 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; - printf("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; - printf("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; - printf("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; - printf("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; - printf("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]->num_bands = RUParamList.paramarray[j][RU_BAND_LIST_IDX].numelt; - - for (i=0; inum_bands; i++) RC.ru[j]->band[i] = RUParamList.paramarray[j][RU_BAND_LIST_IDX].iptr[i]; - } //strcmp(local_rf, "yes") == 0 - else { - printf("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), "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); - - if (config_isparamset(RUParamList.paramarray[j], RU_BF_WEIGHTS_LIST_IDX)) { - RC.ru[j]->nb_bfw = RUParamList.paramarray[j][RU_BF_WEIGHTS_LIST_IDX].numelt; - for (i=0; inum_gNB; i++) { - RC.ru[j]->bw_list[i] = (int32_t *)malloc16_clear((RC.ru[j]->nb_bfw)*sizeof(int32_t)); - for (int b=0; bnb_bfw; b++) RC.ru[j]->bw_list[i][b] = RUParamList.paramarray[j][RU_BF_WEIGHTS_LIST_IDX].iptr[b]; - } - } - }// j=0..num_rus - } else { - RC.nb_RU = 0; - } // setting != NULL - - return; -} - diff --git a/nfapi/oai_integration/nfapi_pnf.c b/nfapi/oai_integration/nfapi_pnf.c index a2d2a2863e..98757b09d0 100644 --- a/nfapi/oai_integration/nfapi_pnf.c +++ b/nfapi/oai_integration/nfapi_pnf.c @@ -73,6 +73,7 @@ extern pthread_mutex_t nfapi_sync_mutex; extern int nfapi_sync_var; extern int sync_var; +char uecap_xer_in; extern void init_eNB_afterRU(void); extern void init_UE_stub(int nb_inst,int,int); @@ -1242,7 +1243,6 @@ int pnf_phy_dl_tti_req(gNB_L1_rxtx_proc_t *proc, nfapi_pnf_p7_config_t *pnf_p7, memcpy(dl_tti_pdu,&dl_tti_pdu_list[i],sizeof(nfapi_nr_dl_tti_request_pdu_t)); int SFN=sfn+2; //if(!&dl_tti_pdu->pdcch_pdu) - printf("interleaversize = %d, coreset_type = %d. \n",dl_tti_pdu->pdcch_pdu.pdcch_pdu_rel15.InterleaverSize,dl_tti_pdu->pdcch_pdu.pdcch_pdu_rel15.CoreSetType); handle_nfapi_nr_pdcch_pdu(gNB, SFN, slot, &dl_tti_pdu->pdcch_pdu); //dl_tti_pdu_list[i].pdcch_pdu.pdcch_pdu_rel15.numDlDci++; // ? // NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() pdcch_vars->num_dci:%d\n", __FUNCTION__, pdcch_vars->num_dci); @@ -1474,7 +1474,6 @@ int pnf_phy_ul_tti_req(gNB_L1_rxtx_proc_t *proc, nfapi_pnf_p7_config_t *pnf_p7, switch (ul_tti_pdu_list[i].pdu_type) { case NFAPI_NR_UL_CONFIG_PUSCH_PDU_TYPE: //LOG_D(PHY,"frame %d, slot %d, Got NFAPI_NR_UL_TTI_PUSCH_PDU_TYPE for %d.%d\n", frame, slot, UL_tti_req->SFN, UL_tti_req->Slot); - //curr_sfn = curr_sfn + 3; //Gokul nr_fill_ulsch(gNB,curr_sfn, curr_slot, &ul_tti_pdu_list[i].pusch_pdu); break; case NFAPI_NR_UL_CONFIG_PUCCH_PDU_TYPE: @@ -2201,7 +2200,7 @@ void configure_nr_nfapi_pnf(char *vnf_ip_addr, int vnf_p5_port, char *pnf_ip_add pnf.phys[0].udp.tx_port = vnf_p7_port; strcpy(pnf.phys[0].udp.tx_addr, vnf_ip_addr); strcpy(pnf.phys[0].local_addr, pnf_ip_addr); - printf("%s() VNF:%s:%d PNF_PHY[addr:%s UDP:tx_addr:%s:%u rx:%u]\n", + printf("%s() VNF:%s:%d PNF_PHY[addr:%s UDP:tx_addr:%s:%d rx:%d]\n", __FUNCTION__,config->vnf_ip_addr, config->vnf_p5_port, pnf.phys[0].local_addr, pnf.phys[0].udp.tx_addr, pnf.phys[0].udp.tx_port, @@ -2252,7 +2251,7 @@ void configure_nfapi_pnf(char *vnf_ip_addr, int vnf_p5_port, char *pnf_ip_addr, pnf.phys[0].udp.tx_port = vnf_p7_port; strcpy(pnf.phys[0].udp.tx_addr, vnf_ip_addr); strcpy(pnf.phys[0].local_addr, pnf_ip_addr); - printf("%s() VNF:%s:%d PNF_PHY[addr:%s UDP:tx_addr:%s:%u rx:%u]\n", + printf("%s() VNF:%s:%d PNF_PHY[addr:%s UDP:tx_addr:%s:%d rx:%d]\n", __FUNCTION__, config->vnf_ip_addr, config->vnf_p5_port, pnf.phys[0].local_addr, @@ -2405,3 +2404,36 @@ int oai_nfapi_sr_indication(nfapi_sr_indication_t *ind) { //free(ind.rx_indication_body.rx_pdu_list); return retval; } + +//NR UPLINK INDICATION + +int oai_nfapi_nr_rx_data_indication(nfapi_nr_rx_data_indication_t *ind) { + ind->header.phy_id = 1; // DJP HACK TODO FIXME - need to pass this around!!!! + ind->header.message_id = NFAPI_NR_PHY_MSG_TYPE_RX_DATA_INDICATION; + return nfapi_pnf_p7_nr_rx_data_ind(p7_config_g, ind); +} + +int oai_nfapi_nr_crc_indication(nfapi_nr_crc_indication_t *ind) { + ind->header.phy_id = 1; // DJP HACK TODO FIXME - need to pass this around!!!! + ind->header.message_id = NFAPI_NR_PHY_MSG_TYPE_CRC_INDICATION; + return nfapi_pnf_p7_nr_crc_ind(p7_config_g, ind); +} + +int oai_nfapi_nr_srs_indication(nfapi_nr_srs_indication_t *ind) { + ind->header.phy_id = 1; // DJP HACK TODO FIXME - need to pass this around!!!! + ind->header.message_id = NFAPI_NR_PHY_MSG_TYPE_SRS_INDICATION; + return nfapi_pnf_p7_nr_srs_ind(p7_config_g, ind); +} + +int oai_nfapi_nr_uci_indication(nfapi_nr_uci_indication_t *ind) { + ind->header.phy_id = 1; // DJP HACK TODO FIXME - need to pass this around!!!! + ind->header.message_id = NFAPI_NR_PHY_MSG_TYPE_UCI_INDICATION; + return nfapi_pnf_p7_nr_uci_ind(p7_config_g, ind); +} + +int oai_nfapi_nr_rach_indication(nfapi_nr_rach_indication_t *ind) { + ind->header.phy_id = 1; // DJP 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); +} + diff --git a/nfapi/oai_integration/nfapi_pnf.h b/nfapi/oai_integration/nfapi_pnf.h index 61d4847eba..b3ab7cbdbc 100644 --- a/nfapi/oai_integration/nfapi_pnf.h +++ b/nfapi/oai_integration/nfapi_pnf.h @@ -21,7 +21,6 @@ #if !defined(NFAPI_PNF_H__) #define NFAPI_PNF_H__ -extern nfapi_ue_release_request_body_t release_rntis; int oai_nfapi_rach_ind(nfapi_rach_indication_t *rach_ind); void configure_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_pnf(char *vnf_ip_addr, int vnf_p5_port, char *pnf_ip_addr, int pnf_p7_port, int vnf_p7_port); diff --git a/nfapi/oai_integration/nfapi_vnf.c b/nfapi/oai_integration/nfapi_vnf.c index 7bbe51f3f0..12dda62eaf 100644 --- a/nfapi/oai_integration/nfapi_vnf.c +++ b/nfapi/oai_integration/nfapi_vnf.c @@ -250,7 +250,7 @@ void oai_create_gnb(void) { RC.gNB[0] = (PHY_VARS_gNB *) calloc(1, sizeof(PHY_VARS_gNB)); LOG_I(PHY,"[nr-gnb.c] gNB structure RC.gNB[%d] allocated @ %p\n",0,RC.gNB[0]); } - + PHY_VARS_gNB *gNB = RC.gNB[0]; RC.nb_nr_CC = (int *)malloc(sizeof(int)); // TODO: find a better function to place this in diff --git a/nfapi/open-nFAPI/common/src/debug.c b/nfapi/open-nFAPI/common/src/debug.c index f53be43223..a45d41d7d7 100644 --- a/nfapi/open-nFAPI/common/src/debug.c +++ b/nfapi/open-nFAPI/common/src/debug.c @@ -1,76 +1,76 @@ -/* - * 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. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#define MAX_MSG_LENGTH 2096 -#define TRACE_HEADER_LENGTH 44 - -void nfapi_trace_dbg(nfapi_trace_level_t level, const char *format, ...); - -// initialize the trace function to 0 -void (*nfapi_trace_g)(nfapi_trace_level_t level, const char* format, ...) = &nfapi_trace_dbg; - -nfapi_trace_level_t nfapi_trace_level_g = NFAPI_TRACE_INFO; -//nfapi_trace_level_t nfapi_trace_level_g = NFAPI_TRACE_WARN; - -void nfapi_set_trace_level(nfapi_trace_level_t new_level) -{ - nfapi_trace_level_g = new_level; -} - -void nfapi_trace_dbg(nfapi_trace_level_t level, const char *format, ...) -{ - char trace_buff[MAX_MSG_LENGTH + TRACE_HEADER_LENGTH]; - uint32_t num_chars; - va_list p_args; - struct timeval tv; - pthread_t tid = pthread_self(); - - (void)gettimeofday(&tv, NULL); - - num_chars = (uint32_t)snprintf(trace_buff, TRACE_HEADER_LENGTH, "%04u.%06u: 0x%02x: %10u: ", ((uint32_t)tv.tv_sec) & 0x1FFF, (uint32_t)tv.tv_usec, (uint32_t)level, (uint32_t)tid); - - if (num_chars > TRACE_HEADER_LENGTH) - { - printf("trace_dbg: Error, num_chars is too large: %u", num_chars); - return; - } - - va_start(p_args, format); - if ((num_chars = (uint32_t)vsnprintf(&trace_buff[num_chars], MAX_MSG_LENGTH, format, p_args))) - { - if (level <= NFAPI_TRACE_WARN) - { - printf("%s", trace_buff); - } - printf("%s", trace_buff); - } - va_end(p_args); -} +/* + * 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. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#define MAX_MSG_LENGTH 2096 +#define TRACE_HEADER_LENGTH 44 + +void nfapi_trace_dbg(nfapi_trace_level_t level, const char *format, ...); + +// initialize the trace function to 0 +void (*nfapi_trace_g)(nfapi_trace_level_t level, const char* format, ...) = &nfapi_trace_dbg; + +nfapi_trace_level_t nfapi_trace_level_g = NFAPI_TRACE_INFO; +//nfapi_trace_level_t nfapi_trace_level_g = NFAPI_TRACE_WARN; + +void nfapi_set_trace_level(nfapi_trace_level_t new_level) +{ + nfapi_trace_level_g = new_level; +} + +void nfapi_trace_dbg(nfapi_trace_level_t level, const char *format, ...) +{ + char trace_buff[MAX_MSG_LENGTH + TRACE_HEADER_LENGTH]; + uint32_t num_chars; + va_list p_args; + struct timeval tv; + pthread_t tid = pthread_self(); + + (void)gettimeofday(&tv, NULL); + + num_chars = (uint32_t)snprintf(trace_buff, TRACE_HEADER_LENGTH, "%04u.%06u: 0x%02x: %10u: ", ((uint32_t)tv.tv_sec) & 0x1FFF, (uint32_t)tv.tv_usec, (uint32_t)level, (uint32_t)tid); + + if (num_chars > TRACE_HEADER_LENGTH) + { + printf("trace_dbg: Error, num_chars is too large: %d", num_chars); + return; + } + + va_start(p_args, format); + if ((num_chars = (uint32_t)vsnprintf(&trace_buff[num_chars], MAX_MSG_LENGTH, format, p_args))) + { + if (level <= NFAPI_TRACE_WARN) + { + printf("%s", trace_buff); + } + printf("%s", trace_buff); + } + va_end(p_args); +} 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 0436f92a8d..9df9be4cbd 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 @@ -972,7 +972,7 @@ typedef struct typedef struct { - int ss_pbch_power;//SSB Block Power Value: TBD (-60..50 dBm) + uint32_t ss_pbch_power;//SSB Block Power Value: TBD (-60..50 dBm) uint8_t bch_payload;//Defines option selected for generation of BCH payload, see Table 3-13 (v0.0.011 Value: 0: MAC generates the full PBCH payload 1: PHY generates the timing PBCH bits 2: PHY generates the full PBCH payload uint8_t scs_common;//subcarrierSpacing for common, used for initial access and broadcast message. [38.211 sec 4.2] Value:0->3 @@ -1058,6 +1058,12 @@ typedef struct { fapi_nr_tdd_table_t tdd_table; fapi_nr_prach_config_t prach_config; + fapi_nr_dl_bwp_common_config_t dl_bwp_common; + fapi_nr_dl_bwp_dedicated_config_t dl_bwp_dedicated; + + fapi_nr_ul_bwp_common_config_t ul_bwp_common; + fapi_nr_ul_bwp_dedicated_config_t ul_bwp_dedicated; + } fapi_nr_config_request_t; #endif 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 bcb0a94ca8..aa3324e17d 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 @@ -1474,7 +1474,7 @@ typedef enum { //section 3.4.7 rx_data_indication -//table 3-61 +///table 3-61 typedef struct { @@ -1492,10 +1492,11 @@ typedef struct typedef struct { + nfapi_p7_message_header_t header; uint16_t sfn; uint16_t slot; uint16_t number_of_pdus; - nfapi_nr_rx_data_pdu_t* pdu_list; + nfapi_nr_rx_data_pdu_t *pdu_list; } nfapi_nr_rx_data_indication_t; @@ -1518,6 +1519,7 @@ typedef struct typedef struct { + nfapi_p7_message_header_t header; uint16_t sfn; uint16_t slot; uint16_t number_crcs; @@ -1655,6 +1657,7 @@ typedef struct typedef struct { + nfapi_p7_message_header_t header; uint16_t sfn; uint16_t slot; uint16_t num_ucis; @@ -1691,6 +1694,7 @@ typedef struct typedef struct { + nfapi_p7_message_header_t header; uint16_t sfn; uint16_t slot; uint8_t number_of_pdus; @@ -1723,6 +1727,7 @@ typedef struct{ typedef struct { + nfapi_p7_message_header_t header; uint16_t sfn; uint16_t slot; uint8_t number_of_pdus; diff --git a/nfapi/open-nFAPI/nfapi/src/nfapi_p7.c b/nfapi/open-nFAPI/nfapi/src/nfapi_p7.c index 8f6a736a14..4097217f99 100755 --- a/nfapi/open-nFAPI/nfapi/src/nfapi_p7.c +++ b/nfapi/open-nFAPI/nfapi/src/nfapi_p7.c @@ -1,8271 +1,8803 @@ -/* - * 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. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include "nfapi_nr_interface_scf.h" - -extern int nfapi_unpack_p7_vendor_extension(nfapi_p7_message_header_t* header, uint8_t **ppReadPackedMsg, void* user_data); -extern int nfapi_pack_p7_vendor_extension(nfapi_p7_message_header_t* header, uint8_t **ppWritePackedMsg, void* user_data); - -uint32_t nfapi_calculate_checksum(uint8_t* buffer, uint16_t len) -{ - uint32_t chksum = 0; - // calcaulte upto the checksum - chksum = crc32(chksum, buffer, 8); - - // skip the checksum - uint8_t zeros[4] = {0, 0, 0, 0}; - chksum = crc32(chksum, zeros, 4); - - // continu with the rest of the mesage - chksum = crc32(chksum, &buffer[NFAPI_P7_HEADER_LENGTH], len - NFAPI_P7_HEADER_LENGTH); - - // return the inverse - return ~(chksum); -} - -int nfapi_p7_update_checksum(uint8_t* buffer, uint32_t len) -{ - uint32_t checksum = nfapi_calculate_checksum(buffer, len); - - uint8_t* p_write = &buffer[8]; - return (push32(checksum, &p_write, buffer + len) > 0 ? 0 : -1); -} - -int nfapi_p7_update_transmit_timestamp(uint8_t* buffer, uint32_t timestamp) -{ - uint8_t* p_write = &buffer[12]; - return (push32(timestamp, &p_write, buffer + 16) > 0 ? 0 : -1); -} - -uint32_t nfapi_p7_calculate_checksum(uint8_t* buffer, uint32_t len) -{ - return nfapi_calculate_checksum(buffer, len); -} - -void* nfapi_p7_allocate(size_t size, nfapi_p7_codec_config_t* config) -{ - if(size == 0) - return 0; - - void* buffer_p = NULL; - if(config && config->allocate) - { - buffer_p = (config->allocate)(size); - if(buffer_p != NULL){ - memset(buffer_p,0,size); - } - return buffer_p; - } - else - { - buffer_p = calloc(1, size); - return buffer_p; - } -} - -void nfapi_p7_deallocate(void* ptr, nfapi_p7_codec_config_t* config) -{ - if(ptr == NULL) - return; - - if(config && config->deallocate) - { - return (config->deallocate)(ptr); - } - else - { - return free(ptr); - } -} -// Pack routines - - -static uint8_t pack_dl_config_dci_dl_pdu_rel8_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_dl_config_dci_dl_pdu_rel8_t* value = (nfapi_dl_config_dci_dl_pdu_rel8_t*)tlv; - - //NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s() dci_format:%u\n", __FUNCTION__, value->dci_format); - - return ( push8(value->dci_format, ppWritePackedMsg, end) && - push8(value->cce_idx, ppWritePackedMsg, end) && - push8(value->aggregation_level, ppWritePackedMsg, end) && - push16(value->rnti, ppWritePackedMsg, end) && - push8(value->resource_allocation_type, ppWritePackedMsg, end) && - push8(value->virtual_resource_block_assignment_flag, ppWritePackedMsg, end) && - push32(value->resource_block_coding, ppWritePackedMsg, end) && - push8(value->mcs_1, ppWritePackedMsg, end) && - push8(value->redundancy_version_1, ppWritePackedMsg, end) && - push8(value->new_data_indicator_1, ppWritePackedMsg, end) && - push8(value->transport_block_to_codeword_swap_flag, ppWritePackedMsg, end) && - push8(value->mcs_2, ppWritePackedMsg, end) && - push8(value->redundancy_version_2, ppWritePackedMsg, end) && - push8(value->new_data_indicator_2, ppWritePackedMsg, end) && - push8(value->harq_process, ppWritePackedMsg, end) && - push8(value->tpmi, ppWritePackedMsg, end) && - push8(value->pmi, ppWritePackedMsg, end) && - push8(value->precoding_information, ppWritePackedMsg, end) && - push8(value->tpc, ppWritePackedMsg, end) && - push8(value->downlink_assignment_index, ppWritePackedMsg, end) && - push8(value->ngap, ppWritePackedMsg, end) && - push8(value->transport_block_size_index, ppWritePackedMsg, end) && - push8(value->downlink_power_offset, ppWritePackedMsg, end) && - push8(value->allocate_prach_flag, ppWritePackedMsg, end) && - push8(value->preamble_index, ppWritePackedMsg, end) && - push8(value->prach_mask_index, ppWritePackedMsg, end) && - push8(value->rnti_type, ppWritePackedMsg, end) && - push16(value->transmission_power, ppWritePackedMsg, end)); -} - -static uint8_t pack_dl_config_dci_dl_pdu_rel9_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_dl_config_dci_dl_pdu_rel9_t* value = (nfapi_dl_config_dci_dl_pdu_rel9_t*)tlv; - - return( push8(value->mcch_flag, ppWritePackedMsg, end) && - push8(value->mcch_change_notification, ppWritePackedMsg, end) && - push8(value->scrambling_identity, ppWritePackedMsg, end)); -} - -static uint8_t pack_dl_config_dci_dl_pdu_rel10_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_dl_config_dci_dl_pdu_rel10_t* value = (nfapi_dl_config_dci_dl_pdu_rel10_t*)tlv; - - return ( push8(value->cross_carrier_scheduling_flag, ppWritePackedMsg, end) && - push8(value->carrier_indicator, ppWritePackedMsg, end) && - push8(value->srs_flag, ppWritePackedMsg, end) && - push8(value->srs_request, ppWritePackedMsg, end) && - push8(value->antenna_ports_scrambling_and_layers, ppWritePackedMsg, end) && - push8(value->total_dci_length_including_padding, ppWritePackedMsg, end) && - push8(value->n_dl_rb, ppWritePackedMsg, end)); -} - -static uint8_t pack_dl_config_dci_dl_pdu_rel11_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_dl_config_dci_dl_pdu_rel11_t* value = (nfapi_dl_config_dci_dl_pdu_rel11_t*)tlv; - - return ( push8(value->harq_ack_resource_offset, ppWritePackedMsg, end) && - push8(value->pdsch_re_mapping_quasi_co_location_indicator, ppWritePackedMsg, end)); -} - -static uint8_t pack_dl_config_dci_dl_pdu_rel12_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_dl_config_dci_dl_pdu_rel12_t* value = (nfapi_dl_config_dci_dl_pdu_rel12_t*)tlv; - - return ( push8(value->primary_cell_type, ppWritePackedMsg, end) && - push8(value->ul_dl_configuration_flag, ppWritePackedMsg, end) && - push8(value->number_ul_dl_configurations, ppWritePackedMsg, end) && - pusharray8(value->ul_dl_configuration_indication, NFAPI_MAX_UL_DL_CONFIGURATIONS, value->number_ul_dl_configurations, ppWritePackedMsg, end)); -} - -static uint8_t pack_tpm_value(nfapi_dl_config_dci_dl_tpm_t* value, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - if (!( push8(value->num_prb_per_subband, ppWritePackedMsg, end) && - push8(value->number_of_subbands, ppWritePackedMsg, end) && - push8(value->num_antennas, ppWritePackedMsg, end))) - return 0; - - uint8_t idx = 0; - for(idx = 0; idx < value->number_of_subbands; ++idx) - { - nfapi_dl_config_dci_dl_tpm_subband_info_t* subband_info = &(value->subband_info[idx]); - - if(!(push8(subband_info->subband_index, ppWritePackedMsg, end) && - push8(subband_info->scheduled_ues, ppWritePackedMsg, end))) - return 0; - - - uint8_t antenna_idx = 0; - uint8_t scheduled_ue_idx = 0; - - for(antenna_idx = 0; antenna_idx < value->num_antennas; ++antenna_idx) - { - for(scheduled_ue_idx = 0; scheduled_ue_idx < subband_info->scheduled_ues; ++scheduled_ue_idx) - { - if(!push16(subband_info->precoding_value[antenna_idx][scheduled_ue_idx], ppWritePackedMsg, end)) - return 0; - } - } - - } - - - return 1; - -} - - -static uint8_t pack_dl_tti_csi_rs_pdu_rel15_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_nr_dl_tti_csi_rs_pdu_rel15_t* value = (nfapi_nr_dl_tti_csi_rs_pdu_rel15_t*)tlv; - - return( - push16(value->bwp_size, ppWritePackedMsg, end) && - push16(value->bwp_start, ppWritePackedMsg, end) && - - push8(value->subcarrier_spacing, ppWritePackedMsg, end) && - push8(value->cyclic_prefix, ppWritePackedMsg, end) && - - push16(value->start_rb, ppWritePackedMsg, end) && - push16(value->nr_of_rbs, ppWritePackedMsg, end) && - - push8(value->csi_type, ppWritePackedMsg, end) && - push8(value->row, ppWritePackedMsg, end) && - - push16(value->freq_domain, ppWritePackedMsg, end) && - push8(value->symb_l0, ppWritePackedMsg, end) && - - push8(value->symb_l1, ppWritePackedMsg, end) && - push8(value->cdm_type, ppWritePackedMsg, end) && - - push8(value->freq_density, ppWritePackedMsg, end) && - push16(value->scramb_id, ppWritePackedMsg, end) && - - push8(value->power_control_offset, ppWritePackedMsg, end) && - push8(value->power_control_offset_ss, ppWritePackedMsg, end) - ); - -} - - -static uint8_t pack_dl_tti_pdcch_pdu_rel15_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_nr_dl_tti_pdcch_pdu_rel15_t* value = (nfapi_nr_dl_tti_pdcch_pdu_rel15_t*)tlv; - - for(uint8_t i = 0; i < MAX_DCI_CORESET; ++i) - { - if(!(push16(value->dci_pdu[i].RNTI, ppWritePackedMsg, end) && - push16(value->dci_pdu[i].ScramblingId, ppWritePackedMsg, end) && - - push16(value->dci_pdu[i].ScramblingRNTI, ppWritePackedMsg, end) && - push8(value->dci_pdu[i].CceIndex, ppWritePackedMsg, end) && - push8(value->dci_pdu[i].AggregationLevel, ppWritePackedMsg, end) && - push8(value->dci_pdu[i].beta_PDCCH_1_0, ppWritePackedMsg, end) && - - push8(value->dci_pdu[i].powerControlOffsetSS, ppWritePackedMsg, end) && - push16(value->dci_pdu[i].PayloadSizeBits, ppWritePackedMsg, end) && - pusharray8(value->dci_pdu[i].Payload, value->dci_pdu[i].PayloadSizeBits, value->dci_pdu[i].PayloadSizeBits, ppWritePackedMsg, end))) - return 0; - - } - - // TODO: resolve the packaging of array (currently sending a single element) - return( - push16(value->BWPSize, ppWritePackedMsg, end) && - push16(value->BWPStart, ppWritePackedMsg, end) && - push8(value->SubcarrierSpacing, ppWritePackedMsg, end) && - push8(value->CyclicPrefix, ppWritePackedMsg, end) && - - push8(value->StartSymbolIndex, ppWritePackedMsg, end) && - push8(value->DurationSymbols, ppWritePackedMsg, end) && - pusharray8(value->FreqDomainResource, 6, 6, ppWritePackedMsg, end) && - push8(value->CceRegMappingType, ppWritePackedMsg, end) && - - push8(value->RegBundleSize, ppWritePackedMsg, end) && - push8(value->InterleaverSize, ppWritePackedMsg, end) && - push8(value->CoreSetType, ppWritePackedMsg, end) && - push16(value->ShiftIndex, ppWritePackedMsg, end) && - - push8(value->precoderGranularity, ppWritePackedMsg, end) && - push16(value->numDlDci, ppWritePackedMsg, end)); - -} - - -static uint8_t pack_dl_tti_pdsch_pdu_rel15_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_nr_dl_tti_pdsch_pdu_rel15_t* value = (nfapi_nr_dl_tti_pdsch_pdu_rel15_t*)tlv; - - // TODO: resolve the packaging of array (currently sending a single element) - return( - push16(value->pduBitmap, ppWritePackedMsg, end) && - push16(value->rnti, ppWritePackedMsg, end) && - push16(value->pduIndex, ppWritePackedMsg, end) && - push16(value->BWPSize, ppWritePackedMsg, end) && - - push16(value->BWPStart, ppWritePackedMsg, end) && - push8(value->SubcarrierSpacing, ppWritePackedMsg, end) && - push8(value->CyclicPrefix, ppWritePackedMsg, end) && - push8(value->NrOfCodewords, ppWritePackedMsg, end) && - - pusharray16(value->targetCodeRate, 2, 1, ppWritePackedMsg, end) && - pusharray8(value->qamModOrder, 2, 1, ppWritePackedMsg, end) && - pusharray8(value->mcsIndex, 2, 1, ppWritePackedMsg, end) && - pusharray8(value->mcsTable, 2, 1, ppWritePackedMsg, end) && - - pusharray8(value->rvIndex, 2, 1, ppWritePackedMsg, end) && - pusharray32(value->TBSize, 2, 1, ppWritePackedMsg, end) && - push16(value->dataScramblingId, ppWritePackedMsg, end) && - push8(value->nrOfLayers, ppWritePackedMsg, end) && - - push8(value->transmissionScheme, ppWritePackedMsg, end) && - push8(value->refPoint, ppWritePackedMsg, end) && - push16(value->dlDmrsSymbPos, ppWritePackedMsg, end) && - push8(value->dmrsConfigType, ppWritePackedMsg, end) && - - push16(value->dlDmrsScramblingId, ppWritePackedMsg, end) && - push8(value->SCID, ppWritePackedMsg, end) && - push8(value->numDmrsCdmGrpsNoData, ppWritePackedMsg, end) && - push16(value->dmrsPorts, ppWritePackedMsg, end) && - - push8(value->resourceAlloc, ppWritePackedMsg, end) && - push16(value->rbStart, ppWritePackedMsg, end) && - push16(value->rbSize, ppWritePackedMsg, end) && - - push8(value->VRBtoPRBMapping, ppWritePackedMsg, end) && - push8(value->StartSymbolIndex, ppWritePackedMsg, end) && - push8(value->NrOfSymbols, ppWritePackedMsg, end) && - push8(value->PTRSPortIndex, ppWritePackedMsg, end) && - - push8(value->PTRSTimeDensity, ppWritePackedMsg, end) && - push8(value->PTRSFreqDensity, ppWritePackedMsg, end) && - push8(value->PTRSReOffset, ppWritePackedMsg, end) - ); - -} - - -static uint8_t pack_dl_tti_ssb_pdu_rel15_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - printf("Packing ssb. \n"); - nfapi_nr_dl_tti_ssb_pdu_rel15_t* value = (nfapi_nr_dl_tti_ssb_pdu_rel15_t*)tlv; - - return( - push16(value->PhysCellId, ppWritePackedMsg, end) && - push8(value->BetaPss, ppWritePackedMsg, end) && - push8(value->SsbBlockIndex, ppWritePackedMsg, end) && - push8(value->SsbSubcarrierOffset, ppWritePackedMsg, end) && - push16(value->ssbOffsetPointA, ppWritePackedMsg, end) && - push8(value->bchPayloadFlag, ppWritePackedMsg, end) && - push32(value->bchPayload, ppWritePackedMsg, end) - // TODO: pack precoding_and_beamforming too - ); - -} - - -static uint8_t pack_dl_config_dci_dl_pdu_rel13_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_dl_config_dci_dl_pdu_rel13_t* value = (nfapi_dl_config_dci_dl_pdu_rel13_t*)tlv; - - return( push8(value->laa_end_partial_sf_flag, ppWritePackedMsg, end) && - push8(value->laa_end_partial_sf_configuration, ppWritePackedMsg, end) && - push8(value->initial_lbt_sf, ppWritePackedMsg, end) && - push8(value->codebook_size_determination, ppWritePackedMsg, end) && - push8(value->drms_table_flag, ppWritePackedMsg, end) && - push8(value->tpm_struct_flag, ppWritePackedMsg, end) && - (value->tpm_struct_flag == 1 ? pack_tpm_value(&(value->tpm), ppWritePackedMsg, end) : 1)); -} - -static uint8_t pack_dl_config_bch_pdu_rel8_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_dl_config_bch_pdu_rel8_t* value = (nfapi_dl_config_bch_pdu_rel8_t*)tlv; - - //NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s()\n", __FUNCTION__); - - return( push16(value->length, ppWritePackedMsg, end) && - push16(value->pdu_index, ppWritePackedMsg, end) && - push16(value->transmission_power, ppWritePackedMsg, end)); -} -static uint8_t pack_dl_config_mch_pdu_rel8_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_dl_config_mch_pdu_rel8_t* value = (nfapi_dl_config_mch_pdu_rel8_t*)tlv; - - return ( push16(value->length, ppWritePackedMsg, end) && - push16(value->pdu_index, ppWritePackedMsg, end) && - push16(value->rnti, ppWritePackedMsg, end) && - push8(value->resource_allocation_type, ppWritePackedMsg, end) && - push32(value->resource_block_coding, ppWritePackedMsg, end) && - push8(value->modulation, ppWritePackedMsg, end) && - push16(value->transmission_power, ppWritePackedMsg, end) && - push16(value->mbsfn_area_id, ppWritePackedMsg, end)); -} - -static uint8_t pack_bf_vector_info(void* elem, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_bf_vector_t* bf = (nfapi_bf_vector_t*)elem; - - return ( push8(bf->subband_index, ppWritePackedMsg, end) && - push8(bf->num_antennas, ppWritePackedMsg, end) && - pusharray16(bf->bf_value, NFAPI_MAX_NUM_ANTENNAS, bf->num_antennas, ppWritePackedMsg, end)); - - -} -static uint8_t pack_dl_config_dlsch_pdu_rel8_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_dl_config_dlsch_pdu_rel8_t* value = (nfapi_dl_config_dlsch_pdu_rel8_t*)tlv; - - return ( push16(value->length, ppWritePackedMsg, end) && - push16(value->pdu_index, ppWritePackedMsg, end) && - push16(value->rnti, ppWritePackedMsg, end) && - push8(value->resource_allocation_type, ppWritePackedMsg, end) && - push8(value->virtual_resource_block_assignment_flag, ppWritePackedMsg, end) && - push32(value->resource_block_coding, ppWritePackedMsg, end) && - push8(value->modulation, ppWritePackedMsg, end) && - push8(value->redundancy_version, ppWritePackedMsg, end) && - push8(value->transport_blocks, ppWritePackedMsg, end) && - push8(value->transport_block_to_codeword_swap_flag, ppWritePackedMsg, end) && - push8(value->transmission_scheme, ppWritePackedMsg, end) && - push8(value->number_of_layers, ppWritePackedMsg, end) && - push8(value->number_of_subbands, ppWritePackedMsg, end) && - pusharray8(value->codebook_index, NFAPI_MAX_NUM_SUBBANDS, value->number_of_subbands, ppWritePackedMsg, end) && - push8(value->ue_category_capacity, ppWritePackedMsg, end) && - push8(value->pa, ppWritePackedMsg, end) && - push8(value->delta_power_offset_index, ppWritePackedMsg, end) && - push8(value->ngap, ppWritePackedMsg, end) && - push8(value->nprb, ppWritePackedMsg, end) && - push8(value->transmission_mode, ppWritePackedMsg, end) && - push8(value->num_bf_prb_per_subband, ppWritePackedMsg, end) && - push8(value->num_bf_vector, ppWritePackedMsg, end) && - packarray(value->bf_vector, sizeof(nfapi_bf_vector_t), NFAPI_MAX_BF_VECTORS, value->num_bf_vector, ppWritePackedMsg, end, &pack_bf_vector_info)); - -} -static uint8_t pack_dl_config_dlsch_pdu_rel9_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_dl_config_dlsch_pdu_rel9_t* value = (nfapi_dl_config_dlsch_pdu_rel9_t*)tlv; - return ( push8(value->nscid, ppWritePackedMsg, end) ); -} -static uint8_t pack_dl_config_dlsch_pdu_rel10_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_dl_config_dlsch_pdu_rel10_t* value = (nfapi_dl_config_dlsch_pdu_rel10_t*)tlv; - - return ( push8(value->csi_rs_flag, ppWritePackedMsg, end) && - push8(value->csi_rs_resource_config_r10, ppWritePackedMsg, end) && - push16(value->csi_rs_zero_tx_power_resource_config_bitmap_r10, ppWritePackedMsg, end) && - push8(value->csi_rs_number_nzp_configuration, ppWritePackedMsg, end) && - pusharray8(value->csi_rs_resource_config, NFAPI_MAX_CSI_RS_RESOURCE_CONFIG, value->csi_rs_number_nzp_configuration, ppWritePackedMsg, end) && - push8(value->pdsch_start, ppWritePackedMsg, end)); -} -static uint8_t pack_dl_config_dlsch_pdu_rel11_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_dl_config_dlsch_pdu_rel11_t* value = (nfapi_dl_config_dlsch_pdu_rel11_t*)tlv; - - return( push8(value->drms_config_flag, ppWritePackedMsg, end) && - push16(value->drms_scrambling, ppWritePackedMsg, end) && - push8(value->csi_config_flag, ppWritePackedMsg, end) && - push16(value->csi_scrambling, ppWritePackedMsg, end) && - push8(value->pdsch_re_mapping_flag, ppWritePackedMsg, end) && - push8(value->pdsch_re_mapping_atenna_ports, ppWritePackedMsg, end) && - push8(value->pdsch_re_mapping_freq_shift, ppWritePackedMsg, end)); -} -static uint8_t pack_dl_config_dlsch_pdu_rel12_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_dl_config_dlsch_pdu_rel12_t* value = (nfapi_dl_config_dlsch_pdu_rel12_t*)tlv; - - return( push8(value->altcqi_table_r12, ppWritePackedMsg, end) && - push8(value->maxlayers, ppWritePackedMsg, end) && - push8(value->n_dl_harq, ppWritePackedMsg, end)); -} -static uint8_t pack_dl_config_dlsch_pdu_rel13_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_dl_config_dlsch_pdu_rel13_t* value = (nfapi_dl_config_dlsch_pdu_rel13_t*)tlv; - - return( push8(value->dwpts_symbols, ppWritePackedMsg, end) && - push8(value->initial_lbt_sf, ppWritePackedMsg, end) && - push8(value->ue_type, ppWritePackedMsg, end) && - push8(value->pdsch_payload_type, ppWritePackedMsg, end) && - push16(value->initial_transmission_sf_io, ppWritePackedMsg, end) && - push8(value->drms_table_flag, ppWritePackedMsg, end)); -} -static uint8_t pack_dl_config_pch_pdu_rel8_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_dl_config_pch_pdu_rel8_t* value = (nfapi_dl_config_pch_pdu_rel8_t*)tlv; - - return( push16(value->length, ppWritePackedMsg, end) && - push16(value->pdu_index, ppWritePackedMsg, end) && - push16(value->p_rnti, ppWritePackedMsg, end) && - push8(value->resource_allocation_type, ppWritePackedMsg, end) && - push8(value->virtual_resource_block_assignment_flag, ppWritePackedMsg, end) && - push32(value->resource_block_coding, ppWritePackedMsg, end) && - push8(value->mcs, ppWritePackedMsg, end) && - push8(value->redundancy_version, ppWritePackedMsg, end) && - push8(value->number_of_transport_blocks, ppWritePackedMsg, end) && - push8(value->transport_block_to_codeword_swap_flag, ppWritePackedMsg, end) && - push8(value->transmission_scheme, ppWritePackedMsg, end) && - push8(value->number_of_layers, ppWritePackedMsg, end) && - push8(value->codebook_index, ppWritePackedMsg, end) && - push8(value->ue_category_capacity, ppWritePackedMsg, end) && - push8(value->pa, ppWritePackedMsg, end) && - push16(value->transmission_power, ppWritePackedMsg, end) && - push8(value->nprb, ppWritePackedMsg, end) && - push8(value->ngap, ppWritePackedMsg, end)); -} -static uint8_t pack_dl_config_pch_pdu_rel13_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_dl_config_pch_pdu_rel13_t* value = (nfapi_dl_config_pch_pdu_rel13_t*)tlv; - - return ( push8(value->ue_mode, ppWritePackedMsg, end) && - push16(value->initial_transmission_sf_io, ppWritePackedMsg, end)); -} -static uint8_t pack_dl_config_prs_pdu_rel9_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_dl_config_prs_pdu_rel9_t* value = (nfapi_dl_config_prs_pdu_rel9_t*)tlv; - - return( push16(value->transmission_power, ppWritePackedMsg, end) && - push8(value->prs_bandwidth, ppWritePackedMsg, end) && - push8(value->prs_cyclic_prefix_type, ppWritePackedMsg, end) && - push8(value->prs_muting, ppWritePackedMsg, end)); -} -static uint8_t pack_dl_config_csi_rs_pdu_rel10_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_dl_config_csi_rs_pdu_rel10_t* value = (nfapi_dl_config_csi_rs_pdu_rel10_t*)tlv; - - return( push8(value->csi_rs_antenna_port_count_r10, ppWritePackedMsg, end) && - push8(value->csi_rs_resource_config_r10, ppWritePackedMsg, end) && - push16(value->transmission_power, ppWritePackedMsg, end) && - push16(value->csi_rs_zero_tx_power_resource_config_bitmap_r10, ppWritePackedMsg, end) && - push8(value->csi_rs_number_of_nzp_configuration, ppWritePackedMsg, end) && - pusharray8(value->csi_rs_resource_config, NFAPI_MAX_CSI_RS_RESOURCE_CONFIG, value->csi_rs_number_of_nzp_configuration, ppWritePackedMsg, end)); -} -static uint8_t pack_dl_config_csi_rs_pdu_rel13_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_dl_config_csi_rs_pdu_rel13_t* value = (nfapi_dl_config_csi_rs_pdu_rel13_t*)tlv; - - if(!(push8(value->csi_rs_class, ppWritePackedMsg, end) && - push8(value->cdm_type, ppWritePackedMsg, end) && - push8(value->num_bf_vector, ppWritePackedMsg, end))) - { - return 0; - } - - uint16_t i; - for(i = 0; i < value->num_bf_vector; ++i) - { - if(!(push8(value->bf_vector[i].csi_rs_resource_index, ppWritePackedMsg, end) && - pusharray16(value->bf_vector[i].bf_value, NFAPI_MAX_ANTENNA_PORT_COUNT, NFAPI_MAX_ANTENNA_PORT_COUNT, ppWritePackedMsg, end))) - return 0; - } - - return 1; -} -static uint8_t pack_bf_vector(nfapi_bf_vector_t* vector, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - return ( push8(vector->subband_index, ppWritePackedMsg, end) && - push8(vector->num_antennas, ppWritePackedMsg, end) && - pusharray16(vector->bf_value, NFAPI_MAX_NUM_ANTENNAS, vector->num_antennas, ppWritePackedMsg, end)); -} - -static uint8_t pack_dl_config_epdcch_parameters_rel11_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_dl_config_epdcch_parameters_rel11_t* value = (nfapi_dl_config_epdcch_parameters_rel11_t*)tlv; - - return ( push8(value->epdcch_resource_assignment_flag, ppWritePackedMsg, end) && - push16(value->epdcch_id, ppWritePackedMsg, end) && - push8(value->epdcch_start_symbol, ppWritePackedMsg, end) && - push8(value->epdcch_num_prb, ppWritePackedMsg, end) && - pusharray8(value->epdcch_prb_index, NFAPI_MAX_EPDCCH_PRB, value->epdcch_num_prb, ppWritePackedMsg, end) && - pack_bf_vector(&value->bf_vector, ppWritePackedMsg, end)); -} -static uint8_t pack_dl_config_epdcch_parameters_rel13_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_dl_config_epdcch_parameters_rel13_t* value = (nfapi_dl_config_epdcch_parameters_rel13_t*)tlv; - - return (push8(value->dwpts_symbols, ppWritePackedMsg, end) && - push8(value->initial_lbt_sf, ppWritePackedMsg, end)); -} -static uint8_t pack_dl_config_mpdcch_pdu_rel13_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_dl_config_mpdcch_pdu_rel13_t* value = (nfapi_dl_config_mpdcch_pdu_rel13_t*)tlv; - - return ( push8(value->mpdcch_narrow_band, ppWritePackedMsg, end) && - push8(value->number_of_prb_pairs, ppWritePackedMsg, end) && - push8(value->resource_block_assignment, ppWritePackedMsg, end) && - push8(value->mpdcch_tansmission_type, ppWritePackedMsg, end) && - push8(value->start_symbol, ppWritePackedMsg, end) && - push8(value->ecce_index, ppWritePackedMsg, end) && - push8(value->aggregation_level, ppWritePackedMsg, end) && - push8(value->rnti_type, ppWritePackedMsg, end) && - push16(value->rnti, ppWritePackedMsg, end) && - push8(value->ce_mode, ppWritePackedMsg, end) && - push16(value->drms_scrambling_init, ppWritePackedMsg, end) && - push16(value->initial_transmission_sf_io, ppWritePackedMsg, end) && - push16(value->transmission_power, ppWritePackedMsg, end) && - push8(value->dci_format, ppWritePackedMsg, end) && - push16(value->resource_block_coding, ppWritePackedMsg, end) && - push8(value->mcs, ppWritePackedMsg, end) && - push8(value->pdsch_reptition_levels, ppWritePackedMsg, end) && - push8(value->redundancy_version, ppWritePackedMsg, end) && - push8(value->new_data_indicator, ppWritePackedMsg, end) && - push8(value->harq_process, ppWritePackedMsg, end) && - push8(value->tpmi_length, ppWritePackedMsg, end) && - push8(value->tpmi, ppWritePackedMsg, end) && - push8(value->pmi_flag, ppWritePackedMsg, end) && - push8(value->pmi, ppWritePackedMsg, end) && - push8(value->harq_resource_offset, ppWritePackedMsg, end) && - push8(value->dci_subframe_repetition_number, ppWritePackedMsg, end) && - push8(value->tpc, ppWritePackedMsg, end) && - push8(value->downlink_assignment_index_length, ppWritePackedMsg, end) && - push8(value->downlink_assignment_index, ppWritePackedMsg, end) && - push8(value->allocate_prach_flag, ppWritePackedMsg, end) && - push8(value->preamble_index, ppWritePackedMsg, end) && - push8(value->prach_mask_index, ppWritePackedMsg, end) && - push8(value->starting_ce_level, ppWritePackedMsg, end) && - push8(value->srs_request, ppWritePackedMsg, end) && - push8(value->antenna_ports_and_scrambling_identity_flag, ppWritePackedMsg, end) && - push8(value->antenna_ports_and_scrambling_identity, ppWritePackedMsg, end) && - push8(value->frequency_hopping_enabled_flag, ppWritePackedMsg, end) && - push8(value->paging_direct_indication_differentiation_flag, ppWritePackedMsg, end) && - push8(value->direct_indication, ppWritePackedMsg, end) && - push8(value->total_dci_length_including_padding, ppWritePackedMsg, end) && - push8(value->number_of_tx_antenna_ports, ppWritePackedMsg, end) && - pusharray16(value->precoding_value, NFAPI_MAX_TX_PHYSICAL_ANTENNA_PORTS, value->number_of_tx_antenna_ports, ppWritePackedMsg, end)); -} - - -static uint8_t pack_dl_config_nbch_pdu_rel13_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_dl_config_nbch_pdu_rel13_t* value = (nfapi_dl_config_nbch_pdu_rel13_t*)tlv; - - return (push16(value->length, ppWritePackedMsg, end) && - push16(value->pdu_index, ppWritePackedMsg, end) && - push16(value->transmission_power, ppWritePackedMsg, end) && - push16(value->hyper_sfn_2_lsbs, ppWritePackedMsg, end)); -} - - -static uint8_t pack_dl_config_npdcch_pdu_rel13_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_dl_config_npdcch_pdu_rel13_t* value = (nfapi_dl_config_npdcch_pdu_rel13_t*)tlv; - - return (push16(value->length, ppWritePackedMsg, end) && - push16(value->pdu_index, ppWritePackedMsg, end) && - push8(value->ncce_index, ppWritePackedMsg, end) && - push8(value->aggregation_level, ppWritePackedMsg, end) && - push8(value->start_symbol, ppWritePackedMsg, end) && - push8(value->rnti_type, ppWritePackedMsg, end) && - push16(value->rnti, ppWritePackedMsg, end) && - push8(value->scrambling_reinitialization_batch_index, ppWritePackedMsg, end) && - push8(value->nrs_antenna_ports_assumed_by_the_ue, ppWritePackedMsg, end) && - push8(value->dci_format, ppWritePackedMsg, end) && - push8(value->scheduling_delay, ppWritePackedMsg, end) && - push8(value->resource_assignment, ppWritePackedMsg, end) && - push8(value->repetition_number, ppWritePackedMsg, end) && - push8(value->mcs, ppWritePackedMsg, end) && - push8(value->new_data_indicator, ppWritePackedMsg, end) && - push8(value->harq_ack_resource, ppWritePackedMsg, end) && - push8(value->npdcch_order_indication, ppWritePackedMsg, end) && - push8(value->starting_number_of_nprach_repetitions, ppWritePackedMsg, end) && - push8(value->subcarrier_indication_of_nprach, ppWritePackedMsg, end) && - push8(value->paging_direct_indication_differentation_flag, ppWritePackedMsg, end) && - push8(value->direct_indication, ppWritePackedMsg, end) && - push8(value->dci_subframe_repetition_number, ppWritePackedMsg, end) && - push8(value->total_dci_length_including_padding, ppWritePackedMsg, end)); -} - -static uint8_t pack_dl_config_ndlsch_pdu_rel13_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_dl_config_ndlsch_pdu_rel13_t* value = (nfapi_dl_config_ndlsch_pdu_rel13_t*)tlv; - - return (push16(value->length, ppWritePackedMsg, end) && - push16(value->pdu_index, ppWritePackedMsg, end) && - push8(value->start_symbol, ppWritePackedMsg, end) && - push8(value->rnti_type, ppWritePackedMsg, end) && - push16(value->rnti, ppWritePackedMsg, end) && - push16(value->resource_assignment, ppWritePackedMsg, end) && - push16(value->repetition_number, ppWritePackedMsg, end) && - push8(value->modulation, ppWritePackedMsg, end) && - push8(value->number_of_subframes_for_resource_assignment, ppWritePackedMsg, end) && - push8(value->scrambling_sequence_initialization_cinit, ppWritePackedMsg, end) && - push16(value->sf_idx, ppWritePackedMsg, end) && - push8(value->nrs_antenna_ports_assumed_by_the_ue, ppWritePackedMsg, end)); -} - - -static uint8_t pack_dl_tti_request_body_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_nr_dl_tti_request_pdu_t* value = (nfapi_nr_dl_tti_request_pdu_t*)tlv; - - if(!(push16(value->PDUSize, ppWritePackedMsg, end) && - push16(value->PDUType, ppWritePackedMsg, end) )) - return 0; - - - // first match the pdu type, then call the respective function - switch(value->PDUType) - { - case NFAPI_NR_DL_TTI_CSI_RS_PDU_TYPE: - { - if(!(pack_dl_tti_csi_rs_pdu_rel15_value(&value->csi_rs_pdu.csi_rs_pdu_rel15,ppWritePackedMsg,end))) - return 0; - } - break; - - case NFAPI_NR_DL_TTI_PDCCH_PDU_TYPE: - { - if(!(pack_dl_tti_pdcch_pdu_rel15_value(&value->pdcch_pdu.pdcch_pdu_rel15,ppWritePackedMsg,end))) - return 0; - } - break; - case NFAPI_NR_DL_TTI_PDSCH_PDU_TYPE: - { - if(!(pack_dl_tti_pdsch_pdu_rel15_value(&value->pdsch_pdu.pdsch_pdu_rel15,ppWritePackedMsg,end))) - return 0; - } - break; - case NFAPI_NR_DL_TTI_SSB_PDU_TYPE: - { - if(!(pack_dl_tti_ssb_pdu_rel15_value(&value->ssb_pdu.ssb_pdu_rel15,ppWritePackedMsg,end))) - return 0; - } - break; - - default: - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "FIXME : Invalid DL_TTI pdu type %d \n", value->PDUType ); - } - break; - } - - return 1; -} - -static uint8_t pack_dl_config_request_body_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_dl_config_request_body_t* value = (nfapi_dl_config_request_body_t*)tlv; - - //NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s() dci:%u pdu:%u pdsch:%u rnti:%u pcfich:%u\n", __FUNCTION__, value->number_dci, value->number_pdu, value->number_pdsch_rnti, value->transmission_power_pcfich); - - if(!(push8(value->number_pdcch_ofdm_symbols, ppWritePackedMsg, end) && - push8(value->number_dci, ppWritePackedMsg, end) && - push16(value->number_pdu, ppWritePackedMsg, end) && - push8(value->number_pdsch_rnti, ppWritePackedMsg, end) && - push16(value->transmission_power_pcfich, ppWritePackedMsg, end))) - { - return 0; - } - - uint16_t i = 0; - uint16_t total_number_of_pdus = value->number_pdu; - for(; i < total_number_of_pdus; ++i) - { - nfapi_dl_config_request_pdu_t* pdu = &(value->dl_config_pdu_list[i]); - - if(push8(pdu->pdu_type, ppWritePackedMsg, end) == 0) - return 0; - - // Put a 0 size in and then determine the size after the pdu - // has been writen and write the calculated size - uint8_t* pWritePackedMsgPduSize = *ppWritePackedMsg; - pdu->pdu_size = 0; - if(push8(pdu->pdu_size, ppWritePackedMsg, end) == 0) - return 0; - - switch(pdu->pdu_type) - { - case NFAPI_DL_CONFIG_DCI_DL_PDU_TYPE: - { - //NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s() NFAPI_DL_CONFIG_DCI_DL_PDU_TYPE\n", __FUNCTION__); - - if(!(pack_tlv(NFAPI_DL_CONFIG_REQUEST_DCI_DL_PDU_REL8_TAG, &pdu->dci_dl_pdu.dci_dl_pdu_rel8, ppWritePackedMsg, end, &pack_dl_config_dci_dl_pdu_rel8_value) && - pack_tlv(NFAPI_DL_CONFIG_REQUEST_DCI_DL_PDU_REL9_TAG, &pdu->dci_dl_pdu.dci_dl_pdu_rel9, ppWritePackedMsg, end, &pack_dl_config_dci_dl_pdu_rel9_value) && - pack_tlv(NFAPI_DL_CONFIG_REQUEST_DCI_DL_PDU_REL10_TAG, &pdu->dci_dl_pdu.dci_dl_pdu_rel10, ppWritePackedMsg, end, &pack_dl_config_dci_dl_pdu_rel10_value) && - pack_tlv(NFAPI_DL_CONFIG_REQUEST_DCI_DL_PDU_REL11_TAG, &pdu->dci_dl_pdu.dci_dl_pdu_rel11, ppWritePackedMsg, end, &pack_dl_config_dci_dl_pdu_rel11_value) && - pack_tlv(NFAPI_DL_CONFIG_REQUEST_DCI_DL_PDU_REL12_TAG, &pdu->dci_dl_pdu.dci_dl_pdu_rel12, ppWritePackedMsg, end, &pack_dl_config_dci_dl_pdu_rel12_value) && - pack_tlv(NFAPI_DL_CONFIG_REQUEST_DCI_DL_PDU_REL13_TAG, &pdu->dci_dl_pdu.dci_dl_pdu_rel13, ppWritePackedMsg, end, &pack_dl_config_dci_dl_pdu_rel13_value))) - { - return 0; - } - } - break; - case NFAPI_DL_CONFIG_BCH_PDU_TYPE: - { - //NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s() NFAPI_DL_CONFIG_BCH_PDU_TYPE\n", __FUNCTION__); - - if(!(pack_tlv(NFAPI_DL_CONFIG_REQUEST_BCH_PDU_REL8_TAG, &pdu->bch_pdu.bch_pdu_rel8, ppWritePackedMsg, end, &pack_dl_config_bch_pdu_rel8_value))) - return 0; - } - break; - case NFAPI_DL_CONFIG_MCH_PDU_TYPE: - { - if(!(pack_tlv(NFAPI_DL_CONFIG_REQUEST_MCH_PDU_REL8_TAG, &pdu->mch_pdu.mch_pdu_rel8, ppWritePackedMsg, end, &pack_dl_config_mch_pdu_rel8_value))) - return 0; - } - break; - case NFAPI_DL_CONFIG_DLSCH_PDU_TYPE: - { - if(!(pack_tlv(NFAPI_DL_CONFIG_REQUEST_DLSCH_PDU_REL8_TAG, &pdu->dlsch_pdu.dlsch_pdu_rel8, ppWritePackedMsg, end, &pack_dl_config_dlsch_pdu_rel8_value) && - pack_tlv(NFAPI_DL_CONFIG_REQUEST_DLSCH_PDU_REL9_TAG, &pdu->dlsch_pdu.dlsch_pdu_rel9, ppWritePackedMsg, end, &pack_dl_config_dlsch_pdu_rel9_value) && - pack_tlv(NFAPI_DL_CONFIG_REQUEST_DLSCH_PDU_REL10_TAG, &pdu->dlsch_pdu.dlsch_pdu_rel10, ppWritePackedMsg, end, &pack_dl_config_dlsch_pdu_rel10_value) && - pack_tlv(NFAPI_DL_CONFIG_REQUEST_DLSCH_PDU_REL11_TAG, &pdu->dlsch_pdu.dlsch_pdu_rel11, ppWritePackedMsg, end, &pack_dl_config_dlsch_pdu_rel11_value) && - pack_tlv(NFAPI_DL_CONFIG_REQUEST_DLSCH_PDU_REL12_TAG, &pdu->dlsch_pdu.dlsch_pdu_rel12, ppWritePackedMsg, end, &pack_dl_config_dlsch_pdu_rel12_value) && - pack_tlv(NFAPI_DL_CONFIG_REQUEST_DLSCH_PDU_REL13_TAG, &pdu->dlsch_pdu.dlsch_pdu_rel13, ppWritePackedMsg, end, &pack_dl_config_dlsch_pdu_rel13_value))) - return 0; - } - break; - case NFAPI_DL_CONFIG_PCH_PDU_TYPE: - { - if(!(pack_tlv(NFAPI_DL_CONFIG_REQUEST_PCH_PDU_REL8_TAG, &pdu->pch_pdu.pch_pdu_rel8, ppWritePackedMsg, end, &pack_dl_config_pch_pdu_rel8_value) && - pack_tlv(NFAPI_DL_CONFIG_REQUEST_PCH_PDU_REL13_TAG, &pdu->pch_pdu.pch_pdu_rel13, ppWritePackedMsg, end, &pack_dl_config_pch_pdu_rel13_value))) - return 0; - } - break; - case NFAPI_DL_CONFIG_PRS_PDU_TYPE: - { - if(!(pack_tlv(NFAPI_DL_CONFIG_REQUEST_PRS_PDU_REL9_TAG, &pdu->prs_pdu.prs_pdu_rel9, ppWritePackedMsg, end, &pack_dl_config_prs_pdu_rel9_value))) - return 0; - } - break; - case NFAPI_DL_CONFIG_CSI_RS_PDU_TYPE: - { - if(!(pack_tlv(NFAPI_DL_CONFIG_REQUEST_CSI_RS_PDU_REL10_TAG, &pdu->csi_rs_pdu.csi_rs_pdu_rel10, ppWritePackedMsg, end, &pack_dl_config_csi_rs_pdu_rel10_value) && - pack_tlv(NFAPI_DL_CONFIG_REQUEST_CSI_RS_PDU_REL13_TAG, &pdu->csi_rs_pdu.csi_rs_pdu_rel13, ppWritePackedMsg, end, &pack_dl_config_csi_rs_pdu_rel13_value))) - return 0; - } - break; - case NFAPI_DL_CONFIG_EPDCCH_DL_PDU_TYPE: - { - if(!(pack_tlv(NFAPI_DL_CONFIG_REQUEST_EPDCCH_PDU_REL8_TAG, &pdu->epdcch_pdu.epdcch_pdu_rel8, ppWritePackedMsg, end, &pack_dl_config_dci_dl_pdu_rel8_value) && - pack_tlv(NFAPI_DL_CONFIG_REQUEST_EPDCCH_PDU_REL9_TAG, &pdu->epdcch_pdu.epdcch_pdu_rel9, ppWritePackedMsg, end, &pack_dl_config_dci_dl_pdu_rel9_value) && - pack_tlv(NFAPI_DL_CONFIG_REQUEST_EPDCCH_PDU_REL10_TAG, &pdu->epdcch_pdu.epdcch_pdu_rel10, ppWritePackedMsg, end, &pack_dl_config_dci_dl_pdu_rel10_value) && - pack_tlv(NFAPI_DL_CONFIG_REQUEST_EPDCCH_PDU_REL11_TAG, &pdu->epdcch_pdu.epdcch_pdu_rel11, ppWritePackedMsg, end, &pack_dl_config_dci_dl_pdu_rel11_value) && - pack_tlv(NFAPI_DL_CONFIG_REQUEST_EPDCCH_PDU_REL12_TAG, &pdu->epdcch_pdu.epdcch_pdu_rel12, ppWritePackedMsg, end, &pack_dl_config_dci_dl_pdu_rel12_value) && - pack_tlv(NFAPI_DL_CONFIG_REQUEST_EPDCCH_PDU_REL13_TAG, &pdu->epdcch_pdu.epdcch_pdu_rel13, ppWritePackedMsg, end, &pack_dl_config_dci_dl_pdu_rel13_value) && - pack_tlv(NFAPI_DL_CONFIG_REQUEST_EPDCCH_PARAM_REL11_TAG, &pdu->epdcch_pdu.epdcch_params_rel11, ppWritePackedMsg, end, &pack_dl_config_epdcch_parameters_rel11_value) & - pack_tlv(NFAPI_DL_CONFIG_REQUEST_EPDCCH_PARAM_REL13_TAG, &pdu->epdcch_pdu.epdcch_params_rel13, ppWritePackedMsg, end, &pack_dl_config_epdcch_parameters_rel13_value))) - return 0; - } - break; - case NFAPI_DL_CONFIG_MPDCCH_PDU_TYPE: - { - if(!(pack_tlv(NFAPI_DL_CONFIG_REQUEST_MPDCCH_PDU_REL13_TAG, &pdu->mpdcch_pdu.mpdcch_pdu_rel13, ppWritePackedMsg, end, &pack_dl_config_mpdcch_pdu_rel13_value))) - return 0; - } - break; - case NFAPI_DL_CONFIG_NBCH_PDU_TYPE: - { - if(!(pack_tlv(NFAPI_DL_CONFIG_REQUEST_NBCH_PDU_REL13_TAG, &pdu->nbch_pdu.nbch_pdu_rel13, ppWritePackedMsg, end, &pack_dl_config_nbch_pdu_rel13_value))) - return 0; - } - break; - case NFAPI_DL_CONFIG_NPDCCH_PDU_TYPE: - { - if(!(pack_tlv(NFAPI_DL_CONFIG_REQUEST_NPDCCH_PDU_REL13_TAG, &pdu->npdcch_pdu.npdcch_pdu_rel13, ppWritePackedMsg, end, &pack_dl_config_npdcch_pdu_rel13_value))) - return 0; - } - break; - case NFAPI_DL_CONFIG_NDLSCH_PDU_TYPE: - { - if(!(pack_tlv(NFAPI_DL_CONFIG_REQUEST_NDLSCH_PDU_REL13_TAG, &pdu->ndlsch_pdu.ndlsch_pdu_rel13, ppWritePackedMsg, end, &pack_dl_config_ndlsch_pdu_rel13_value))) - return 0; - } - break; - default: - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "FIXME : Invalid pdu type %d \n", pdu->pdu_type ); - } - break; - }; - - // add 1 for the pdu_type. The delta will include the pdu_size - pdu->pdu_size = 1 + (*ppWritePackedMsg - pWritePackedMsgPduSize); - push8(pdu->pdu_size, &pWritePackedMsgPduSize, end); - } - - return 1; -} - - -static uint8_t pack_dl_tti_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) -{ - nfapi_nr_dl_tti_request_t *pNfapiMsg = (nfapi_nr_dl_tti_request_t*)msg; - - if (!(push16(pNfapiMsg->SFN , ppWritePackedMsg, end) && - push16(pNfapiMsg->Slot , ppWritePackedMsg, end) && - push8(pNfapiMsg->dl_tti_request_body.nGroup , ppWritePackedMsg, end) && - push8(pNfapiMsg->dl_tti_request_body.nPDUs , ppWritePackedMsg, end) && - pusharray8(pNfapiMsg->dl_tti_request_body.nUe ,256,pNfapiMsg->dl_tti_request_body.nGroup, ppWritePackedMsg, end) - //pusharray8(pNfapiMsg->PduIdx[0] ,256,256, ppWritePackedMsg, end) - )) - return 0; - - int arr[12]; - for(int i=0;idl_tti_request_body.nGroup;i++) - { - for(int j=0;jdl_tti_request_body.nUe[i];j++) - { - arr[j] = pNfapiMsg->dl_tti_request_body.PduIdx[i][j]; - } - if(!(pusharrays32(arr,12,pNfapiMsg->dl_tti_request_body.nUe[i],ppWritePackedMsg, end))) - return 0; - } - - for(int i=0;idl_tti_request_body.nPDUs;i++) - { - if(!pack_dl_tti_request_body_value(&pNfapiMsg->dl_tti_request_body.dl_tti_pdu_list[i],ppWritePackedMsg,end)) - return 0; - } - -return 1; -} - - -static uint8_t pack_dl_config_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) -{ - nfapi_dl_config_request_t *pNfapiMsg = (nfapi_dl_config_request_t*)msg; - - //return ( push16(pNfapiMsg->sfn_sf, ppWritePackedMsg, end) && - //pack_tlv(NFAPI_DL_CONFIG_REQUEST_BODY_TAG, &pNfapiMsg->dl_config_request_body, ppWritePackedMsg, end, &pack_dl_config_request_body_value) && - //pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); - { - uint8_t x = push16(pNfapiMsg->sfn_sf, ppWritePackedMsg, end); - uint8_t y = pack_tlv(NFAPI_DL_CONFIG_REQUEST_BODY_TAG, &pNfapiMsg->dl_config_request_body, ppWritePackedMsg, end, &pack_dl_config_request_body_value); - uint8_t z = pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config); - - if (!x || !y || !z) - { - NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() NFAPI_DL_CONFIG_REQUEST x:%u y:%u z:%u \n", __FUNCTION__,x,y,z); - } - - return x && y && z; - } -} - - - - -static uint8_t pack_ul_config_request_ulsch_rel8_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t * end) -{ - nfapi_ul_config_ulsch_pdu_rel8_t* ulsch_pdu_rel8 = (nfapi_ul_config_ulsch_pdu_rel8_t*)tlv; - - return( push32(ulsch_pdu_rel8->handle, ppWritePackedMsg, end) && - push16(ulsch_pdu_rel8->size, ppWritePackedMsg, end) && - push16(ulsch_pdu_rel8->rnti, ppWritePackedMsg, end) && - push8(ulsch_pdu_rel8->resource_block_start, ppWritePackedMsg, end) && - push8(ulsch_pdu_rel8->number_of_resource_blocks, ppWritePackedMsg, end) && - push8(ulsch_pdu_rel8->modulation_type, ppWritePackedMsg, end) && - push8(ulsch_pdu_rel8->cyclic_shift_2_for_drms, ppWritePackedMsg, end) && - push8(ulsch_pdu_rel8->frequency_hopping_enabled_flag, ppWritePackedMsg, end) && - push8(ulsch_pdu_rel8->frequency_hopping_bits, ppWritePackedMsg, end) && - push8(ulsch_pdu_rel8->new_data_indication, ppWritePackedMsg, end) && - push8(ulsch_pdu_rel8->redundancy_version, ppWritePackedMsg, end) && - push8(ulsch_pdu_rel8->harq_process_number, ppWritePackedMsg, end) && - push8(ulsch_pdu_rel8->ul_tx_mode, ppWritePackedMsg, end) && - push8(ulsch_pdu_rel8->current_tx_nb, ppWritePackedMsg, end) && - push8(ulsch_pdu_rel8->n_srs, ppWritePackedMsg, end)); -} -static uint8_t pack_ul_config_request_ulsch_rel10_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_ul_config_ulsch_pdu_rel10_t* ulsch_pdu_rel10 = (nfapi_ul_config_ulsch_pdu_rel10_t*)tlv; - - return (push8(ulsch_pdu_rel10->resource_allocation_type, ppWritePackedMsg, end) && - push32(ulsch_pdu_rel10->resource_block_coding, ppWritePackedMsg, end) && - push8(ulsch_pdu_rel10->transport_blocks, ppWritePackedMsg, end) && - push8(ulsch_pdu_rel10->transmission_scheme, ppWritePackedMsg, end) && - push8(ulsch_pdu_rel10->number_of_layers, ppWritePackedMsg, end) && - push8(ulsch_pdu_rel10->codebook_index, ppWritePackedMsg, end) && - push8(ulsch_pdu_rel10->disable_sequence_hopping_flag, ppWritePackedMsg, end)); -} - -static uint8_t pack_ul_config_request_ulsch_rel11_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_ul_config_ulsch_pdu_rel11_t* ulsch_pdu_rel11 = (nfapi_ul_config_ulsch_pdu_rel11_t*)tlv; - - return (push8(ulsch_pdu_rel11->virtual_cell_id_enabled_flag, ppWritePackedMsg, end) && - push16(ulsch_pdu_rel11->npusch_identity, ppWritePackedMsg, end) && - push8(ulsch_pdu_rel11->dmrs_config_flag, ppWritePackedMsg, end) && - push16(ulsch_pdu_rel11->ndmrs_csh_identity, ppWritePackedMsg, end)); -} - -static uint8_t pack_ul_config_request_ulsch_rel13_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_ul_config_ulsch_pdu_rel13_t* ulsch_pdu_rel13 = (nfapi_ul_config_ulsch_pdu_rel13_t*)tlv; - - return (push8(ulsch_pdu_rel13->ue_type, ppWritePackedMsg, end) && - push16(ulsch_pdu_rel13->total_number_of_repetitions, ppWritePackedMsg, end) && - push16(ulsch_pdu_rel13->repetition_number, ppWritePackedMsg, end) && - push16(ulsch_pdu_rel13->initial_transmission_sf_io, ppWritePackedMsg, end) && - push8(ulsch_pdu_rel13->empty_symbols_due_to_re_tunning, ppWritePackedMsg, end)); -} - -//Pack fns for ul_tti PDUS - - -static uint8_t pack_ul_tti_request_prach_pdu(nfapi_nr_prach_pdu_t* prach_pdu, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - return( - push16(prach_pdu->phys_cell_id, ppWritePackedMsg, end) && - push8(prach_pdu->num_prach_ocas, ppWritePackedMsg, end) && - push8(prach_pdu->prach_format, ppWritePackedMsg, end) && - push8(prach_pdu->num_ra, ppWritePackedMsg, end) && - push8(prach_pdu->prach_start_symbol, ppWritePackedMsg, end) && - push16(prach_pdu->num_cs, ppWritePackedMsg, end) - // TODO: ignoring beamforming tlv for now - ); - -} - -static uint8_t pack_ul_tti_request_pucch_pdu(nfapi_nr_pucch_pdu_t* pucch_pdu, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - return( - push16(pucch_pdu->rnti, ppWritePackedMsg, end) && - push32(pucch_pdu->handle, ppWritePackedMsg, end) && - push16(pucch_pdu->bwp_size, ppWritePackedMsg, end) && - push16(pucch_pdu->bwp_start, ppWritePackedMsg, end) && - push8(pucch_pdu->subcarrier_spacing, ppWritePackedMsg, end) && - push8(pucch_pdu->cyclic_prefix, ppWritePackedMsg, end) && - push8(pucch_pdu->format_type, ppWritePackedMsg, end) && - push8(pucch_pdu->multi_slot_tx_indicator, ppWritePackedMsg, end) && - push16(pucch_pdu->prb_start, ppWritePackedMsg, end) && - push16(pucch_pdu->prb_size, ppWritePackedMsg, end) && - push8(pucch_pdu->start_symbol_index, ppWritePackedMsg, end) && - push8(pucch_pdu->nr_of_symbols, ppWritePackedMsg, end) && - push8(pucch_pdu->freq_hop_flag, ppWritePackedMsg, end) && - push16(pucch_pdu->second_hop_prb, ppWritePackedMsg, end) && - push8(pucch_pdu->group_hop_flag, ppWritePackedMsg, end) && - push8(pucch_pdu->sequence_hop_flag, ppWritePackedMsg, end) && - push16(pucch_pdu->hopping_id, ppWritePackedMsg, end) && - push16(pucch_pdu->initial_cyclic_shift, ppWritePackedMsg, end) && - push16(pucch_pdu->data_scrambling_id, ppWritePackedMsg, end) && - push8(pucch_pdu->time_domain_occ_idx, ppWritePackedMsg, end) && - push8(pucch_pdu->pre_dft_occ_idx, ppWritePackedMsg, end) && - push8(pucch_pdu->pre_dft_occ_len, ppWritePackedMsg, end) && - push8(pucch_pdu->add_dmrs_flag, ppWritePackedMsg, end) && - push16(pucch_pdu->dmrs_scrambling_id, ppWritePackedMsg, end) && - push8(pucch_pdu->dmrs_cyclic_shift, ppWritePackedMsg, end) && - push8(pucch_pdu->sr_flag, ppWritePackedMsg, end) && - push8(pucch_pdu->bit_len_harq, ppWritePackedMsg, end) && - push16(pucch_pdu->bit_len_csi_part1, ppWritePackedMsg, end) && - push16(pucch_pdu->bit_len_csi_part2, ppWritePackedMsg, end) - // TODO: ignoring beamforming tlv for now - ); - -} - - -static uint8_t pack_ul_tti_request_pusch_pdu(nfapi_nr_pusch_pdu_t* pusch_pdu, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - - if (!( - push16(pusch_pdu->pdu_bit_map, ppWritePackedMsg, end) && - push16(pusch_pdu->rnti, ppWritePackedMsg, end) && - push32(pusch_pdu->handle, ppWritePackedMsg, end) && - push16(pusch_pdu->bwp_size, ppWritePackedMsg, end) && - push16(pusch_pdu->bwp_start, ppWritePackedMsg, end) && - push8(pusch_pdu->subcarrier_spacing, ppWritePackedMsg, end) && - push8(pusch_pdu->cyclic_prefix, ppWritePackedMsg, end) && - push16(pusch_pdu->target_code_rate, ppWritePackedMsg, end) && - push8(pusch_pdu->qam_mod_order, ppWritePackedMsg, end) && - push8(pusch_pdu->mcs_index, ppWritePackedMsg, end) && - push8(pusch_pdu->mcs_table, ppWritePackedMsg, end) && - push8(pusch_pdu->transform_precoding, ppWritePackedMsg, end) && - push16(pusch_pdu->data_scrambling_id, ppWritePackedMsg, end) && - push8(pusch_pdu->nrOfLayers, ppWritePackedMsg, end) && - push16(pusch_pdu->ul_dmrs_symb_pos, ppWritePackedMsg, end) && - push8(pusch_pdu->dmrs_config_type, ppWritePackedMsg, end) && - push16(pusch_pdu->ul_dmrs_scrambling_id, ppWritePackedMsg, end) && - push8(pusch_pdu->scid, ppWritePackedMsg, end) && - push8(pusch_pdu->num_dmrs_cdm_grps_no_data, ppWritePackedMsg, end) && - push16(pusch_pdu->dmrs_ports, ppWritePackedMsg, end) && - push8(pusch_pdu->resource_alloc, ppWritePackedMsg, end) && - push8(pusch_pdu->resource_alloc,ppWritePackedMsg, end) && - push16(pusch_pdu->dmrs_ports, ppWritePackedMsg, end) && - push16(pusch_pdu->rb_start, ppWritePackedMsg, end) && - push16(pusch_pdu->rb_size, ppWritePackedMsg, end) && - push8(pusch_pdu->vrb_to_prb_mapping, ppWritePackedMsg, end) && - push8(pusch_pdu->frequency_hopping, ppWritePackedMsg, end) && - push16(pusch_pdu->tx_direct_current_location, ppWritePackedMsg, end) && - push8(pusch_pdu->uplink_frequency_shift_7p5khz, ppWritePackedMsg, end) && - push8(pusch_pdu->start_symbol_index, ppWritePackedMsg, end) && - push8(pusch_pdu->nr_of_symbols, ppWritePackedMsg, end) - // TODO: ignoring beamforming tlv for now - )) - return 0; - - - //Pack Optional Data only included if indicated in pduBitmap - switch(pusch_pdu->pdu_bit_map){ - case PUSCH_PDU_BITMAP_PUSCH_DATA: - { - // pack optional TLVs - return( - push8(pusch_pdu->pusch_data.rv_index, ppWritePackedMsg, end) && - push8(pusch_pdu->pusch_data.harq_process_id, ppWritePackedMsg, end) && - push32(pusch_pdu->pusch_data.tb_size, ppWritePackedMsg, end) && - push16(pusch_pdu->pusch_data.num_cb, ppWritePackedMsg, end) && - pusharray8(pusch_pdu->pusch_data.cb_present_and_position,1,1,ppWritePackedMsg, end) - ); - } - break; - - case PUSCH_PDU_BITMAP_PUSCH_UCI: - { - return( - push16(pusch_pdu->pusch_uci.harq_ack_bit_length, ppWritePackedMsg, end) && - push16(pusch_pdu->pusch_uci.csi_part1_bit_length, ppWritePackedMsg, end) && - push16(pusch_pdu->pusch_uci.csi_part2_bit_length, ppWritePackedMsg, end) && - push8(pusch_pdu->pusch_uci.alpha_scaling, ppWritePackedMsg, end) && - push8(pusch_pdu->pusch_uci.beta_offset_harq_ack, ppWritePackedMsg, end) && - push8(pusch_pdu->pusch_uci.beta_offset_csi1, ppWritePackedMsg, end) && - push8(pusch_pdu->pusch_uci.beta_offset_csi2, ppWritePackedMsg, end) - ); - } - break; - - case PUSCH_PDU_BITMAP_PUSCH_PTRS: - { - return( - push8(pusch_pdu->pusch_ptrs.num_ptrs_ports, ppWritePackedMsg, end) && - push8(pusch_pdu->pusch_ptrs.ptrs_ports_list->ptrs_dmrs_port, ppWritePackedMsg, end) && - push16(pusch_pdu->pusch_ptrs.ptrs_ports_list->ptrs_port_index, ppWritePackedMsg, end) && - push8(pusch_pdu->pusch_ptrs.ptrs_ports_list->ptrs_re_offset, ppWritePackedMsg, end) && - push8(pusch_pdu->pusch_ptrs.ptrs_time_density, ppWritePackedMsg, end) && - push8(pusch_pdu->pusch_ptrs.ptrs_freq_density, ppWritePackedMsg, end) && - push8(pusch_pdu->pusch_ptrs.ul_ptrs_power, ppWritePackedMsg, end) - ); - } - break; - - case PUSCH_PDU_BITMAP_DFTS_OFDM: - { - return( - push8(pusch_pdu->dfts_ofdm.low_papr_group_number, ppWritePackedMsg, end) && - push16(pusch_pdu->dfts_ofdm.low_papr_sequence_number, ppWritePackedMsg, end) && - push8(pusch_pdu->dfts_ofdm.ul_ptrs_sample_density, ppWritePackedMsg, end) && - push8(pusch_pdu->dfts_ofdm.ul_ptrs_time_density_transform_precoding, ppWritePackedMsg, end) - ); - } - break; - - default: - { - NFAPI_TRACE(NFAPI_TRACE_INFO, "Invalid pdu bitmap %d \n", pusch_pdu->pdu_bit_map ); - } - } - - return 1; -} - -static uint8_t pack_ul_tti_request_srs_pdu(nfapi_nr_srs_pdu_t* srs_pdu, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - return( - push16(srs_pdu->rnti, ppWritePackedMsg, end) && - push32(srs_pdu->handle, ppWritePackedMsg, end) && - push16(srs_pdu->bwp_size, ppWritePackedMsg, end) && - push16(srs_pdu->bwp_start, ppWritePackedMsg, end) && - push8(srs_pdu->subcarrier_spacing, ppWritePackedMsg, end) && - push8(srs_pdu->cyclic_prefix, ppWritePackedMsg, end) && - push8(srs_pdu->num_ant_ports, ppWritePackedMsg, end) && - push8(srs_pdu->num_symbols, ppWritePackedMsg, end) && - push8(srs_pdu->num_repetitions, ppWritePackedMsg, end) && - push8(srs_pdu->time_start_position, ppWritePackedMsg, end) && - push8(srs_pdu->config_index, ppWritePackedMsg, end) && - push16(srs_pdu->sequence_id, ppWritePackedMsg, end) && - push8(srs_pdu->bandwidth_index, ppWritePackedMsg, end) && - push8(srs_pdu->comb_size, ppWritePackedMsg, end) && - push8(srs_pdu->comb_offset, ppWritePackedMsg, end) && - push8(srs_pdu->cyclic_shift, ppWritePackedMsg, end) && - push8(srs_pdu->frequency_position, ppWritePackedMsg, end) && - push8(srs_pdu->frequency_shift, ppWritePackedMsg, end) && - push8(srs_pdu->frequency_hopping, ppWritePackedMsg, end) && - push8(srs_pdu->group_or_sequence_hopping, ppWritePackedMsg, end) && - push8(srs_pdu->resource_type, ppWritePackedMsg, end) && - push16(srs_pdu->t_srs, ppWritePackedMsg, end) && - push16(srs_pdu->t_offset, ppWritePackedMsg, end) - - // TODO: ignoring beamforming tlv for now - ); - -} - -static uint8_t pack_ul_config_request_ulsch_pdu(nfapi_ul_config_ulsch_pdu* ulsch_pdu, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - return ( pack_tlv(NFAPI_UL_CONFIG_REQUEST_ULSCH_PDU_REL8_TAG, &ulsch_pdu->ulsch_pdu_rel8, ppWritePackedMsg, end, &pack_ul_config_request_ulsch_rel8_value) && - pack_tlv(NFAPI_UL_CONFIG_REQUEST_ULSCH_PDU_REL10_TAG, &ulsch_pdu->ulsch_pdu_rel10, ppWritePackedMsg, end, &pack_ul_config_request_ulsch_rel10_value) && - pack_tlv(NFAPI_UL_CONFIG_REQUEST_ULSCH_PDU_REL11_TAG, &ulsch_pdu->ulsch_pdu_rel11, ppWritePackedMsg, end, &pack_ul_config_request_ulsch_rel11_value) && - pack_tlv(NFAPI_UL_CONFIG_REQUEST_ULSCH_PDU_REL13_TAG, &ulsch_pdu->ulsch_pdu_rel13, ppWritePackedMsg, end, &pack_ul_config_request_ulsch_rel13_value)); -} - -static uint8_t pack_ul_config_request_cqi_ri_rel8_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_ul_config_cqi_ri_information_rel8_t* cqi_ri_info_rel8 = (nfapi_ul_config_cqi_ri_information_rel8_t*)tlv; - - return ( push8(cqi_ri_info_rel8->dl_cqi_pmi_size_rank_1, ppWritePackedMsg, end) && - push8(cqi_ri_info_rel8->dl_cqi_pmi_size_rank_greater_1, ppWritePackedMsg, end) && - push8(cqi_ri_info_rel8->ri_size, ppWritePackedMsg, end) && - push8(cqi_ri_info_rel8->delta_offset_cqi, ppWritePackedMsg, end) && - push8(cqi_ri_info_rel8->delta_offset_ri, ppWritePackedMsg, end)); -} - -static uint8_t pack_ul_config_request_cqi_ri_rel9_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_ul_config_cqi_ri_information_rel9_t* cqi_ri_info_rel9 = (nfapi_ul_config_cqi_ri_information_rel9_t*)tlv; - - if(!(push8(cqi_ri_info_rel9->report_type, ppWritePackedMsg, end) && - push8(cqi_ri_info_rel9->delta_offset_cqi, ppWritePackedMsg, end) && - push8(cqi_ri_info_rel9->delta_offset_ri, ppWritePackedMsg, end))) - { - return 0; - } - - switch(cqi_ri_info_rel9->report_type) - { - case NFAPI_CSI_REPORT_TYPE_PERIODIC: - { - if(!(push8(cqi_ri_info_rel9->periodic_cqi_pmi_ri_report.dl_cqi_pmi_ri_size, ppWritePackedMsg, end) && - push8(cqi_ri_info_rel9->periodic_cqi_pmi_ri_report.control_type, ppWritePackedMsg, end))) - { - return 0; - } - } - break; - case NFAPI_CSI_REPORT_TYPE_APERIODIC: - { - if(push8(cqi_ri_info_rel9->aperiodic_cqi_pmi_ri_report.number_of_cc, ppWritePackedMsg, end) == 0) - return 0; - - uint8_t i; - for(i = 0; i < cqi_ri_info_rel9->aperiodic_cqi_pmi_ri_report.number_of_cc; ++i) - { - if(push8(cqi_ri_info_rel9->aperiodic_cqi_pmi_ri_report.cc[i].ri_size, ppWritePackedMsg, end) == 0) - return 0; - - uint8_t j; - for(j = 0; j < 8; ++j) - { - if(push8(cqi_ri_info_rel9->aperiodic_cqi_pmi_ri_report.cc[i].dl_cqi_pmi_size[j], ppWritePackedMsg, end) == 0) - return 0; - } - } - } - break; - default: - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "FIXME : Invalid report type %d \n", cqi_ri_info_rel9->report_type ); - } - break; - }; - - return 1; -} - -static uint8_t pack_ul_config_request_cqi_ri_rel13_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_ul_config_cqi_ri_information_rel13_t* cqi_ri_info_rel13 = (nfapi_ul_config_cqi_ri_information_rel13_t*)tlv; - - switch(cqi_ri_info_rel13->report_type) - { - case NFAPI_CSI_REPORT_TYPE_PERIODIC: - { - if(push16(cqi_ri_info_rel13->periodic_cqi_pmi_ri_report.dl_cqi_pmi_ri_size_2, ppWritePackedMsg, end) == 0) - return 0; - } - break; - case NFAPI_CSI_REPORT_TYPE_APERIODIC: - { - // No parameters - } - break; - default: - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "FIXME : Invalid report type %d \n", cqi_ri_info_rel13->report_type ); - } - break; - }; - - return 1; -} - -static uint8_t pack_ul_config_request_cqi_ri_information(nfapi_ul_config_cqi_ri_information* cqi_ri_info, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - return (pack_tlv(NFAPI_UL_CONFIG_REQUEST_CQI_RI_INFORMATION_REL8_TAG, &cqi_ri_info->cqi_ri_information_rel8, ppWritePackedMsg, end, &pack_ul_config_request_cqi_ri_rel8_value) && - pack_tlv(NFAPI_UL_CONFIG_REQUEST_CQI_RI_INFORMATION_REL9_TAG, &cqi_ri_info->cqi_ri_information_rel9, ppWritePackedMsg, end, &pack_ul_config_request_cqi_ri_rel9_value) && - pack_tlv(NFAPI_UL_CONFIG_REQUEST_CQI_RI_INFORMATION_REL13_TAG, &cqi_ri_info->cqi_ri_information_rel13, ppWritePackedMsg, end, &pack_ul_config_request_cqi_ri_rel13_value)); - -} - -static uint8_t pack_ul_config_request_init_tx_params_rel8_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_ul_config_initial_transmission_parameters_rel8_t* init_tx_params_rel8 = (nfapi_ul_config_initial_transmission_parameters_rel8_t*)tlv; - - return (push8(init_tx_params_rel8->n_srs_initial, ppWritePackedMsg, end) && - push8(init_tx_params_rel8->initial_number_of_resource_blocks, ppWritePackedMsg, end)); -} - -static uint8_t pack_ul_config_request_initial_transmission_parameters(nfapi_ul_config_initial_transmission_parameters* init_tx_params, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - return pack_tlv(NFAPI_UL_CONFIG_REQUEST_INITIAL_TRANSMISSION_PARAMETERS_REL8_TAG, &init_tx_params->initial_transmission_parameters_rel8, ppWritePackedMsg, end, &pack_ul_config_request_init_tx_params_rel8_value); -} - -static uint8_t pack_ul_config_request_ulsch_harq_info_rel10_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_ul_config_ulsch_harq_information_rel10_t* harq_info_rel10 = (nfapi_ul_config_ulsch_harq_information_rel10_t*)tlv; - - return (push8(harq_info_rel10->harq_size, ppWritePackedMsg, end) && - push8(harq_info_rel10->delta_offset_harq, ppWritePackedMsg, end) && - push8(harq_info_rel10->ack_nack_mode, ppWritePackedMsg, end)); -} -static uint8_t pack_ul_config_request_ulsch_harq_info_rel13_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_ul_config_ulsch_harq_information_rel13_t* harq_info_rel13 = (nfapi_ul_config_ulsch_harq_information_rel13_t*)tlv; - - return (push16(harq_info_rel13->harq_size_2, ppWritePackedMsg, end) && - push8(harq_info_rel13->delta_offset_harq_2, ppWritePackedMsg, end)); -} - -static uint8_t pack_ul_config_request_ulsch_harq_information(nfapi_ul_config_ulsch_harq_information* harq_info, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - return ( pack_tlv(NFAPI_UL_CONFIG_REQUEST_ULSCH_HARQ_INFORMATION_REL10_TAG, &harq_info->harq_information_rel10, ppWritePackedMsg, end, &pack_ul_config_request_ulsch_harq_info_rel10_value) && - pack_tlv(NFAPI_UL_CONFIG_REQUEST_ULSCH_HARQ_INFORMATION_REL13_TAG, &harq_info->harq_information_rel13, ppWritePackedMsg, end, &pack_ul_config_request_ulsch_harq_info_rel13_value)); -} - -static uint8_t pack_ul_config_request_ue_info_rel8_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_ul_config_ue_information_rel8_t* ue_info_rel8 = (nfapi_ul_config_ue_information_rel8_t*)tlv; - - return ( push32(ue_info_rel8->handle, ppWritePackedMsg, end) && - push16(ue_info_rel8->rnti, ppWritePackedMsg, end)); -} -static uint8_t pack_ul_config_request_ue_info_rel11_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_ul_config_ue_information_rel11_t* ue_info_rel11 = (nfapi_ul_config_ue_information_rel11_t*)tlv; - - return ( push8(ue_info_rel11->virtual_cell_id_enabled_flag, ppWritePackedMsg, end) && - push16(ue_info_rel11->npusch_identity, ppWritePackedMsg, end)); -} -static uint8_t pack_ul_config_request_ue_info_rel13_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_ul_config_ue_information_rel13_t* ue_info_rel13 = (nfapi_ul_config_ue_information_rel13_t*)tlv; - - return ( push8(ue_info_rel13->ue_type, ppWritePackedMsg, end) && - push8(ue_info_rel13->empty_symbols, ppWritePackedMsg, end) && - push16(ue_info_rel13->total_number_of_repetitions, ppWritePackedMsg, end) && - push16(ue_info_rel13->repetition_number, ppWritePackedMsg, end)); -} - -static uint8_t pack_ul_config_request_ue_information(nfapi_ul_config_ue_information* ue_info, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - return ( pack_tlv(NFAPI_UL_CONFIG_REQUEST_UE_INFORMATION_REL8_TAG, &ue_info->ue_information_rel8, ppWritePackedMsg, end, &pack_ul_config_request_ue_info_rel8_value) && - pack_tlv(NFAPI_UL_CONFIG_REQUEST_UE_INFORMATION_REL11_TAG, &ue_info->ue_information_rel11, ppWritePackedMsg, end, &pack_ul_config_request_ue_info_rel11_value) && - pack_tlv(NFAPI_UL_CONFIG_REQUEST_UE_INFORMATION_REL13_TAG, &ue_info->ue_information_rel13, ppWritePackedMsg, end, &pack_ul_config_request_ue_info_rel13_value)); -} - -static uint8_t pack_ul_config_request_harq_info_rel10_tdd_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_ul_config_harq_information_rel10_tdd_t* harq_info_rel10_tdd = (nfapi_ul_config_harq_information_rel10_tdd_t*)tlv; - - return ( push8(harq_info_rel10_tdd->harq_size, ppWritePackedMsg, end) && - push8(harq_info_rel10_tdd->ack_nack_mode, ppWritePackedMsg, end) && - push8(harq_info_rel10_tdd->number_of_pucch_resources, ppWritePackedMsg, end) && - push16(harq_info_rel10_tdd->n_pucch_1_0, ppWritePackedMsg, end) && - push16(harq_info_rel10_tdd->n_pucch_1_1, ppWritePackedMsg, end) && - push16(harq_info_rel10_tdd->n_pucch_1_2, ppWritePackedMsg, end) && - push16(harq_info_rel10_tdd->n_pucch_1_3, ppWritePackedMsg, end)); -} -static uint8_t pack_ul_config_request_harq_info_rel8_fdd_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_ul_config_harq_information_rel8_fdd_t* harq_info_rel8_fdd = (nfapi_ul_config_harq_information_rel8_fdd_t*)tlv; - - return ( push16(harq_info_rel8_fdd->n_pucch_1_0, ppWritePackedMsg, end) && - push8(harq_info_rel8_fdd->harq_size, ppWritePackedMsg, end)); -} -static uint8_t pack_ul_config_request_harq_info_rel9_fdd_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_ul_config_harq_information_rel9_fdd_t* harq_info_rel9_fdd = (nfapi_ul_config_harq_information_rel9_fdd_t*)tlv; - - return ( push8(harq_info_rel9_fdd->harq_size, ppWritePackedMsg, end) && - push8(harq_info_rel9_fdd->ack_nack_mode, ppWritePackedMsg, end) && - push8(harq_info_rel9_fdd->number_of_pucch_resources, ppWritePackedMsg, end) && - push16(harq_info_rel9_fdd->n_pucch_1_0, ppWritePackedMsg, end) && - push16(harq_info_rel9_fdd->n_pucch_1_1, ppWritePackedMsg, end) && - push16(harq_info_rel9_fdd->n_pucch_1_2, ppWritePackedMsg, end) && - push16(harq_info_rel9_fdd->n_pucch_1_3, ppWritePackedMsg, end)); -} -static uint8_t pack_ul_config_request_harq_info_rel11_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_ul_config_harq_information_rel11_t* harq_info_rel11 = (nfapi_ul_config_harq_information_rel11_t*)tlv; - - return ( push8(harq_info_rel11->num_ant_ports, ppWritePackedMsg, end) && - push16(harq_info_rel11->n_pucch_2_0, ppWritePackedMsg, end) && - push16(harq_info_rel11->n_pucch_2_1, ppWritePackedMsg, end) && - push16(harq_info_rel11->n_pucch_2_2, ppWritePackedMsg, end) && - push16(harq_info_rel11->n_pucch_2_3, ppWritePackedMsg, end)); -} -static uint8_t pack_ul_config_request_harq_info_rel13_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_ul_config_harq_information_rel13_t* harq_info_rel13 = (nfapi_ul_config_harq_information_rel13_t*)tlv; - - return ( push16(harq_info_rel13->harq_size_2, ppWritePackedMsg, end) && - push8(harq_info_rel13->starting_prb, ppWritePackedMsg, end) && - push8(harq_info_rel13->n_prb, ppWritePackedMsg, end) && - push8(harq_info_rel13->cdm_index, ppWritePackedMsg, end) && - push8(harq_info_rel13->n_srs, ppWritePackedMsg, end)); -} - -static uint8_t pack_ul_config_request_harq_information(nfapi_ul_config_harq_information* harq_info, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - return ( pack_tlv(NFAPI_UL_CONFIG_REQUEST_HARQ_INFORMATION_REL10_TDD_TAG, &harq_info->harq_information_rel10_tdd, ppWritePackedMsg, end, &pack_ul_config_request_harq_info_rel10_tdd_value) && - pack_tlv(NFAPI_UL_CONFIG_REQUEST_HARQ_INFORMATION_REL8_FDD_TAG, &harq_info->harq_information_rel8_fdd, ppWritePackedMsg, end, &pack_ul_config_request_harq_info_rel8_fdd_value) && - pack_tlv(NFAPI_UL_CONFIG_REQUEST_HARQ_INFORMATION_REL9_FDD_TAG, &harq_info->harq_information_rel9_fdd, ppWritePackedMsg, end, &pack_ul_config_request_harq_info_rel9_fdd_value) && - pack_tlv(NFAPI_UL_CONFIG_REQUEST_HARQ_INFORMATION_REL11_TAG, &harq_info->harq_information_rel11, ppWritePackedMsg, end, &pack_ul_config_request_harq_info_rel11_value) && - pack_tlv(NFAPI_UL_CONFIG_REQUEST_HARQ_INFORMATION_REL13_TAG, &harq_info->harq_information_rel13, ppWritePackedMsg, end, &pack_ul_config_request_harq_info_rel13_value)); - -} - -static uint8_t pack_ul_config_request_cqi_info_rel8_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_ul_config_cqi_information_rel8_t* cqi_info_rel8 = (nfapi_ul_config_cqi_information_rel8_t*)tlv; - - return ( push16(cqi_info_rel8->pucch_index, ppWritePackedMsg, end) && - push8(cqi_info_rel8->dl_cqi_pmi_size, ppWritePackedMsg, end)); -} -static uint8_t pack_ul_config_request_cqi_info_rel10_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_ul_config_cqi_information_rel10_t* cqi_info_rel10 = (nfapi_ul_config_cqi_information_rel10_t*)tlv; - - return ( push8(cqi_info_rel10->number_of_pucch_resource, ppWritePackedMsg, end) && - push16(cqi_info_rel10->pucch_index_p1, ppWritePackedMsg, end)); -} -static uint8_t pack_ul_config_request_cqi_info_rel13_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_ul_config_cqi_information_rel13_t* cqi_info_rel13 = (nfapi_ul_config_cqi_information_rel13_t*)tlv; - - return ( push8(cqi_info_rel13->csi_mode, ppWritePackedMsg, end) && - push16(cqi_info_rel13->dl_cqi_pmi_size_2, ppWritePackedMsg, end) && - push8(cqi_info_rel13->starting_prb, ppWritePackedMsg, end) && - push8(cqi_info_rel13->n_prb, ppWritePackedMsg, end) && - push8(cqi_info_rel13->cdm_index, ppWritePackedMsg, end) && - push8(cqi_info_rel13->n_srs, ppWritePackedMsg, end)); -} - -static uint8_t pack_ul_config_request_cqi_information(nfapi_ul_config_cqi_information* cqi_info, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - return ( pack_tlv(NFAPI_UL_CONFIG_REQUEST_CQI_INFORMATION_REL8_TAG, &cqi_info->cqi_information_rel8, ppWritePackedMsg, end, &pack_ul_config_request_cqi_info_rel8_value) && - pack_tlv(NFAPI_UL_CONFIG_REQUEST_CQI_INFORMATION_REL10_TAG, &cqi_info->cqi_information_rel10, ppWritePackedMsg, end, &pack_ul_config_request_cqi_info_rel10_value) && - pack_tlv(NFAPI_UL_CONFIG_REQUEST_CQI_INFORMATION_REL13_TAG, &cqi_info->cqi_information_rel13, ppWritePackedMsg, end, &pack_ul_config_request_cqi_info_rel13_value)); - -} - -static uint8_t pack_ul_config_request_sr_info_rel8_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_ul_config_sr_information_rel8_t* sr_info_rel8 = (nfapi_ul_config_sr_information_rel8_t*)tlv; - return push16(sr_info_rel8->pucch_index, ppWritePackedMsg, end); -} -static uint8_t pack_ul_config_request_sr_info_rel10_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_ul_config_sr_information_rel10_t* sr_info_rel10 = (nfapi_ul_config_sr_information_rel10_t*)tlv; - - return ( push8(sr_info_rel10->number_of_pucch_resources, ppWritePackedMsg, end) && - push16(sr_info_rel10->pucch_index_p1, ppWritePackedMsg, end)); -} - -static uint8_t pack_ul_config_request_sr_information(nfapi_ul_config_sr_information* sr_info, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - return ( pack_tlv(NFAPI_UL_CONFIG_REQUEST_SR_INFORMATION_REL8_TAG, &sr_info->sr_information_rel8, ppWritePackedMsg, end, &pack_ul_config_request_sr_info_rel8_value) && - pack_tlv(NFAPI_UL_CONFIG_REQUEST_SR_INFORMATION_REL10_TAG, &sr_info->sr_information_rel10, ppWritePackedMsg, end, &pack_ul_config_request_sr_info_rel10_value)); -} - -static uint8_t pack_ul_config_request_srs_pdu_rel8_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_ul_config_srs_pdu_rel8_t* srs_pdu_rel8 = (nfapi_ul_config_srs_pdu_rel8_t*)tlv; - - return (push32(srs_pdu_rel8->handle, ppWritePackedMsg, end) && - push16(srs_pdu_rel8->size, ppWritePackedMsg, end) && - push16(srs_pdu_rel8->rnti, ppWritePackedMsg, end) && - push8(srs_pdu_rel8->srs_bandwidth, ppWritePackedMsg, end) && - push8(srs_pdu_rel8->frequency_domain_position, ppWritePackedMsg, end) && - push8(srs_pdu_rel8->srs_hopping_bandwidth, ppWritePackedMsg, end) && - push8(srs_pdu_rel8->transmission_comb, ppWritePackedMsg, end) && - push16(srs_pdu_rel8->i_srs, ppWritePackedMsg, end) && - push8(srs_pdu_rel8->sounding_reference_cyclic_shift, ppWritePackedMsg, end)); -} - -static uint8_t pack_ul_config_request_srs_pdu_rel10_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_ul_config_srs_pdu_rel10_t* srs_pdu_rel10 = (nfapi_ul_config_srs_pdu_rel10_t*)tlv; - return push8(srs_pdu_rel10->antenna_port, ppWritePackedMsg, end); -} - -static uint8_t pack_ul_config_request_srs_pdu_rel13_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_ul_config_srs_pdu_rel13_t* srs_pdu_rel13 = (nfapi_ul_config_srs_pdu_rel13_t*)tlv; - - return ( push8(srs_pdu_rel13->number_of_combs, ppWritePackedMsg, end)); -} - -static uint8_t pack_ul_config_request_nb_harq_rel13_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_ul_config_nb_harq_information_rel13_fdd_t* nb_harq_pdu_rel13 = (nfapi_ul_config_nb_harq_information_rel13_fdd_t*)tlv; - - return ( push8(nb_harq_pdu_rel13->harq_ack_resource, ppWritePackedMsg, end)); -} - -static uint8_t pack_ul_config_request_nulsch_pdu_rel13_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_ul_config_nulsch_pdu_rel13_t* nulsch_pdu_rel13 = (nfapi_ul_config_nulsch_pdu_rel13_t*)tlv; - - return (push8(nulsch_pdu_rel13->nulsch_format, ppWritePackedMsg, end) && - push32(nulsch_pdu_rel13->handle, ppWritePackedMsg, end) && - push16(nulsch_pdu_rel13->size, ppWritePackedMsg, end) && - push16(nulsch_pdu_rel13->rnti, ppWritePackedMsg, end) && - push8(nulsch_pdu_rel13->subcarrier_indication, ppWritePackedMsg, end) && - push8(nulsch_pdu_rel13->resource_assignment, ppWritePackedMsg, end) && - push8(nulsch_pdu_rel13->mcs, ppWritePackedMsg, end) && - push8(nulsch_pdu_rel13->redudancy_version, ppWritePackedMsg, end) && - push8(nulsch_pdu_rel13->repetition_number, ppWritePackedMsg, end) && - push8(nulsch_pdu_rel13->new_data_indication, ppWritePackedMsg, end) && - push8(nulsch_pdu_rel13->n_srs, ppWritePackedMsg, end) && - push16(nulsch_pdu_rel13->scrambling_sequence_initialization_cinit, ppWritePackedMsg, end) && - push16(nulsch_pdu_rel13->sf_idx, ppWritePackedMsg, end) && - pack_ul_config_request_ue_information(&(nulsch_pdu_rel13->ue_information), ppWritePackedMsg, end) && - pack_tlv(NFAPI_UL_CONFIG_REQUEST_NB_HARQ_INFORMATION_REL13_FDD_TAG, &nulsch_pdu_rel13->nb_harq_information.nb_harq_information_rel13_fdd, ppWritePackedMsg, end, &pack_ul_config_request_nb_harq_rel13_value)); -} -static uint8_t pack_ul_config_request_nrach_pdu_rel13_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_ul_config_nrach_pdu_rel13_t* nrach_pdu_rel13 = (nfapi_ul_config_nrach_pdu_rel13_t*)tlv; - - return ( push8(nrach_pdu_rel13->nprach_config_0, ppWritePackedMsg, end) && - push8(nrach_pdu_rel13->nprach_config_1, ppWritePackedMsg, end) && - push8(nrach_pdu_rel13->nprach_config_2, ppWritePackedMsg, end)); - -} - - - -static uint8_t pack_ul_tti_pdu_list_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_nr_ul_tti_request_number_of_pdus_t* value = (nfapi_nr_ul_tti_request_number_of_pdus_t*)tlv; - - if(!(push16(value->pdu_size, ppWritePackedMsg, end) && - push16(value->pdu_type, ppWritePackedMsg, end) )) - return 0; - - - // first match the pdu type, then call the respective function - switch(value->pdu_type) - { - case NFAPI_NR_UL_CONFIG_PRACH_PDU_TYPE: - { - if(!pack_ul_tti_request_prach_pdu(&value->prach_pdu, ppWritePackedMsg, end)) - return 0; - } - break; - - case NFAPI_NR_UL_CONFIG_PUCCH_PDU_TYPE: - { - if(!pack_ul_tti_request_pucch_pdu(&value->pucch_pdu, ppWritePackedMsg, end)) - return 0; - } - break; - case NFAPI_NR_UL_CONFIG_PUSCH_PDU_TYPE: - { - if(!pack_ul_tti_request_pusch_pdu(&value->pusch_pdu, ppWritePackedMsg, end)) - return 0; - } - break; - case NFAPI_NR_UL_CONFIG_SRS_PDU_TYPE: - { - if(!pack_ul_tti_request_srs_pdu(&value->srs_pdu, ppWritePackedMsg, end)) - return 0; - } - break; - - default: - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "FIXME : Invalid UL_TTI pdu type %d \n", value->pdu_type ); - } - break; - } - - return 1; -} - -static uint8_t pack_ul_tti_groups_list_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_nr_ul_tti_request_number_of_groups_t* value = (nfapi_nr_ul_tti_request_number_of_groups_t*)tlv; - - if(!push8(value->n_ue, ppWritePackedMsg, end)) - return 0; - for(int i=0; in_ue;i++) - { - if(!push8(value->ue_list[i].pdu_idx, ppWritePackedMsg, end)) - return 0; - } - return 1; -} - -static uint8_t pack_ul_config_request_body_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_ul_config_request_body_t* value = (nfapi_ul_config_request_body_t*)tlv; - - if(!(push8(value->number_of_pdus, ppWritePackedMsg, end) && - push8(value->rach_prach_frequency_resources, ppWritePackedMsg, end) && - push8(value->srs_present, ppWritePackedMsg, end))) - return 0; - - uint16_t i = 0; - for(i = 0; i < value->number_of_pdus; ++i) - { - nfapi_ul_config_request_pdu_t* pdu = &(value->ul_config_pdu_list[i]); - - if(push8(pdu->pdu_type, ppWritePackedMsg, end) == 0) - return 0; - - // Put a 0 size in and then determine the size after the pdu - // has been writen and write the calculated size - uint8_t* pWritePackedMsgPduSize = *ppWritePackedMsg; - pdu->pdu_size = 0; - if(push8(pdu->pdu_size, ppWritePackedMsg, end) == 0) - return 0; - - switch(pdu->pdu_type) - { - case NFAPI_UL_CONFIG_ULSCH_PDU_TYPE: - { - if(!pack_ul_config_request_ulsch_pdu(&(pdu->ulsch_pdu), ppWritePackedMsg, end)) - return 0; - } - break; - case NFAPI_UL_CONFIG_ULSCH_CQI_RI_PDU_TYPE: - { - if(!(pack_ul_config_request_ulsch_pdu(&(pdu->ulsch_cqi_ri_pdu.ulsch_pdu), ppWritePackedMsg, end) && - pack_ul_config_request_cqi_ri_information(&(pdu->ulsch_cqi_ri_pdu.cqi_ri_information), ppWritePackedMsg, end) && - pack_ul_config_request_initial_transmission_parameters(&(pdu->ulsch_cqi_ri_pdu.initial_transmission_parameters), ppWritePackedMsg, end))) - return 0; - } - break; - case NFAPI_UL_CONFIG_ULSCH_HARQ_PDU_TYPE: - { - if(!(pack_ul_config_request_ulsch_pdu(&(pdu->ulsch_harq_pdu.ulsch_pdu), ppWritePackedMsg, end) && - pack_ul_config_request_ulsch_harq_information(&(pdu->ulsch_harq_pdu.harq_information), ppWritePackedMsg, end) && - pack_ul_config_request_initial_transmission_parameters(&(pdu->ulsch_harq_pdu.initial_transmission_parameters), ppWritePackedMsg, end))) - return 0; - } - break; - case NFAPI_UL_CONFIG_ULSCH_CQI_HARQ_RI_PDU_TYPE: - { - if(!(pack_ul_config_request_ulsch_pdu(&(pdu->ulsch_cqi_harq_ri_pdu.ulsch_pdu), ppWritePackedMsg, end) && - pack_ul_config_request_cqi_ri_information(&(pdu->ulsch_cqi_harq_ri_pdu.cqi_ri_information), ppWritePackedMsg, end) && - pack_ul_config_request_ulsch_harq_information(&(pdu->ulsch_cqi_harq_ri_pdu.harq_information), ppWritePackedMsg, end) && - pack_ul_config_request_initial_transmission_parameters(&(pdu->ulsch_cqi_harq_ri_pdu.initial_transmission_parameters), ppWritePackedMsg, end))) - return 0; - } - break; - case NFAPI_UL_CONFIG_UCI_CQI_PDU_TYPE: - { - if(!(pack_ul_config_request_ue_information(&(pdu->uci_cqi_pdu.ue_information), ppWritePackedMsg, end) && - pack_ul_config_request_cqi_information(&(pdu->uci_cqi_pdu.cqi_information), ppWritePackedMsg, end))) - return 0; - } - break; - case NFAPI_UL_CONFIG_UCI_SR_PDU_TYPE: - { - if(!(pack_ul_config_request_ue_information(&(pdu->uci_sr_pdu.ue_information), ppWritePackedMsg, end) && - pack_ul_config_request_sr_information(&(pdu->uci_sr_pdu.sr_information), ppWritePackedMsg, end))) - return 0; - } - break; - case NFAPI_UL_CONFIG_UCI_HARQ_PDU_TYPE: - { - if(!(pack_ul_config_request_ue_information(&(pdu->uci_harq_pdu.ue_information), ppWritePackedMsg, end) && - pack_ul_config_request_harq_information(&(pdu->uci_harq_pdu.harq_information), ppWritePackedMsg, end))) - return 0; - } - break; - case NFAPI_UL_CONFIG_UCI_SR_HARQ_PDU_TYPE: - { - if(!(pack_ul_config_request_ue_information(&(pdu->uci_sr_harq_pdu.ue_information), ppWritePackedMsg, end) && - pack_ul_config_request_sr_information(&(pdu->uci_sr_harq_pdu.sr_information), ppWritePackedMsg, end) && - pack_ul_config_request_harq_information(&(pdu->uci_sr_harq_pdu.harq_information), ppWritePackedMsg, end))) - return 0; - } - break; - case NFAPI_UL_CONFIG_UCI_CQI_HARQ_PDU_TYPE: - { - if(!(pack_ul_config_request_ue_information(&(pdu->uci_cqi_harq_pdu.ue_information), ppWritePackedMsg, end) && - pack_ul_config_request_cqi_information(&(pdu->uci_cqi_harq_pdu.cqi_information), ppWritePackedMsg, end) && - pack_ul_config_request_harq_information(&(pdu->uci_cqi_harq_pdu.harq_information), ppWritePackedMsg, end))) - return 0; - } - break; - case NFAPI_UL_CONFIG_UCI_CQI_SR_PDU_TYPE: - { - if(!(pack_ul_config_request_ue_information(&(pdu->uci_cqi_sr_pdu.ue_information), ppWritePackedMsg, end) && - pack_ul_config_request_cqi_information(&(pdu->uci_cqi_sr_pdu.cqi_information), ppWritePackedMsg, end) && - pack_ul_config_request_sr_information(&(pdu->uci_cqi_sr_pdu.sr_information), ppWritePackedMsg, end))) - return 0; - } - break; - case NFAPI_UL_CONFIG_UCI_CQI_SR_HARQ_PDU_TYPE: - { - if(!(pack_ul_config_request_ue_information(&(pdu->uci_cqi_sr_harq_pdu.ue_information), ppWritePackedMsg, end) && - pack_ul_config_request_cqi_information(&(pdu->uci_cqi_sr_harq_pdu.cqi_information), ppWritePackedMsg, end) && - pack_ul_config_request_sr_information(&(pdu->uci_cqi_sr_harq_pdu.sr_information), ppWritePackedMsg, end) && - pack_ul_config_request_harq_information(&(pdu->uci_cqi_sr_harq_pdu.harq_information), ppWritePackedMsg, end))) - return 0; - } - break; - case NFAPI_UL_CONFIG_SRS_PDU_TYPE: - { - if(!(pack_tlv(NFAPI_UL_CONFIG_REQUEST_SRS_PDU_REL8_TAG, &pdu->srs_pdu.srs_pdu_rel8, ppWritePackedMsg, end, &pack_ul_config_request_srs_pdu_rel8_value) && - pack_tlv(NFAPI_UL_CONFIG_REQUEST_SRS_PDU_REL10_TAG, &pdu->srs_pdu.srs_pdu_rel10, ppWritePackedMsg, end, &pack_ul_config_request_srs_pdu_rel10_value) && - pack_tlv(NFAPI_UL_CONFIG_REQUEST_SRS_PDU_REL13_TAG, &pdu->srs_pdu.srs_pdu_rel13, ppWritePackedMsg, end, &pack_ul_config_request_srs_pdu_rel13_value))) - return 0; - } - break; - case NFAPI_UL_CONFIG_HARQ_BUFFER_PDU_TYPE: - { - if(!(pack_ul_config_request_ue_information(&(pdu->harq_buffer_pdu.ue_information), ppWritePackedMsg, end))) - return 0; - } - break; - case NFAPI_UL_CONFIG_ULSCH_UCI_CSI_PDU_TYPE: - { - if(!(pack_ul_config_request_ulsch_pdu(&(pdu->ulsch_uci_csi_pdu.ulsch_pdu), ppWritePackedMsg, end) && - pack_ul_config_request_cqi_information(&(pdu->ulsch_uci_csi_pdu.csi_information), ppWritePackedMsg, end))) - return 0; - } - break; - case NFAPI_UL_CONFIG_ULSCH_UCI_HARQ_PDU_TYPE: - { - if(!(pack_ul_config_request_ulsch_pdu(&(pdu->ulsch_uci_harq_pdu.ulsch_pdu), ppWritePackedMsg, end) && - pack_ul_config_request_harq_information(&(pdu->ulsch_uci_harq_pdu.harq_information), ppWritePackedMsg, end))) - return 0; - } - break; - case NFAPI_UL_CONFIG_ULSCH_CSI_UCI_HARQ_PDU_TYPE: - { - if(!(pack_ul_config_request_ulsch_pdu(&(pdu->ulsch_csi_uci_harq_pdu.ulsch_pdu), ppWritePackedMsg, end) && - pack_ul_config_request_cqi_information(&(pdu->ulsch_csi_uci_harq_pdu.csi_information), ppWritePackedMsg, end) && - pack_ul_config_request_harq_information(&(pdu->ulsch_csi_uci_harq_pdu.harq_information), ppWritePackedMsg, end))) - return 0; - } - break; - case NFAPI_UL_CONFIG_NULSCH_PDU_TYPE: - { - if(!(pack_tlv(NFAPI_UL_CONFIG_REQUEST_NULSCH_PDU_REL13_TAG, &pdu->nulsch_pdu.nulsch_pdu_rel13, ppWritePackedMsg, end, &pack_ul_config_request_nulsch_pdu_rel13_value))) - return 0; - } - break; - case NFAPI_UL_CONFIG_NRACH_PDU_TYPE: - { - if(!(pack_tlv(NFAPI_UL_CONFIG_REQUEST_NRACH_PDU_REL13_TAG, &pdu->nrach_pdu.nrach_pdu_rel13, ppWritePackedMsg, end, &pack_ul_config_request_nrach_pdu_rel13_value))) - return 0; - } - break; - default: - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "FIXME : Invalid pdu type %d \n", pdu->pdu_type ); - } - break; - }; - - // add 1 for the pdu_type. The delta will include the pdu_size - pdu->pdu_size = 1 + (*ppWritePackedMsg - pWritePackedMsgPduSize); - push8(pdu->pdu_size, &pWritePackedMsgPduSize, end); - - } - return 1; -} - - -static uint8_t pack_ul_tti_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) -{ - nfapi_nr_ul_tti_request_t *pNfapiMsg = (nfapi_nr_ul_tti_request_t*)msg; - - if (!(push16(pNfapiMsg->SFN , ppWritePackedMsg, end) && - push16(pNfapiMsg->Slot , ppWritePackedMsg, end) && - push8(pNfapiMsg->n_pdus , ppWritePackedMsg, end) && - push8(pNfapiMsg->rach_present, ppWritePackedMsg, end) && - push8(pNfapiMsg->n_ulsch, ppWritePackedMsg, end) && - push8(pNfapiMsg->n_ulcch, ppWritePackedMsg, end) && - push8(pNfapiMsg->n_group, ppWritePackedMsg, end) )) - return 0; - - for(int i=0; in_pdus; i++) - { - if(!pack_ul_tti_pdu_list_value(&pNfapiMsg->pdus_list[i], ppWritePackedMsg, end)) - return 0; - } - - for(int i=0; in_group; i++) - { - if(!pack_ul_tti_groups_list_value(&pNfapiMsg->groups_list[i], ppWritePackedMsg, end)) - return 0; - - } - - return 1; -} - - -static uint8_t pack_ul_config_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) -{ - nfapi_ul_config_request_t *pNfapiMsg = (nfapi_ul_config_request_t*)msg; - - return ( push16(pNfapiMsg->sfn_sf, ppWritePackedMsg, end) && - pack_tlv(NFAPI_UL_CONFIG_REQUEST_BODY_TAG, &pNfapiMsg->ul_config_request_body, ppWritePackedMsg, end, &pack_ul_config_request_body_value) && - pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)) ; -} - -static uint8_t pack_hi_dci0_hi_rel8_pdu_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_hi_dci0_hi_pdu_rel8_t* hi_pdu_rel8 = (nfapi_hi_dci0_hi_pdu_rel8_t*)tlv; - - return ( push8(hi_pdu_rel8->resource_block_start, ppWritePackedMsg, end) && - push8(hi_pdu_rel8->cyclic_shift_2_for_drms, ppWritePackedMsg, end) && - push8(hi_pdu_rel8->hi_value, ppWritePackedMsg, end) && - push8(hi_pdu_rel8->i_phich, ppWritePackedMsg, end) && - push16(hi_pdu_rel8->transmission_power, ppWritePackedMsg, end)); -} - -static uint8_t pack_hi_dci0_hi_rel10_pdu_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_hi_dci0_hi_pdu_rel10_t* hi_pdu_rel10 = (nfapi_hi_dci0_hi_pdu_rel10_t*)tlv; - - return ( push8(hi_pdu_rel10->flag_tb2, ppWritePackedMsg, end) && - push8(hi_pdu_rel10->hi_value_2, ppWritePackedMsg, end)); -} - -static uint8_t pack_hi_dci0_dci_rel8_pdu_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_hi_dci0_dci_pdu_rel8_t* dci_pdu_rel8 = (nfapi_hi_dci0_dci_pdu_rel8_t*)tlv; - - return ( push8(dci_pdu_rel8->dci_format, ppWritePackedMsg, end) && - push8(dci_pdu_rel8->cce_index, ppWritePackedMsg, end) && - push8(dci_pdu_rel8->aggregation_level, ppWritePackedMsg, end) && - push16(dci_pdu_rel8->rnti, ppWritePackedMsg, end) && - push8(dci_pdu_rel8->resource_block_start, ppWritePackedMsg, end) && - push8(dci_pdu_rel8->number_of_resource_block, ppWritePackedMsg, end) && - push8(dci_pdu_rel8->mcs_1, ppWritePackedMsg, end) && - push8(dci_pdu_rel8->cyclic_shift_2_for_drms, ppWritePackedMsg, end) && - push8(dci_pdu_rel8->frequency_hopping_enabled_flag, ppWritePackedMsg, end) && - push8(dci_pdu_rel8->frequency_hopping_bits, ppWritePackedMsg, end) && - push8(dci_pdu_rel8->new_data_indication_1, ppWritePackedMsg, end) && - push8(dci_pdu_rel8->ue_tx_antenna_seleciton, ppWritePackedMsg, end) && - push8(dci_pdu_rel8->tpc, ppWritePackedMsg, end) && - push8(dci_pdu_rel8->cqi_csi_request, ppWritePackedMsg, end) && - push8(dci_pdu_rel8->ul_index, ppWritePackedMsg, end) && - push8(dci_pdu_rel8->dl_assignment_index, ppWritePackedMsg, end) && - push32(dci_pdu_rel8->tpc_bitmap, ppWritePackedMsg, end) && - push16(dci_pdu_rel8->transmission_power, ppWritePackedMsg, end)); -} - -static uint8_t pack_hi_dci0_dci_rel10_pdu_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_hi_dci0_dci_pdu_rel10_t* dci_pdu_rel10 = (nfapi_hi_dci0_dci_pdu_rel10_t*)tlv; - - return ( push8(dci_pdu_rel10->cross_carrier_scheduling_flag, ppWritePackedMsg, end) && - push8(dci_pdu_rel10->carrier_indicator, ppWritePackedMsg, end) && - push8(dci_pdu_rel10->size_of_cqi_csi_feild, ppWritePackedMsg, end) && - push8(dci_pdu_rel10->srs_flag, ppWritePackedMsg, end) && - push8(dci_pdu_rel10->srs_request, ppWritePackedMsg, end) && - push8(dci_pdu_rel10->resource_allocation_flag, ppWritePackedMsg, end) && - push8(dci_pdu_rel10->resource_allocation_type, ppWritePackedMsg, end) && - push32(dci_pdu_rel10->resource_block_coding, ppWritePackedMsg, end) && - push8(dci_pdu_rel10->mcs_2, ppWritePackedMsg, end) && - push8(dci_pdu_rel10->new_data_indication_2, ppWritePackedMsg, end) && - push8(dci_pdu_rel10->number_of_antenna_ports, ppWritePackedMsg, end) && - push8(dci_pdu_rel10->tpmi, ppWritePackedMsg, end) && - push8(dci_pdu_rel10->total_dci_length_including_padding, ppWritePackedMsg, end) && - push8(dci_pdu_rel10->n_ul_rb, ppWritePackedMsg, end)); -} - -static uint8_t pack_hi_dci0_dci_rel12_pdu_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_hi_dci0_dci_pdu_rel12_t* dci_pdu_rel12 = (nfapi_hi_dci0_dci_pdu_rel12_t*)tlv; - - return ( push8(dci_pdu_rel12->pscch_resource, ppWritePackedMsg, end) && - push8(dci_pdu_rel12->time_resource_pattern, ppWritePackedMsg, end)); -} - -static uint8_t pack_hi_dci0_mpdcch_dci_rel13_pdu_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_hi_dci0_mpdcch_dci_pdu_rel13_t* mpdcch_dci_pdu_rel13 = (nfapi_hi_dci0_mpdcch_dci_pdu_rel13_t*)tlv; - - return ( push8(mpdcch_dci_pdu_rel13->mpdcch_narrowband, ppWritePackedMsg, end) && - push8(mpdcch_dci_pdu_rel13->number_of_prb_pairs, ppWritePackedMsg, end) && - push8(mpdcch_dci_pdu_rel13->resource_block_assignment, ppWritePackedMsg, end) && - push8(mpdcch_dci_pdu_rel13->mpdcch_transmission_type, ppWritePackedMsg, end) && - push8(mpdcch_dci_pdu_rel13->start_symbol, ppWritePackedMsg, end) && - push8(mpdcch_dci_pdu_rel13->ecce_index, ppWritePackedMsg, end) && - push8(mpdcch_dci_pdu_rel13->aggreagation_level, ppWritePackedMsg, end) && - push8(mpdcch_dci_pdu_rel13->rnti_type, ppWritePackedMsg, end) && - push16(mpdcch_dci_pdu_rel13->rnti, ppWritePackedMsg, end) && - push8(mpdcch_dci_pdu_rel13->ce_mode, ppWritePackedMsg, end) && - push16(mpdcch_dci_pdu_rel13->drms_scrambling_init, ppWritePackedMsg, end) && - push16(mpdcch_dci_pdu_rel13->initial_transmission_sf_io, ppWritePackedMsg, end) && - push16(mpdcch_dci_pdu_rel13->transmission_power, ppWritePackedMsg, end) && - push8(mpdcch_dci_pdu_rel13->dci_format, ppWritePackedMsg, end) && - push8(mpdcch_dci_pdu_rel13->resource_block_start, ppWritePackedMsg, end) && - push8(mpdcch_dci_pdu_rel13->number_of_resource_blocks, ppWritePackedMsg, end) && - push8(mpdcch_dci_pdu_rel13->mcs, ppWritePackedMsg, end) && - push8(mpdcch_dci_pdu_rel13->pusch_repetition_levels, ppWritePackedMsg, end) && - push8(mpdcch_dci_pdu_rel13->frequency_hopping_flag, ppWritePackedMsg, end) && - push8(mpdcch_dci_pdu_rel13->new_data_indication, ppWritePackedMsg, end) && - push8(mpdcch_dci_pdu_rel13->harq_process, ppWritePackedMsg, end) && - push8(mpdcch_dci_pdu_rel13->redudency_version, ppWritePackedMsg, end) && - push8(mpdcch_dci_pdu_rel13->tpc, ppWritePackedMsg, end) && - push8(mpdcch_dci_pdu_rel13->csi_request, ppWritePackedMsg, end) && - push8(mpdcch_dci_pdu_rel13->ul_inex, ppWritePackedMsg, end) && - push8(mpdcch_dci_pdu_rel13->dai_presence_flag, ppWritePackedMsg, end) && - push8(mpdcch_dci_pdu_rel13->dl_assignment_index, ppWritePackedMsg, end) && - push8(mpdcch_dci_pdu_rel13->srs_request, ppWritePackedMsg, end) && - push8(mpdcch_dci_pdu_rel13->dci_subframe_repetition_number, ppWritePackedMsg, end) && - push32(mpdcch_dci_pdu_rel13->tcp_bitmap, ppWritePackedMsg, end) && - push8(mpdcch_dci_pdu_rel13->total_dci_length_include_padding, ppWritePackedMsg, end) && - push8(mpdcch_dci_pdu_rel13->number_of_tx_antenna_ports, ppWritePackedMsg, end) && - pusharray16(mpdcch_dci_pdu_rel13->precoding_value, NFAPI_MAX_TX_PHYSICAL_ANTENNA_PORTS, mpdcch_dci_pdu_rel13->number_of_tx_antenna_ports, ppWritePackedMsg, end)); - -} - -static uint8_t pack_hi_dci0_npdcch_dci_rel13_pdu_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_hi_dci0_npdcch_dci_pdu_rel13_t* npdcch_dci_pdu_rel13 = (nfapi_hi_dci0_npdcch_dci_pdu_rel13_t*)tlv; - - return ( push8(npdcch_dci_pdu_rel13->ncce_index, ppWritePackedMsg, end) && - push8(npdcch_dci_pdu_rel13->aggregation_level, ppWritePackedMsg, end) && - push8(npdcch_dci_pdu_rel13->start_symbol, ppWritePackedMsg, end) && - push16(npdcch_dci_pdu_rel13->rnti, ppWritePackedMsg, end) && - push8(npdcch_dci_pdu_rel13->scrambling_reinitialization_batch_index, ppWritePackedMsg, end) && - push8(npdcch_dci_pdu_rel13->nrs_antenna_ports_assumed_by_the_ue, ppWritePackedMsg, end) && - push8(npdcch_dci_pdu_rel13->subcarrier_indication, ppWritePackedMsg, end) && - push8(npdcch_dci_pdu_rel13->resource_assignment, ppWritePackedMsg, end) && - push8(npdcch_dci_pdu_rel13->scheduling_delay, ppWritePackedMsg, end) && - push8(npdcch_dci_pdu_rel13->mcs, ppWritePackedMsg, end) && - push8(npdcch_dci_pdu_rel13->redudancy_version, ppWritePackedMsg, end) && - push8(npdcch_dci_pdu_rel13->repetition_number, ppWritePackedMsg, end) && - push8(npdcch_dci_pdu_rel13->new_data_indicator, ppWritePackedMsg, end) && - push8(npdcch_dci_pdu_rel13->dci_subframe_repetition_number, ppWritePackedMsg, end)); -} - - -static uint8_t pack_hi_dci0_request_body_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_hi_dci0_request_body_t* value = (nfapi_hi_dci0_request_body_t*)tlv; - - if(!(push16(value->sfnsf, ppWritePackedMsg, end) && - push8(value->number_of_dci, ppWritePackedMsg, end) && - push8(value->number_of_hi, ppWritePackedMsg, end))) - return 0; - - uint16_t i = 0; - uint16_t total_number_of_pdus = value->number_of_dci + value->number_of_hi; - for(i = 0; i < total_number_of_pdus; ++i) - { - nfapi_hi_dci0_request_pdu_t* pdu = &(value->hi_dci0_pdu_list[i]); - - if(push8(pdu->pdu_type, ppWritePackedMsg, end) == 0) - return 0; - - // Put a 0 size in and then determine the size after the pdu - // has been writen and write the calculated size - uint8_t* pWritePackedMsgPduSize = *ppWritePackedMsg; - pdu->pdu_size = 0; - if(push8(pdu->pdu_size, ppWritePackedMsg, end) == 0) - return 0; - - switch(pdu->pdu_type) - { - case NFAPI_HI_DCI0_HI_PDU_TYPE: - { - if(!(pack_tlv(NFAPI_HI_DCI0_REQUEST_HI_PDU_REL8_TAG, &pdu->hi_pdu.hi_pdu_rel8, ppWritePackedMsg, end, pack_hi_dci0_hi_rel8_pdu_value) && - pack_tlv(NFAPI_HI_DCI0_REQUEST_HI_PDU_REL10_TAG, &pdu->hi_pdu.hi_pdu_rel10, ppWritePackedMsg, end, pack_hi_dci0_hi_rel10_pdu_value))) - return 0; - } - break; - case NFAPI_HI_DCI0_DCI_PDU_TYPE: - { - if(!(pack_tlv(NFAPI_HI_DCI0_REQUEST_DCI_PDU_REL8_TAG, &pdu->dci_pdu.dci_pdu_rel8, ppWritePackedMsg, end, pack_hi_dci0_dci_rel8_pdu_value) && - pack_tlv(NFAPI_HI_DCI0_REQUEST_DCI_PDU_REL10_TAG, &pdu->dci_pdu.dci_pdu_rel10, ppWritePackedMsg, end, pack_hi_dci0_dci_rel10_pdu_value) && - pack_tlv(NFAPI_HI_DCI0_REQUEST_DCI_PDU_REL12_TAG, &pdu->dci_pdu.dci_pdu_rel12, ppWritePackedMsg, end, pack_hi_dci0_dci_rel12_pdu_value))) - return 0; - } - break; - case NFAPI_HI_DCI0_EPDCCH_DCI_PDU_TYPE: - { - if(!(pack_tlv(NFAPI_HI_DCI0_REQUEST_EPDCCH_DCI_PDU_REL8_TAG, &pdu->epdcch_dci_pdu.epdcch_dci_pdu_rel8, ppWritePackedMsg, end, pack_hi_dci0_dci_rel8_pdu_value) && - pack_tlv(NFAPI_HI_DCI0_REQUEST_EPDCCH_DCI_PDU_REL10_TAG, &pdu->epdcch_dci_pdu.epdcch_dci_pdu_rel10, ppWritePackedMsg, end, pack_hi_dci0_dci_rel10_pdu_value) && - pack_tlv(NFAPI_HI_DCI0_REQUEST_EPDCCH_PARAMETERS_REL11_TAG, &pdu->epdcch_dci_pdu.epdcch_parameters_rel11, ppWritePackedMsg, end, pack_dl_config_epdcch_parameters_rel11_value))) - return 0; - } - break; - case NFAPI_HI_DCI0_MPDCCH_DCI_PDU_TYPE: - { - if(!(pack_tlv(NFAPI_HI_DCI0_REQUEST_MPDCCH_DCI_PDU_REL13_TAG, &pdu->mpdcch_dci_pdu.mpdcch_dci_pdu_rel13, ppWritePackedMsg, end, pack_hi_dci0_mpdcch_dci_rel13_pdu_value))) - return 0; - } - break; - case NFAPI_HI_DCI0_NPDCCH_DCI_PDU_TYPE: - { - if(!(pack_tlv(NFAPI_HI_DCI0_REQUEST_NPDCCH_DCI_PDU_REL13_TAG, &pdu->npdcch_dci_pdu.npdcch_dci_pdu_rel13, ppWritePackedMsg, end, pack_hi_dci0_npdcch_dci_rel13_pdu_value))) - return 0; - } - break; - default: - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "FIXME : Invalid pdu type %d \n", pdu->pdu_type ); - } - break; - }; - - // add 1 for the pdu_type. The delta will include the pdu_size - pdu->pdu_size = 1 + (*ppWritePackedMsg - pWritePackedMsgPduSize); - push8(pdu->pdu_size, &pWritePackedMsgPduSize, end); - - } - - return 1; -} - -static uint8_t pack_ul_dci_pdu_list_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_nr_ul_dci_request_pdus_t* value = (nfapi_nr_ul_dci_request_pdus_t*)tlv; - - for(uint8_t i = 0; i < MAX_DCI_CORESET; ++i) - { - if(!(push16(value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].RNTI, ppWritePackedMsg, end) && - push16(value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].ScramblingId, ppWritePackedMsg, end) && - - push16(value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].ScramblingRNTI, ppWritePackedMsg, end) && - push8(value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].CceIndex, ppWritePackedMsg, end) && - push8(value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].AggregationLevel, ppWritePackedMsg, end) && - push8(value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].beta_PDCCH_1_0, ppWritePackedMsg, end) && - - push8(value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].powerControlOffsetSS, ppWritePackedMsg, end) && - push16(value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].PayloadSizeBits, ppWritePackedMsg, end) && - - pusharray8(value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].Payload, value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].PayloadSizeBits, value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].PayloadSizeBits, ppWritePackedMsg, end))) - - return 0; - } - - return (push16(value->PDUType, ppWritePackedMsg, end) && - push16(value->PDUSize, ppWritePackedMsg, end) && - push16(value->pdcch_pdu.pdcch_pdu_rel15.BWPSize, ppWritePackedMsg, end) && - push16(value->pdcch_pdu.pdcch_pdu_rel15.BWPStart, ppWritePackedMsg, end) && - push8(value->pdcch_pdu.pdcch_pdu_rel15.SubcarrierSpacing, ppWritePackedMsg, end) && - push8(value->pdcch_pdu.pdcch_pdu_rel15.CyclicPrefix, ppWritePackedMsg, end) && - - push8(value->pdcch_pdu.pdcch_pdu_rel15.StartSymbolIndex, ppWritePackedMsg, end) && - push8(value->pdcch_pdu.pdcch_pdu_rel15.DurationSymbols, ppWritePackedMsg, end) && - pusharray8(value->pdcch_pdu.pdcch_pdu_rel15.FreqDomainResource, 6, 6, ppWritePackedMsg, end) && - push8(value->pdcch_pdu.pdcch_pdu_rel15.CceRegMappingType, ppWritePackedMsg, end) && - - push8(value->pdcch_pdu.pdcch_pdu_rel15.RegBundleSize, ppWritePackedMsg, end) && - push8(value->pdcch_pdu.pdcch_pdu_rel15.InterleaverSize, ppWritePackedMsg, end) && - push8(value->pdcch_pdu.pdcch_pdu_rel15.CoreSetType, ppWritePackedMsg, end) && - push16(value->pdcch_pdu.pdcch_pdu_rel15.ShiftIndex, ppWritePackedMsg, end) && - push8(value->pdcch_pdu.pdcch_pdu_rel15.precoderGranularity, ppWritePackedMsg, end) && - push16(value->pdcch_pdu.pdcch_pdu_rel15.numDlDci, ppWritePackedMsg, end)); - -} - -static uint8_t pack_ul_dci_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) -{ - nfapi_nr_ul_dci_request_t *pNfapiMsg = (nfapi_nr_ul_dci_request_t*)msg; - - if (!(push16(pNfapiMsg->SFN, ppWritePackedMsg, end) && - push16(pNfapiMsg->Slot, ppWritePackedMsg, end) && - push8(pNfapiMsg->numPdus, ppWritePackedMsg, end) - )) - return 0; - - for(int i=0; inumPdus; i++) - { - if(!pack_ul_dci_pdu_list_value(&pNfapiMsg->ul_dci_pdu_list[i], ppWritePackedMsg, end)) - return 0; - } - return 1; - - -} - - - -static uint8_t pack_hi_dci0_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) -{ - nfapi_hi_dci0_request_t *pNfapiMsg = (nfapi_hi_dci0_request_t*)msg; - - return ( push16(pNfapiMsg->sfn_sf, ppWritePackedMsg, end) && - pack_tlv(NFAPI_HI_DCI0_REQUEST_BODY_TAG, &pNfapiMsg->hi_dci0_request_body, ppWritePackedMsg, end, &pack_hi_dci0_request_body_value) && - pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); -} - -//pack_tx_data_pdu_list_value -static uint8_t pack_tx_data_pdu_list_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_nr_pdu_t* value = (nfapi_nr_pdu_t*)tlv; - - if(!(push32(value->num_TLV, ppWritePackedMsg, end) && - push16(value->PDU_index, ppWritePackedMsg, end) && - push16(value->PDU_length, ppWritePackedMsg, end) - )) - return 0; - - uint16_t i = 0; - uint16_t total_number_of_tlvs = value->num_TLV; - for(; i < total_number_of_tlvs; ++i) - { - - if (!(push16(value->TLVs[i].length, ppWritePackedMsg, end) && - push16(value->TLVs[i].tag, ppWritePackedMsg, end))) - return 0; - - switch(value->TLVs[i].tag) - { - case 0: - { - if(!pusharray32(value->TLVs[i].value.direct, 16384, value->TLVs[i].length, ppWritePackedMsg, end)) - return 0; - break; - - } - - case 1: - { - if(!pusharray32(value->TLVs[i].value.ptr, value->TLVs[i].length , value->TLVs[i].length, ppWritePackedMsg, end)) - return 0; - break; - - } - - default: - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "FIXME : Invalid tag value %d \n", value->TLVs[i].tag ); - break; - } - - } - } - return 1; -} - -static uint8_t pack_tx_request_body_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_tx_request_body_t* value = (nfapi_tx_request_body_t*)tlv; - - if(push16(value->number_of_pdus, ppWritePackedMsg, end) == 0) - return 0; - - uint16_t i = 0; - uint16_t total_number_of_pdus = value->number_of_pdus; - for(; i < total_number_of_pdus; ++i) - { - nfapi_tx_request_pdu_t* pdu = &(value->tx_pdu_list[i]); - - if(!(push16(pdu->pdu_length, ppWritePackedMsg, end) && - push16(pdu->pdu_index, ppWritePackedMsg, end))) - return 0; - - uint8_t j; - for(j = 0; j < pdu->num_segments; ++j) - { - // Use -1 as it is unbounded - // DJP - does not handle -1 - // DJP - if(pusharray8(pdu->segments[j].segment_data, (uint32_t)(-1), pdu->segments[j].segment_length, ppWritePackedMsg, end) == 0) - int push_ret = pusharray8(pdu->segments[j].segment_data, 65535, pdu->segments[j].segment_length, ppWritePackedMsg, end); - - if (pdu->segments[j].segment_length == 3) - { - NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() BCH? segment_data:%x %x %x\n", __FUNCTION__, - pdu->segments[j].segment_data[0], - pdu->segments[j].segment_data[1], - pdu->segments[j].segment_data[2] - ); - } - //NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() segment_data:%p segment_length:%u pusharray8()=%d\n", __FUNCTION__, pdu->segments[j].segment_data, pdu->segments[j].segment_length, push_ret); - - if (push_ret == 0) - { - return 0; - } - } - } - - return 1; -} - -static uint8_t pack_tx_data_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) -{ - nfapi_nr_tx_data_request_t *pNfapiMsg = (nfapi_nr_tx_data_request_t*)msg; - - if (!( - push16(pNfapiMsg->SFN, ppWritePackedMsg, end) && - push16(pNfapiMsg->Slot, ppWritePackedMsg, end) && - push16(pNfapiMsg->Number_of_PDUs, ppWritePackedMsg, end) - )) - return 0; - - for(int i=0; iNumber_of_PDUs; i++) - { - if(!pack_tx_data_pdu_list_value(&pNfapiMsg->pdu_list[i], ppWritePackedMsg, end)) - return 0; - } - - return 1; -} - -static uint8_t pack_tx_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) -{ - nfapi_tx_request_t *pNfapiMsg = (nfapi_tx_request_t*)msg; - - int x = push16(pNfapiMsg->sfn_sf, ppWritePackedMsg, end); - int y = pack_tlv(NFAPI_TX_REQUEST_BODY_TAG, &pNfapiMsg->tx_request_body, ppWritePackedMsg, end, &pack_tx_request_body_value); - int z = pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config); - - //NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() x:%d y:%d z:%d\n", __FUNCTION__, x, y, z); - - return x && y && z; -} - -static uint8_t pack_release_request_body_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_ue_release_request_body_t* value = (nfapi_ue_release_request_body_t*)tlv; - if(push16(value->number_of_TLVs, ppWritePackedMsg, end) == 0){ - return 0; - } - - uint8_t j; - uint16_t num = value->number_of_TLVs; - for(j = 0; j < num; ++j){ - if(push16(value->ue_release_request_TLVs_list[j].rnti, ppWritePackedMsg, end) == 0){ - return 0; - } - } - return 1; -} - -static uint8_t pack_ue_release_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) -{ - nfapi_ue_release_request_t *pNfapiMsg = (nfapi_ue_release_request_t*)msg; - int x = push16(pNfapiMsg->sfn_sf, ppWritePackedMsg, end); - int y = pack_tlv(NFAPI_UE_RELEASE_BODY_TAG, &pNfapiMsg->ue_release_request_body, ppWritePackedMsg, end, &pack_release_request_body_value); - int z = pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config); - return x && y && z; -} - -static uint8_t pack_ue_release_response(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) -{ - - nfapi_ue_release_response_t *pNfapiMsg = (nfapi_ue_release_response_t*)msg; - - int x = push32(pNfapiMsg->error_code, ppWritePackedMsg, end); - int z = pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config); - return x && z; -} - -static uint8_t pack_rx_ue_information_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_rx_ue_information* value = (nfapi_rx_ue_information*)tlv; - - return ( push32(value->handle, ppWritePackedMsg, end) && - push16(value->rnti, ppWritePackedMsg, end) ); -} - -static uint8_t unpack_rx_ue_information_value(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_rx_ue_information* value = (nfapi_rx_ue_information*)tlv; - - return ( pull32(ppReadPackedMsg, &value->handle, end) && - pull16(ppReadPackedMsg, &value->rnti, end)); -} - -static uint8_t pack_harq_indication_tdd_harq_data_bundling(nfapi_harq_indication_tdd_harq_data_bundling_t* data, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - return ( push8(data->value_0, ppWritePackedMsg, end) && - push8(data->value_1, ppWritePackedMsg, end)); -} - -static uint8_t pack_harq_indication_tdd_harq_data_multiplexing(nfapi_harq_indication_tdd_harq_data_multiplexing_t* data, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - return ( push8(data->value_0, ppWritePackedMsg, end) && - push8(data->value_1, ppWritePackedMsg, end) && - push8(data->value_2, ppWritePackedMsg, end) && - push8(data->value_3, ppWritePackedMsg, end)); -} - -static uint8_t pack_harq_indication_tdd_harq_data_special_bundling(nfapi_harq_indication_tdd_harq_data_special_bundling_t* data, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - return ( push8(data->value_0, ppWritePackedMsg, end) ); -} - -static uint8_t pack_harq_indication_tdd_harq_data(nfapi_harq_indication_tdd_harq_data_t* data, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - return ( push8(data->value_0, ppWritePackedMsg, end) ); -} - -static uint8_t pack_harq_indication_tdd_rel8_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_harq_indication_tdd_rel8_t* harq_indication_tdd_rel8 = (nfapi_harq_indication_tdd_rel8_t*)tlv; - - if(!(push8(harq_indication_tdd_rel8->mode, ppWritePackedMsg, end) && - push8(harq_indication_tdd_rel8->number_of_ack_nack, ppWritePackedMsg, end))) - return 0; - - uint8_t result = 0; - switch(harq_indication_tdd_rel8->mode) - { - case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_BUNDLING: - result = pack_harq_indication_tdd_harq_data_bundling(&harq_indication_tdd_rel8->harq_data.bundling, ppWritePackedMsg, end); - break; - case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_MULIPLEXING: - result = pack_harq_indication_tdd_harq_data_multiplexing(&harq_indication_tdd_rel8->harq_data.multiplex, ppWritePackedMsg, end); - break; - case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_SPECIAL_BUNDLING: - result = pack_harq_indication_tdd_harq_data_special_bundling(&harq_indication_tdd_rel8->harq_data.special_bundling, ppWritePackedMsg, end); - break; - case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_CHANNEL_SELECTION: - case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_FORMAT_3: - result = 1; - break; - default: - // err.... - break; - } - - return result; - -} - -static uint8_t pack_harq_indication_tdd_rel9_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_harq_indication_tdd_rel9_t* harq_indication_tdd_rel9 = (nfapi_harq_indication_tdd_rel9_t*)tlv; - - if(!(push8(harq_indication_tdd_rel9->mode, ppWritePackedMsg, end) && - push8(harq_indication_tdd_rel9->number_of_ack_nack, ppWritePackedMsg, end))) - return 0; - - uint8_t idx; - for(idx = 0; idx < harq_indication_tdd_rel9->number_of_ack_nack; ++idx) - { - uint8_t result = 0; - - switch(harq_indication_tdd_rel9->mode) - { - case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_BUNDLING: - result = pack_harq_indication_tdd_harq_data(&(harq_indication_tdd_rel9->harq_data[idx].bundling), ppWritePackedMsg, end); - break; - case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_MULIPLEXING: - result = pack_harq_indication_tdd_harq_data(&harq_indication_tdd_rel9->harq_data[idx].multiplex, ppWritePackedMsg, end); - break; - case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_SPECIAL_BUNDLING: - result = pack_harq_indication_tdd_harq_data_special_bundling(&harq_indication_tdd_rel9->harq_data[idx].special_bundling, ppWritePackedMsg, end); - break; - case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_CHANNEL_SELECTION: - result = pack_harq_indication_tdd_harq_data(&harq_indication_tdd_rel9->harq_data[idx].channel_selection, ppWritePackedMsg, end); - break; - case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_FORMAT_3: - result = pack_harq_indication_tdd_harq_data(&harq_indication_tdd_rel9->harq_data[idx].format_3, ppWritePackedMsg, end); - break; - default: - // err.... - break; - } - - if(result == 0) - return 0; - } - - return 1; -} - -static uint8_t pack_harq_indication_tdd_rel13_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_harq_indication_tdd_rel13_t* harq_indication_tdd_rel13 = (nfapi_harq_indication_tdd_rel13_t*)tlv; - - if(!(push8(harq_indication_tdd_rel13->mode, ppWritePackedMsg, end) && - push16(harq_indication_tdd_rel13->number_of_ack_nack, ppWritePackedMsg, end))) - return 0; - - uint8_t idx; - for(idx = 0; idx < harq_indication_tdd_rel13->number_of_ack_nack; ++idx) - { - uint8_t result = 0; - switch(harq_indication_tdd_rel13->mode) - { - case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_BUNDLING: - result = pack_harq_indication_tdd_harq_data(&harq_indication_tdd_rel13->harq_data[idx].bundling, ppWritePackedMsg, end); - break; - case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_MULIPLEXING: - result = pack_harq_indication_tdd_harq_data(&harq_indication_tdd_rel13->harq_data[idx].multiplex, ppWritePackedMsg, end); - break; - case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_SPECIAL_BUNDLING: - result = pack_harq_indication_tdd_harq_data_special_bundling(&harq_indication_tdd_rel13->harq_data[idx].special_bundling, ppWritePackedMsg, end); - break; - case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_CHANNEL_SELECTION: - result = pack_harq_indication_tdd_harq_data(&harq_indication_tdd_rel13->harq_data[idx].channel_selection, ppWritePackedMsg, end); - break; - case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_FORMAT_3: - result = pack_harq_indication_tdd_harq_data(&harq_indication_tdd_rel13->harq_data[idx].format_3, ppWritePackedMsg, end); - break; - case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_FORMAT_4: - result = pack_harq_indication_tdd_harq_data(&harq_indication_tdd_rel13->harq_data[idx].format_4, ppWritePackedMsg, end); - break; - case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_FORMAT_5: - result = pack_harq_indication_tdd_harq_data(&harq_indication_tdd_rel13->harq_data[idx].format_5, ppWritePackedMsg, end); - break; - default: - // err.... - break; - } - - if(result == 0) - return 0; - } - - return 1; -} - -static uint8_t pack_harq_indication_fdd_rel8_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_harq_indication_fdd_rel8_t* harq_indication_fdd_rel8 = (nfapi_harq_indication_fdd_rel8_t*)tlv; - - return ( push8(harq_indication_fdd_rel8->harq_tb1, ppWritePackedMsg, end) && - push8(harq_indication_fdd_rel8->harq_tb2, ppWritePackedMsg, end)); -} - -static uint8_t pack_harq_indication_fdd_rel9_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_harq_indication_fdd_rel9_t* harq_indication_fdd_rel9 = (nfapi_harq_indication_fdd_rel9_t*)tlv; - - return ( push8(harq_indication_fdd_rel9->mode, ppWritePackedMsg, end) && - push8(harq_indication_fdd_rel9->number_of_ack_nack, ppWritePackedMsg, end) && - pusharray8(harq_indication_fdd_rel9->harq_tb_n, NFAPI_HARQ_ACK_NACK_REL9_MAX, harq_indication_fdd_rel9->number_of_ack_nack, ppWritePackedMsg, end)); -} - -static uint8_t pack_harq_indication_fdd_rel13_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_harq_indication_fdd_rel13_t* harq_indication_fdd_rel13 = (nfapi_harq_indication_fdd_rel13_t*)tlv; - - return ( push8(harq_indication_fdd_rel13->mode, ppWritePackedMsg, end) && - push16(harq_indication_fdd_rel13->number_of_ack_nack, ppWritePackedMsg, end) && - pusharray8(harq_indication_fdd_rel13->harq_tb_n, NFAPI_HARQ_ACK_NACK_REL13_MAX, harq_indication_fdd_rel13->number_of_ack_nack, ppWritePackedMsg, end)); -} - -static uint8_t pack_ul_cqi_information_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_ul_cqi_information_t* value = (nfapi_ul_cqi_information_t*)tlv; - - return ( push8(value->ul_cqi, ppWritePackedMsg, end) && - push8(value->channel, ppWritePackedMsg, end)); - -} - -static uint8_t pack_harq_indication_body_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_harq_indication_body_t* value = (nfapi_harq_indication_body_t*)tlv; - - if(push16(value->number_of_harqs, ppWritePackedMsg, end) == 0) - return 0; - - uint16_t i = 0; - uint16_t total_number_of_pdus = value->number_of_harqs; - for(; i < total_number_of_pdus; ++i) - { - nfapi_harq_indication_pdu_t* pdu = &(value->harq_pdu_list[i]); - - uint8_t* instance_length_p = *ppWritePackedMsg; - if(!push16(pdu->instance_length, ppWritePackedMsg, end)) - return 0; - - if(!(pack_tlv(NFAPI_RX_UE_INFORMATION_TAG, &pdu->rx_ue_information, ppWritePackedMsg, end, pack_rx_ue_information_value) && - pack_tlv(NFAPI_HARQ_INDICATION_TDD_REL8_TAG, &pdu->harq_indication_tdd_rel8, ppWritePackedMsg, end, pack_harq_indication_tdd_rel8_value) && - pack_tlv(NFAPI_HARQ_INDICATION_TDD_REL9_TAG, &pdu->harq_indication_tdd_rel9, ppWritePackedMsg, end, pack_harq_indication_tdd_rel9_value) && - pack_tlv(NFAPI_HARQ_INDICATION_TDD_REL13_TAG, &pdu->harq_indication_tdd_rel13, ppWritePackedMsg, end, pack_harq_indication_tdd_rel13_value) && - pack_tlv(NFAPI_HARQ_INDICATION_FDD_REL8_TAG, &pdu->harq_indication_fdd_rel8, ppWritePackedMsg, end, pack_harq_indication_fdd_rel8_value) && - pack_tlv(NFAPI_HARQ_INDICATION_FDD_REL9_TAG, &pdu->harq_indication_fdd_rel9, ppWritePackedMsg, end, pack_harq_indication_fdd_rel9_value) && - pack_tlv(NFAPI_HARQ_INDICATION_FDD_REL13_TAG, &pdu->harq_indication_fdd_rel13, ppWritePackedMsg, end, pack_harq_indication_fdd_rel13_value) && - pack_tlv(NFAPI_UL_CQI_INFORMATION_TAG, &pdu->ul_cqi_information, ppWritePackedMsg, end, pack_ul_cqi_information_value))) - return 0; - - // calculate the instance length subtracting the size of the instance - // length feild - uint16_t instance_length = *ppWritePackedMsg - instance_length_p - 2; - push16(instance_length, &instance_length_p, end); - } - - return 1; -} - -static uint8_t pack_harq_indication(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) -{ - nfapi_harq_indication_t *pNfapiMsg = (nfapi_harq_indication_t*)msg; - - return ( push16(pNfapiMsg->sfn_sf, ppWritePackedMsg, end) && - pack_tlv(NFAPI_HARQ_INDICATION_BODY_TAG, &pNfapiMsg->harq_indication_body, ppWritePackedMsg, end, pack_harq_indication_body_value) && - pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); -} - -static uint8_t pack_crc_indication_rel8_body(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_crc_indication_rel8_t* crc_indication_rel8 = (nfapi_crc_indication_rel8_t*)tlv; - - return ( push8(crc_indication_rel8->crc_flag, ppWritePackedMsg, end) ); -} - -static uint8_t pack_crc_indication_body_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_crc_indication_body_t* value = (nfapi_crc_indication_body_t*)tlv; - - if(push16(value->number_of_crcs, ppWritePackedMsg, end) == 0) - return 0; - - uint16_t i = 0; - uint16_t total_number_of_pdus = value->number_of_crcs; - for(; i < total_number_of_pdus; ++i) - { - nfapi_crc_indication_pdu_t* pdu = &(value->crc_pdu_list[i]); - - uint8_t* instance_length_p = *ppWritePackedMsg; - if(!push16(pdu->instance_length, ppWritePackedMsg, end)) - return 0; - - if(!(pack_tlv(NFAPI_RX_UE_INFORMATION_TAG, &pdu->rx_ue_information, ppWritePackedMsg, end, pack_rx_ue_information_value) && - pack_tlv(NFAPI_CRC_INDICATION_REL8_TAG, &pdu->crc_indication_rel8, ppWritePackedMsg, end, pack_crc_indication_rel8_body))) - return 0; - - // calculate the instance length subtracting the size of the instance - // length feild - uint16_t instance_length = *ppWritePackedMsg - instance_length_p - 2; - push16(instance_length, &instance_length_p, end); - } - return 1; -} - -static uint8_t pack_crc_indication(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) -{ - nfapi_crc_indication_t *pNfapiMsg = (nfapi_crc_indication_t*)msg; - - return ( push16(pNfapiMsg->sfn_sf, ppWritePackedMsg, end) && - pack_tlv(NFAPI_CRC_INDICATION_BODY_TAG, &pNfapiMsg->crc_indication_body, ppWritePackedMsg, end, &pack_crc_indication_body_value) && - pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); - -} -static uint8_t pack_rx_indication_rel8_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_rx_indication_rel8_t* value = (nfapi_rx_indication_rel8_t*)tlv; - - return ( push16(value->length, ppWritePackedMsg, end) && - push16(value->offset, ppWritePackedMsg, end) && - push8(value->ul_cqi, ppWritePackedMsg, end) && - push16(value->timing_advance, ppWritePackedMsg, end)); -} -static uint8_t pack_rx_indication_rel9_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_rx_indication_rel9_t* value = (nfapi_rx_indication_rel9_t*)tlv; - - return ( push16(value->timing_advance_r9, ppWritePackedMsg, end)); -} - -static uint8_t pack_rx_ulsch_indication_body_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_rx_indication_body_t* value = (nfapi_rx_indication_body_t*)tlv; - - //printf("RX ULSCH BODY\n"); - - if( push16(value->number_of_pdus, ppWritePackedMsg, end) == 0) - return 0; - - // need to calculate the data offset's. - uint16_t i = 0; - uint16_t offset = 2; // taking into account the number_of_pdus - uint16_t total_number_of_pdus = value->number_of_pdus; - //printf("ULSCH:pdus:%d\n", total_number_of_pdus); - - for(i = 0; i < total_number_of_pdus; ++i) - { - nfapi_rx_indication_pdu_t* pdu = &(value->rx_pdu_list[i]); - if(pdu->rx_ue_information.tl.tag == NFAPI_RX_UE_INFORMATION_TAG) - { - //printf("NFAPI_RX_UE_INFORMATION_TAG\n"); - offset += 4 + 6; - } - - if(pdu->rx_indication_rel8.tl.tag == NFAPI_RX_INDICATION_REL8_TAG) - { - //printf("NFAPI_RX_INDICATION_REL8_TAG\n"); - offset += 4 + 7; - } - - if(pdu->rx_indication_rel9.tl.tag == NFAPI_RX_INDICATION_REL9_TAG) - { - //printf("NFAPI_RX_INDICATION_REL9_TAG\n"); - offset += 4 + 2; - } - } - - // Now update the structure to include the offset - for(i =0; i < total_number_of_pdus; ++i) - { - nfapi_rx_indication_pdu_t* pdu = &(value->rx_pdu_list[i]); - - if(pdu->rx_indication_rel8.tl.tag == NFAPI_RX_INDICATION_REL8_TAG) - { - if(pdu->rx_indication_rel8.offset == 1) - { - pdu->rx_indication_rel8.offset = offset; - offset += pdu->rx_indication_rel8.length; - } - } - } - - // Write out the pdu - for(i = 0; i < total_number_of_pdus; ++i) - { - nfapi_rx_indication_pdu_t* pdu = &(value->rx_pdu_list[i]); - if(!(pack_tlv(NFAPI_RX_UE_INFORMATION_TAG, &pdu->rx_ue_information, ppWritePackedMsg, end, pack_rx_ue_information_value) && - pack_tlv(NFAPI_RX_INDICATION_REL8_TAG, &pdu->rx_indication_rel8, ppWritePackedMsg, end, pack_rx_indication_rel8_value) && - pack_tlv(NFAPI_RX_INDICATION_REL9_TAG, &pdu->rx_indication_rel9, ppWritePackedMsg, end, pack_rx_indication_rel9_value))) - return 0; - } - - // Write out the pdu data - for(i = 0; i < total_number_of_pdus; ++i) - { - uint16_t length = 0; - nfapi_rx_indication_pdu_t* pdu = &(value->rx_pdu_list[i]); - - if(pdu->rx_indication_rel8.tl.tag == NFAPI_RX_INDICATION_REL8_TAG) - { - length = pdu->rx_indication_rel8.length; - } - - if( pusharray8(value->rx_pdu_list[i].data, length, length, ppWritePackedMsg, end) == 0) - return 0; - } - return 1; -} - - -static uint8_t pack_rx_ulsch_indication(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) -{ - nfapi_rx_indication_t *pNfapiMsg = (nfapi_rx_indication_t*)msg; - - return ( push16(pNfapiMsg->sfn_sf, ppWritePackedMsg, end) && - pack_tlv(NFAPI_RX_INDICATION_BODY_TAG, &pNfapiMsg->rx_indication_body, ppWritePackedMsg, end, pack_rx_ulsch_indication_body_value) && - pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); -} - -static uint8_t pack_preamble_pdu_rel8_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_preamble_pdu_rel8_t* preamble_rel8 = (nfapi_preamble_pdu_rel8_t*)tlv; - - return ( push16(preamble_rel8->rnti, ppWritePackedMsg, end) && - push8(preamble_rel8->preamble, ppWritePackedMsg, end) && - push16(preamble_rel8->timing_advance, ppWritePackedMsg, end)); -} -static uint8_t pack_preamble_pdu_rel9_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_preamble_pdu_rel9_t* preamble_rel9 = (nfapi_preamble_pdu_rel9_t*)tlv; - - return ( push16(preamble_rel9->timing_advance_r9, ppWritePackedMsg, end) ); -} -static uint8_t pack_preamble_pdu_rel13_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_preamble_pdu_rel13_t* preamble_rel13 = (nfapi_preamble_pdu_rel13_t*)tlv; - - return ( push8(preamble_rel13->rach_resource_type, ppWritePackedMsg, end) ); -} - -static uint8_t pack_rach_indication_body_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_rach_indication_body_t* value = (nfapi_rach_indication_body_t*)tlv; - - if( push16(value->number_of_preambles, ppWritePackedMsg, end) == 0) - return 0; - - uint16_t i = 0; - uint16_t total_number_of_pdus = value->number_of_preambles; - for(; i < total_number_of_pdus; ++i) - { - nfapi_preamble_pdu_t* pdu = &(value->preamble_list[i]); - - uint8_t* instance_length_p = *ppWritePackedMsg; - if(!push16(pdu->instance_length, ppWritePackedMsg, end)) - return 0; - - if(!(pack_tlv(NFAPI_PREAMBLE_REL8_TAG, &pdu->preamble_rel8, ppWritePackedMsg, end, pack_preamble_pdu_rel8_value) && - pack_tlv(NFAPI_PREAMBLE_REL9_TAG, &pdu->preamble_rel9, ppWritePackedMsg, end, pack_preamble_pdu_rel9_value) && - pack_tlv(NFAPI_PREAMBLE_REL13_TAG, &pdu->preamble_rel13, ppWritePackedMsg, end, pack_preamble_pdu_rel13_value))) - return 0; - - // calculate the instance length subtracting the size of the instance - // length feild - uint16_t instance_length = *ppWritePackedMsg - instance_length_p - 2; - push16(instance_length, &instance_length_p, end); - } - - return 1; -} - -static uint8_t pack_rach_indication(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) -{ - nfapi_rach_indication_t *pNfapiMsg = (nfapi_rach_indication_t*)msg; - - return ( push16(pNfapiMsg->sfn_sf, ppWritePackedMsg, end) && - pack_tlv(NFAPI_RACH_INDICATION_BODY_TAG, &pNfapiMsg->rach_indication_body, ppWritePackedMsg, end, pack_rach_indication_body_value) && - pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); -} - -static uint8_t pack_srs_indication_fdd_rel8_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_srs_indication_fdd_rel8_t* srs_pdu_rel8 = (nfapi_srs_indication_fdd_rel8_t*)tlv; - - return ( push16(srs_pdu_rel8->doppler_estimation, ppWritePackedMsg, end) && - push16(srs_pdu_rel8->timing_advance, ppWritePackedMsg, end) && - push8(srs_pdu_rel8->number_of_resource_blocks, ppWritePackedMsg, end) && - push8(srs_pdu_rel8->rb_start, ppWritePackedMsg, end) && - pusharray8(srs_pdu_rel8->snr, NFAPI_NUM_RB_MAX, srs_pdu_rel8->number_of_resource_blocks, ppWritePackedMsg, end)); -} - -static uint8_t pack_srs_indication_fdd_rel9_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_srs_indication_fdd_rel9_t* srs_pdu_rel9 = (nfapi_srs_indication_fdd_rel9_t*)tlv; - - return ( push16(srs_pdu_rel9->timing_advance_r9, ppWritePackedMsg, end) ); -} - -static uint8_t pack_srs_indication_tdd_rel10_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_srs_indication_ttd_rel10_t* srs_pdu_rel10 = (nfapi_srs_indication_ttd_rel10_t*)tlv; - - return ( push8(srs_pdu_rel10->uppts_symbol, ppWritePackedMsg, end) ); - -} - -static uint8_t pack_srs_indication_fdd_rel11_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_srs_indication_fdd_rel11_t* srs_pdu_rel11 = (nfapi_srs_indication_fdd_rel11_t*)tlv; - - return ( push16(srs_pdu_rel11->ul_rtoa, ppWritePackedMsg, end) ) ; -} - -static uint8_t pack_tdd_channel_measurement_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_tdd_channel_measurement_t* value = (nfapi_tdd_channel_measurement_t*)tlv; - - if(!(push8(value->num_prb_per_subband, ppWritePackedMsg, end) && - push8(value->number_of_subbands, ppWritePackedMsg, end) && - push8(value->num_atennas, ppWritePackedMsg, end))) - return 0; - - uint8_t idx = 0; - for(idx = 0; idx < value->number_of_subbands; ++idx) - { - if(!(push8(value->subands[idx].subband_index, ppWritePackedMsg, end) && - pusharray16(value->subands[idx].channel, NFAPI_MAX_NUM_PHYSICAL_ANTENNAS, value->num_atennas, ppWritePackedMsg, end))) - return 0; - } - - return 1; -} - -static uint8_t pack_srs_indication_body_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_srs_indication_body_t *value = (nfapi_srs_indication_body_t*)tlv; - - if( push8(value->number_of_ues, ppWritePackedMsg, end) == 0) - return 0; - - uint16_t i = 0; - uint16_t total_number_of_pdus = value->number_of_ues; - for(; i < total_number_of_pdus; ++i) - { - nfapi_srs_indication_pdu_t* pdu = &(value->srs_pdu_list[i]); - - uint8_t* instance_length_p = *ppWritePackedMsg; - if(!push16(pdu->instance_length, ppWritePackedMsg, end)) - return 0; - - if(!(pack_tlv(NFAPI_RX_UE_INFORMATION_TAG, &pdu->rx_ue_information, ppWritePackedMsg, end, &pack_rx_ue_information_value) && - pack_tlv(NFAPI_SRS_INDICATION_FDD_REL8_TAG, &pdu->srs_indication_fdd_rel8, ppWritePackedMsg, end, &pack_srs_indication_fdd_rel8_value) && - pack_tlv(NFAPI_SRS_INDICATION_FDD_REL9_TAG, &pdu->srs_indication_fdd_rel9, ppWritePackedMsg, end, &pack_srs_indication_fdd_rel9_value) && - pack_tlv(NFAPI_SRS_INDICATION_TDD_REL10_TAG, &pdu->srs_indication_tdd_rel10, ppWritePackedMsg, end, &pack_srs_indication_tdd_rel10_value) && - pack_tlv(NFAPI_SRS_INDICATION_FDD_REL11_TAG, &pdu->srs_indication_fdd_rel11, ppWritePackedMsg, end, &pack_srs_indication_fdd_rel11_value) && - pack_tlv(NFAPI_TDD_CHANNEL_MEASUREMENT_TAG, &pdu->tdd_channel_measurement, ppWritePackedMsg, end, &pack_tdd_channel_measurement_value))) - return 0; - - // calculate the instance length subtracting the size of the instance - // length feild - uint16_t instance_length = *ppWritePackedMsg - instance_length_p - 2; - push16(instance_length, &instance_length_p, end); - } - - return 1; -} - -static uint8_t pack_srs_indication(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) -{ - nfapi_srs_indication_t *pNfapiMsg = (nfapi_srs_indication_t*)msg; - - return ( push16(pNfapiMsg->sfn_sf, ppWritePackedMsg, end) && - pack_tlv(NFAPI_SRS_INDICATION_BODY_TAG, &pNfapiMsg->srs_indication_body, ppWritePackedMsg, end, &pack_srs_indication_body_value) && - pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); - -} - -static uint8_t pack_sr_indication_body_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_sr_indication_body_t* value = (nfapi_sr_indication_body_t*)tlv; - - if(push16(value->number_of_srs, ppWritePackedMsg, end) == 0) - return 0; - - uint16_t i = 0; - uint16_t total_number_of_pdus = value->number_of_srs; - for(; i < total_number_of_pdus; ++i) - { - nfapi_sr_indication_pdu_t* pdu = &(value->sr_pdu_list[i]); - - uint8_t* instance_length_p = *ppWritePackedMsg; - if(!push16(pdu->instance_length, ppWritePackedMsg, end)) - return 0; - - if(!(pack_tlv(NFAPI_RX_UE_INFORMATION_TAG, &pdu->rx_ue_information, ppWritePackedMsg, end, pack_rx_ue_information_value) && - pack_tlv(NFAPI_UL_CQI_INFORMATION_TAG, &pdu->ul_cqi_information, ppWritePackedMsg, end, pack_ul_cqi_information_value))) - return 0; - - // calculate the instance length subtracting the size of the instance - // length feild - uint16_t instance_length = *ppWritePackedMsg - instance_length_p - 2; - push16(instance_length, &instance_length_p, end); - } - return 1; -} - -static uint8_t pack_sr_indication(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) -{ - nfapi_sr_indication_t *pNfapiMsg = (nfapi_sr_indication_t*)msg; - - return ( push16(pNfapiMsg->sfn_sf, ppWritePackedMsg, end) && - pack_tlv(NFAPI_SR_INDICATION_BODY_TAG, &pNfapiMsg->sr_indication_body, ppWritePackedMsg, end, &pack_sr_indication_body_value) && - pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); - -} - -static uint8_t pack_cqi_indication_rel8_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_cqi_indication_rel8_t* cqi_pdu_rel8 = (nfapi_cqi_indication_rel8_t*)tlv; - - return ( push16(cqi_pdu_rel8->length, ppWritePackedMsg, end) && - push16(cqi_pdu_rel8->data_offset, ppWritePackedMsg, end) && - push8(cqi_pdu_rel8->ul_cqi, ppWritePackedMsg, end) && - push8(cqi_pdu_rel8->ri, ppWritePackedMsg, end) && - push16(cqi_pdu_rel8->timing_advance, ppWritePackedMsg, end)); -} - -static uint8_t pack_cqi_indication_rel9_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_cqi_indication_rel9_t* cqi_pdu_rel9 = (nfapi_cqi_indication_rel9_t*)tlv; - - return ( push16(cqi_pdu_rel9->length, ppWritePackedMsg, end) && - push16(cqi_pdu_rel9->data_offset, ppWritePackedMsg, end) && - push8(cqi_pdu_rel9->ul_cqi, ppWritePackedMsg, end) && - push8(cqi_pdu_rel9->number_of_cc_reported, ppWritePackedMsg, end) && - pusharray8(cqi_pdu_rel9->ri, NFAPI_CC_MAX, cqi_pdu_rel9->number_of_cc_reported, ppWritePackedMsg, end) && - push16(cqi_pdu_rel9->timing_advance, ppWritePackedMsg, end) && - push16(cqi_pdu_rel9->timing_advance_r9, ppWritePackedMsg, end)); -} - -static uint8_t pack_cqi_indication_body_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_cqi_indication_body_t* value = (nfapi_cqi_indication_body_t*)tlv; - - if( push16(value->number_of_cqis, ppWritePackedMsg, end) == 0) - return 0; - - // need to calculate the data offset's. This very bittle due the hardcoding - // of the sizes. can not use the sizeof as we have an array for the Rel9 - // info - uint16_t i = 0; - uint16_t offset = 2; // taking into account the number_of_cqis - uint16_t total_number_of_pdus = value->number_of_cqis; - for(i = 0; i < total_number_of_pdus; ++i) - { - nfapi_cqi_indication_pdu_t* pdu = &(value->cqi_pdu_list[i]); - - offset += 2; // for the instance length - - if(pdu->rx_ue_information.tl.tag == NFAPI_RX_UE_INFORMATION_TAG) - { - offset += 4 + 6; // sizeof(nfapi_rx_ue_information) - sizeof(nfapi_tl_t) - } - - if(pdu->cqi_indication_rel8.tl.tag == NFAPI_CQI_INDICATION_REL8_TAG) - { - offset += 4 + 8; - } - - if(pdu->cqi_indication_rel9.tl.tag == NFAPI_CQI_INDICATION_REL9_TAG) - { - offset += 4 + 10 + pdu->cqi_indication_rel9.number_of_cc_reported; - } - - if(pdu->ul_cqi_information.tl.tag == NFAPI_UL_CQI_INFORMATION_TAG) - { - offset += 4 + 2; - } - } - - // Now update the structure to include the offset - for(i =0; i < total_number_of_pdus; ++i) - { - nfapi_cqi_indication_pdu_t* pdu = &(value->cqi_pdu_list[i]); - - if(pdu->cqi_indication_rel8.tl.tag == NFAPI_CQI_INDICATION_REL8_TAG) - { - if(pdu->cqi_indication_rel8.data_offset == 1) - { - pdu->cqi_indication_rel8.data_offset = offset; - offset += pdu->cqi_indication_rel8.length; - } - } - - if(pdu->cqi_indication_rel9.tl.tag == NFAPI_CQI_INDICATION_REL9_TAG) - { - if(pdu->cqi_indication_rel9.data_offset == 1) - { - pdu->cqi_indication_rel9.data_offset = offset; - offset += pdu->cqi_indication_rel9.length; - } - } - - } - - // Write out the cqi information - for(i = 0; i < total_number_of_pdus; ++i) - { - nfapi_cqi_indication_pdu_t* pdu = &(value->cqi_pdu_list[i]); - - uint8_t* instance_length_p = *ppWritePackedMsg; - if(!push16(pdu->instance_length, ppWritePackedMsg, end)) - return 0; - - if(!(pack_tlv(NFAPI_RX_UE_INFORMATION_TAG, &pdu->rx_ue_information, ppWritePackedMsg, end ,pack_rx_ue_information_value) && - pack_tlv(NFAPI_CQI_INDICATION_REL8_TAG, &pdu->cqi_indication_rel8, ppWritePackedMsg, end, pack_cqi_indication_rel8_value) && - pack_tlv(NFAPI_CQI_INDICATION_REL9_TAG, &pdu->cqi_indication_rel9, ppWritePackedMsg, end, pack_cqi_indication_rel9_value) && - pack_tlv(NFAPI_UL_CQI_INFORMATION_TAG, &pdu->ul_cqi_information, ppWritePackedMsg, end, pack_ul_cqi_information_value))) - return 0; - - // calculate the instance length subtracting the size of the instance - // length feild - uint16_t instance_length = *ppWritePackedMsg - instance_length_p - 2; - push16(instance_length, &instance_length_p, end); - - } - - // Write out the cqi raw data - for(i = 0; i < total_number_of_pdus; ++i) - { - uint16_t length = 0; - nfapi_cqi_indication_pdu_t* pdu = &(value->cqi_pdu_list[i]); - - if(pdu->cqi_indication_rel8.tl.tag == NFAPI_CQI_INDICATION_REL8_TAG) - { - length = pdu->cqi_indication_rel8.length; - } - - if(pdu->cqi_indication_rel9.tl.tag == NFAPI_CQI_INDICATION_REL9_TAG) - { - length = pdu->cqi_indication_rel9.length; - } - - if( pusharray8(value->cqi_raw_pdu_list[i].pdu, NFAPI_CQI_RAW_MAX_LEN, length, ppWritePackedMsg, end) == 0) - return 0; - } - - return 1; -} - -static uint8_t pack_cqi_indication(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) -{ - nfapi_cqi_indication_t *pNfapiMsg = (nfapi_cqi_indication_t*)msg; - - return ( push16(pNfapiMsg->sfn_sf, ppWritePackedMsg, end) && - pack_tlv(NFAPI_CQI_INDICATION_BODY_TAG, &pNfapiMsg->cqi_indication_body, ppWritePackedMsg, end, pack_cqi_indication_body_value) && - pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); - -} - -static uint8_t pack_lbt_pdsch_req_pdu_rel13_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_lbt_pdsch_req_pdu_rel13_t* value = (nfapi_lbt_pdsch_req_pdu_rel13_t*)tlv; - - return ( push32(value->handle, ppWritePackedMsg, end) && - push32(value->mp_cca, ppWritePackedMsg, end) && - push32(value->n_cca, ppWritePackedMsg, end) && - push32(value->offset, ppWritePackedMsg, end) && - push32(value->lte_txop_sf, ppWritePackedMsg, end) && - push16(value->txop_sfn_sf_end, ppWritePackedMsg, end) && - push32(value->lbt_mode, ppWritePackedMsg, end)); -} - -static uint8_t pack_lbt_drs_req_pdu_rel13_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_lbt_drs_req_pdu_rel13_t* value = (nfapi_lbt_drs_req_pdu_rel13_t*)tlv; - - return ( push32(value->handle, ppWritePackedMsg, end) && - push32(value->offset, ppWritePackedMsg, end) && - push16(value->sfn_sf_end, ppWritePackedMsg, end) && - push32(value->lbt_mode, ppWritePackedMsg, end)); -} - -static uint8_t pack_lbt_dl_config_request_body_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_lbt_dl_config_request_body_t* value = (nfapi_lbt_dl_config_request_body_t*)tlv; - - if( push16(value->number_of_pdus, ppWritePackedMsg, end) == 0) - return 0; - - uint16_t i = 0; - uint16_t total_number_of_pdus = value->number_of_pdus; - for(; i < total_number_of_pdus; ++i) - { - nfapi_lbt_dl_config_request_pdu_t* pdu = &(value->lbt_dl_config_req_pdu_list[i]); - - if( push8(pdu->pdu_type, ppWritePackedMsg, end) == 0) - return 0; - - // Put a 0 size in and then determine the size after the pdu - // has been writen and write the calculated size - uint8_t* pWritePackedMsgPduSize = *ppWritePackedMsg; - pdu->pdu_size = 0; - if( push8(pdu->pdu_size, ppWritePackedMsg, end) == 0) - return 0; - - switch(pdu->pdu_type) - { - case NFAPI_LBT_DL_CONFIG_REQUEST_PDSCH_PDU_TYPE: - { - if( pack_tlv(NFAPI_LBT_PDSCH_REQ_PDU_REL13_TAG, &pdu->lbt_pdsch_req_pdu.lbt_pdsch_req_pdu_rel13, ppWritePackedMsg, end, pack_lbt_pdsch_req_pdu_rel13_value) == 0) - return 0; - } - break; - case NFAPI_LBT_DL_CONFIG_REQUEST_DRS_PDU_TYPE: - { - if(pack_tlv(NFAPI_LBT_DRS_REQ_PDU_REL13_TAG, &pdu->lbt_drs_req_pdu.lbt_drs_req_pdu_rel13, ppWritePackedMsg, end, pack_lbt_drs_req_pdu_rel13_value) == 0) - return 0; - } - break; - default: - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "LBT_DL_CONFIG.request invalid pdu type %d \n", pdu->pdu_type ); - } - break; - }; - - // add 1 for the pdu_type. The delta will include the pdu_size - pdu->pdu_size = 1 + (*ppWritePackedMsg - pWritePackedMsgPduSize); - push8(pdu->pdu_size, &pWritePackedMsgPduSize, end); - } - - return 1; -} - -static uint8_t pack_lbt_pdsch_rsp_pdu_rel13_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_lbt_pdsch_rsp_pdu_rel13_t* value = (nfapi_lbt_pdsch_rsp_pdu_rel13_t*)tlv; - - return ( push32(value->handle, ppWritePackedMsg, end) && - push32(value->result, ppWritePackedMsg, end) && - push32(value->lte_txop_symbols, ppWritePackedMsg, end) && - push32(value->initial_partial_sf, ppWritePackedMsg, end)); -} - -static uint8_t pack_lbt_drs_rsp_pdu_rel13_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_lbt_drs_rsp_pdu_rel13_t* value = (nfapi_lbt_drs_rsp_pdu_rel13_t*)tlv; - - return ( push32(value->handle, ppWritePackedMsg, end) && - push32(value->result, ppWritePackedMsg, end)); -} - -static uint8_t pack_lbt_dl_config_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) -{ - nfapi_lbt_dl_config_request_t *pNfapiMsg = (nfapi_lbt_dl_config_request_t*)msg; - - return ( push16(pNfapiMsg->sfn_sf, ppWritePackedMsg, end) && - pack_tlv(NFAPI_LBT_DL_CONFIG_REQUEST_BODY_TAG, &pNfapiMsg->lbt_dl_config_request_body, ppWritePackedMsg, end, &pack_lbt_dl_config_request_body_value) && - pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); -} - -static uint8_t pack_lbt_dl_config_indication_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_lbt_dl_indication_body_t* value = (nfapi_lbt_dl_indication_body_t*)tlv; - - if( push16(value->number_of_pdus, ppWritePackedMsg, end) == 0) - return 0; - - uint16_t i = 0; - uint16_t total_number_of_pdus = value->number_of_pdus; - for(; i < total_number_of_pdus; ++i) - { - nfapi_lbt_dl_indication_pdu_t* pdu = &(value->lbt_indication_pdu_list[i]); - - if( push8(pdu->pdu_type, ppWritePackedMsg, end) == 0) - return 0; - - // Put a 0 size in and then determine the size after the pdu - // has been writen and write the calculated size - uint8_t* pWritePackedMsgPduSize = *ppWritePackedMsg; - pdu->pdu_size = 0; - - if(push8(pdu->pdu_size, ppWritePackedMsg, end) == 0) - return 0; - - switch(pdu->pdu_type) - { - case NFAPI_LBT_DL_RSP_PDSCH_PDU_TYPE: - { - if( pack_tlv(NFAPI_LBT_PDSCH_RSP_PDU_REL13_TAG, &pdu->lbt_pdsch_rsp_pdu.lbt_pdsch_rsp_pdu_rel13, ppWritePackedMsg, end, pack_lbt_pdsch_rsp_pdu_rel13_value) == 0) - return 0; - } - break; - case NFAPI_LBT_DL_RSP_DRS_PDU_TYPE: - { - if( pack_tlv(NFAPI_LBT_DRS_RSP_PDU_REL13_TAG, &pdu->lbt_drs_rsp_pdu.lbt_drs_rsp_pdu_rel13, ppWritePackedMsg, end, pack_lbt_drs_rsp_pdu_rel13_value) == 0) - return 0; - } - break; - default: - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "LBT_DL.indication body invalid pdu type %d \n", pdu->pdu_type ); - } - break; - }; - - // add 1 for the pdu_type. The delta will include the pdu_size - pdu->pdu_size = 1 + (*ppWritePackedMsg - pWritePackedMsgPduSize); - push8(pdu->pdu_size, &pWritePackedMsgPduSize, end); - } - - return 1; -} - -static uint8_t pack_lbt_dl_indication(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) -{ - nfapi_lbt_dl_indication_t *pNfapiMsg = (nfapi_lbt_dl_indication_t*)msg; - - return ( push16(pNfapiMsg->sfn_sf, ppWritePackedMsg, end) && - pack_tlv(NFAPI_LBT_DL_INDICATION_BODY_TAG, &pNfapiMsg->lbt_dl_indication_body, ppWritePackedMsg, end, &pack_lbt_dl_config_indication_value) && - pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); -} - -static uint8_t pack_nb_harq_indication_fdd_rel13_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_nb_harq_indication_fdd_rel13_t* nb_harq_indication_fdd_rel13 = (nfapi_nb_harq_indication_fdd_rel13_t*)tlv; - - return ( push8(nb_harq_indication_fdd_rel13->harq_tb1, ppWritePackedMsg, end) ); -} - -static uint8_t pack_nb_harq_indication_body_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_nb_harq_indication_body_t* value = (nfapi_nb_harq_indication_body_t*)tlv; - - if( push16(value->number_of_harqs, ppWritePackedMsg, end) == 0) - return 0; - - uint16_t i = 0; - uint16_t total_number_of_harqs = value->number_of_harqs; - for(; i < total_number_of_harqs; ++i) - { - nfapi_nb_harq_indication_pdu_t* pdu = &(value->nb_harq_pdu_list[i]); - - uint8_t* instance_length_p = *ppWritePackedMsg; - if(!push16(pdu->instance_length, ppWritePackedMsg, end)) - return 0; - - if(!(pack_tlv(NFAPI_RX_UE_INFORMATION_TAG, &pdu->rx_ue_information, ppWritePackedMsg, end, pack_rx_ue_information_value) && - pack_tlv(NFAPI_NB_HARQ_INDICATION_FDD_REL13_TAG, &pdu->nb_harq_indication_fdd_rel13, ppWritePackedMsg, end, pack_nb_harq_indication_fdd_rel13_value) && - pack_tlv(NFAPI_UL_CQI_INFORMATION_TAG, &pdu->ul_cqi_information, ppWritePackedMsg, end, pack_ul_cqi_information_value))) - return 0; - - // calculate the instance length subtracting the size of the instance - // length feild - uint16_t instance_length = *ppWritePackedMsg - instance_length_p - 2; - push16(instance_length, &instance_length_p, end); - } - - return 1; -} - - -static uint8_t pack_nb_harq_indication(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) -{ - nfapi_nb_harq_indication_t *pNfapiMsg = (nfapi_nb_harq_indication_t*)msg; - - return ( push16(pNfapiMsg->sfn_sf, ppWritePackedMsg, end) && - pack_tlv(NFAPI_NB_HARQ_INDICATION_BODY_TAG, &pNfapiMsg->nb_harq_indication_body, ppWritePackedMsg, end, &pack_nb_harq_indication_body_value) && - pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); -} - -static uint8_t pack_nrach_indication_rel13_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_nrach_indication_pdu_rel13_t* nrach_indication_fdd_rel13 = (nfapi_nrach_indication_pdu_rel13_t*)tlv; - - return ( push16(nrach_indication_fdd_rel13->rnti, ppWritePackedMsg, end) && - push8(nrach_indication_fdd_rel13->initial_sc, ppWritePackedMsg, end) && - push16(nrach_indication_fdd_rel13->timing_advance, ppWritePackedMsg, end) && - push8(nrach_indication_fdd_rel13->nrach_ce_level, ppWritePackedMsg, end)); -} - - -static uint8_t pack_nrach_indication_body_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_nrach_indication_body_t* value = (nfapi_nrach_indication_body_t*)tlv; - - if( push8(value->number_of_initial_scs_detected, ppWritePackedMsg, end) == 0) - return 0; - - uint16_t i = 0; - uint16_t total_number_of_initial_scs_detected = value->number_of_initial_scs_detected; - for(; i < total_number_of_initial_scs_detected; ++i) - { - nfapi_nrach_indication_pdu_t* pdu = &(value->nrach_pdu_list[i]); - - //uint8_t* instance_length_p = *ppWritePackedMsg; - //if(!push16(pdu->instance_length, ppWritePackedMsg, end)) - // return 0; - - if(!(pack_tlv(NFAPI_NRACH_INDICATION_REL13_TAG, &pdu->nrach_indication_rel13, ppWritePackedMsg, end, pack_nrach_indication_rel13_value))) - return 0; - - // calculate the instance length subtracting the size of the instance - // length feild - //uint16_t instance_length = *ppWritePackedMsg - instance_length_p - 2; - //push16(instance_length, &instance_length_p, end); - } - - return 1; -} - -static uint8_t pack_nrach_indication(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) -{ - nfapi_nrach_indication_t *pNfapiMsg = (nfapi_nrach_indication_t*)msg; - - return ( push16(pNfapiMsg->sfn_sf, ppWritePackedMsg, end) && - pack_tlv(NFAPI_NRACH_INDICATION_BODY_TAG, &pNfapiMsg->nrach_indication_body, ppWritePackedMsg, end, &pack_nrach_indication_body_value) && - pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); -} - -static uint8_t pack_nr_dl_node_sync(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) -{ - nfapi_nr_dl_node_sync_t *pNfapiMsg = (nfapi_nr_dl_node_sync_t*)msg; - - return ( push32(pNfapiMsg->t1, ppWritePackedMsg, end) && - pushs32(pNfapiMsg->delta_sfn_slot, ppWritePackedMsg, end) && - pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); -} - -static uint8_t pack_dl_node_sync(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) -{ - nfapi_dl_node_sync_t *pNfapiMsg = (nfapi_dl_node_sync_t*)msg; - - return ( push32(pNfapiMsg->t1, ppWritePackedMsg, end) && - pushs32(pNfapiMsg->delta_sfn_sf, ppWritePackedMsg, end) && - pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); -} - -static uint8_t pack_nr_ul_node_sync(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) -{ - nfapi_nr_ul_node_sync_t *pNfapiMsg = (nfapi_nr_ul_node_sync_t*)msg; - - return (push32(pNfapiMsg->t1, ppWritePackedMsg, end) && - push32(pNfapiMsg->t2, ppWritePackedMsg, end) && - push32(pNfapiMsg->t3, ppWritePackedMsg, end) && - pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); -} - -static uint8_t pack_ul_node_sync(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) -{ - nfapi_ul_node_sync_t *pNfapiMsg = (nfapi_ul_node_sync_t*)msg; - - return (push32(pNfapiMsg->t1, ppWritePackedMsg, end) && - push32(pNfapiMsg->t2, ppWritePackedMsg, end) && - push32(pNfapiMsg->t3, ppWritePackedMsg, end) && - pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); -} - -static uint8_t pack_timing_info(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) -{ - nfapi_timing_info_t *pNfapiMsg = (nfapi_timing_info_t*)msg; - - return (push32(pNfapiMsg->last_sfn_sf, ppWritePackedMsg, end) && - push32(pNfapiMsg->time_since_last_timing_info, ppWritePackedMsg, end) && - push32(pNfapiMsg->dl_config_jitter, ppWritePackedMsg, end) && - push32(pNfapiMsg->tx_request_jitter, ppWritePackedMsg, end) && - push32(pNfapiMsg->ul_config_jitter, ppWritePackedMsg, end) && - push32(pNfapiMsg->hi_dci0_jitter, ppWritePackedMsg, end) && - pushs32(pNfapiMsg->dl_config_latest_delay, ppWritePackedMsg, end) && - pushs32(pNfapiMsg->tx_request_latest_delay, ppWritePackedMsg, end) && - pushs32(pNfapiMsg->ul_config_latest_delay, ppWritePackedMsg, end) && - pushs32(pNfapiMsg->hi_dci0_latest_delay, ppWritePackedMsg, end) && - pushs32(pNfapiMsg->dl_config_earliest_arrival, ppWritePackedMsg, end) && - pushs32(pNfapiMsg->tx_request_earliest_arrival, ppWritePackedMsg, end) && - pushs32(pNfapiMsg->ul_config_earliest_arrival, ppWritePackedMsg, end) && - pushs32(pNfapiMsg->hi_dci0_earliest_arrival, ppWritePackedMsg, end) && - pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); -} - -static uint8_t pack_nr_timing_info(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) -{ - nfapi_nr_timing_info_t *pNfapiMsg = (nfapi_nr_timing_info_t*)msg; - - return (push32(pNfapiMsg->last_sfn, ppWritePackedMsg, end) && - push32(pNfapiMsg->last_slot, ppWritePackedMsg, end) && - push32(pNfapiMsg->time_since_last_timing_info, ppWritePackedMsg, end) && - push32(pNfapiMsg->dl_tti_jitter, ppWritePackedMsg, end) && - push32(pNfapiMsg->tx_data_request_jitter, ppWritePackedMsg, end) && - push32(pNfapiMsg->ul_tti_jitter, ppWritePackedMsg, end) && - push32(pNfapiMsg->ul_dci_jitter, ppWritePackedMsg, end) && - pushs32(pNfapiMsg->dl_tti_latest_delay, ppWritePackedMsg, end) && - pushs32(pNfapiMsg->tx_data_request_latest_delay, ppWritePackedMsg, end) && - pushs32(pNfapiMsg->ul_tti_latest_delay, ppWritePackedMsg, end) && - pushs32(pNfapiMsg->ul_dci_latest_delay, ppWritePackedMsg, end) && - pushs32(pNfapiMsg->dl_tti_earliest_arrival, ppWritePackedMsg, end) && - pushs32(pNfapiMsg->tx_data_request_earliest_arrival, ppWritePackedMsg, end) && - pushs32(pNfapiMsg->ul_tti_earliest_arrival, ppWritePackedMsg, end) && - pushs32(pNfapiMsg->ul_dci_earliest_arrival, ppWritePackedMsg, end) && - pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); -} - - - -// Main pack function - public - -int nfapi_nr_p7_message_pack(void *pMessageBuf, void *pPackedBuf, uint32_t packedBufLen, nfapi_p7_codec_config_t* config) -{ - nfapi_p7_message_header_t *pMessageHeader = pMessageBuf; - uint8_t *pWritePackedMessage = pPackedBuf; - uint8_t *pPackedLengthField = &pWritePackedMessage[4]; - uint8_t *end = pPackedBuf + packedBufLen; - - if (pMessageBuf == NULL || pPackedBuf == NULL) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "P7 Pack supplied pointers are null\n"); - return -1; - } - /* - printf("\n P7 MESSAGE SENT: \n"); - for(int i=0; i< packedBufLen; i++){ - printf("%d", *(uint8_t *)(pMessageBuf + i)); - } - printf("\n"); - */ - // process the header - if(!(push16(pMessageHeader->phy_id, &pWritePackedMessage, end) && - push16(pMessageHeader->message_id, &pWritePackedMessage, end) && - push16(0/*pMessageHeader->message_length*/, &pWritePackedMessage, end) && - push16(pMessageHeader->m_segment_sequence, &pWritePackedMessage, end) && - push32(0/*pMessageHeader->checksum*/, &pWritePackedMessage, end) && - push32(pMessageHeader->transmit_timestamp, &pWritePackedMessage, end))) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "P7 Pack header failed\n"); - return -1; - } - - if (pMessageHeader->message_id != NFAPI_TIMING_INFO) - { - //NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() message_id:0x%04x phy_id:%u m_segment_sequence:%u timestamp:%u\n", __FUNCTION__, pMessageHeader->message_id, pMessageHeader->phy_id, pMessageHeader->m_segment_sequence, pMessageHeader->transmit_timestamp); - } - // look for the specific message - uint8_t result = 0; - switch (pMessageHeader->message_id) - { - case NFAPI_NR_PHY_MSG_TYPE_DL_TTI_REQUEST: - result = pack_dl_tti_request(pMessageHeader, &pWritePackedMessage, end, config); - break; - - case NFAPI_NR_PHY_MSG_TYPE_UL_TTI_REQUEST: - result = pack_ul_tti_request(pMessageHeader, &pWritePackedMessage, end, config); - break; - case NFAPI_NR_PHY_MSG_TYPE_TX_DATA_REQUEST: - result = pack_tx_data_request(pMessageHeader, &pWritePackedMessage, end, config); - break; - case NFAPI_NR_PHY_MSG_TYPE_UL_DCI_REQUEST: - result = pack_ul_dci_request(pMessageHeader, &pWritePackedMessage, end, config); - break; - - case NFAPI_UE_RELEASE_REQUEST: - result =pack_ue_release_request(pMessageHeader, &pWritePackedMessage, end, config); - break; - - case NFAPI_UE_RELEASE_RESPONSE: - result =pack_ue_release_response(pMessageHeader, &pWritePackedMessage, end, config); - break; - - case NFAPI_HARQ_INDICATION: - result = pack_harq_indication(pMessageHeader, &pWritePackedMessage, end, config); - break; - - case NFAPI_CRC_INDICATION: - result = pack_crc_indication(pMessageHeader, &pWritePackedMessage, end, config); - break; - - case NFAPI_RX_ULSCH_INDICATION: - //printf("RX ULSCH\n"); - result = pack_rx_ulsch_indication(pMessageHeader, &pWritePackedMessage, end, config); - break; - - case NFAPI_RACH_INDICATION: - result = pack_rach_indication(pMessageHeader, &pWritePackedMessage, end, config); - break; - - case NFAPI_SRS_INDICATION: - result = pack_srs_indication(pMessageHeader, &pWritePackedMessage, end, config); - break; - - case NFAPI_RX_SR_INDICATION: - result = pack_sr_indication(pMessageHeader, &pWritePackedMessage, end, config); - break; - - case NFAPI_RX_CQI_INDICATION: - result = pack_cqi_indication(pMessageHeader, &pWritePackedMessage, end, config); - break; - - case NFAPI_LBT_DL_CONFIG_REQUEST: - result = pack_lbt_dl_config_request(pMessageHeader, &pWritePackedMessage, end, config); - break; - - case NFAPI_LBT_DL_INDICATION: - result = pack_lbt_dl_indication(pMessageHeader, &pWritePackedMessage, end, config); - break; - - case NFAPI_NB_HARQ_INDICATION: - result = pack_nb_harq_indication(pMessageHeader, &pWritePackedMessage, end, config); - break; - - case NFAPI_NRACH_INDICATION: - result = pack_nrach_indication(pMessageHeader, &pWritePackedMessage, end, config); - break; - - case NFAPI_NR_PHY_MSG_TYPE_DL_NODE_SYNC: - result = pack_nr_dl_node_sync(pMessageHeader, &pWritePackedMessage, end, config); - break; - - case NFAPI_NR_PHY_MSG_TYPE_UL_NODE_SYNC: - result = pack_nr_ul_node_sync(pMessageHeader, &pWritePackedMessage, end, config); - break; - - case NFAPI_TIMING_INFO: - result = pack_nr_timing_info(pMessageHeader, &pWritePackedMessage, end, config); - break; - - default: - { - if(pMessageHeader->message_id >= NFAPI_VENDOR_EXT_MSG_MIN && - pMessageHeader->message_id <= NFAPI_VENDOR_EXT_MSG_MAX) - { - if(config && config->pack_p7_vendor_extension) - { - result = (config->pack_p7_vendor_extension)(pMessageHeader, &pWritePackedMessage, end, config); - } - else - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s VE NFAPI message ID %d. No ve ecoder provided\n", __FUNCTION__, pMessageHeader->message_id); - } - } - else - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s NFAPI Unknown message ID %d\n", __FUNCTION__, pMessageHeader->message_id); - } - } - break; - } - - if(result == 0) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "P7 Pack failed to pack message\n"); - return -1; - } - - // check for a valid message length - uintptr_t msgHead = (uintptr_t)pPackedBuf; - uintptr_t msgEnd = (uintptr_t)pWritePackedMessage; - uint32_t packedMsgLen = msgEnd - msgHead; - uint16_t packedMsgLen16; - if (packedMsgLen > 0xFFFF || packedMsgLen > packedBufLen) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "Packed message length error %d, buffer supplied %d\n", packedMsgLen, packedBufLen); - return -1; - } - else - { - packedMsgLen16 = (uint16_t)packedMsgLen; - } - - // Update the message length in the header - pMessageHeader->message_length = packedMsgLen16; - - if(!push16(packedMsgLen16, &pPackedLengthField, end)) - return -1; - - if(1) - { - //quick test - if(pMessageHeader->message_length != packedMsgLen) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "nfapi packedMsgLen(%d) != message_length(%d) id %d\n", packedMsgLen, pMessageHeader->message_length, pMessageHeader->message_id); - } - } - - return (packedMsgLen); -} - -int nfapi_p7_message_pack(void *pMessageBuf, void *pPackedBuf, uint32_t packedBufLen, nfapi_p7_codec_config_t* config) -{ - nfapi_p7_message_header_t *pMessageHeader = pMessageBuf; - uint8_t *pWritePackedMessage = pPackedBuf; - uint8_t *pPackedLengthField = &pWritePackedMessage[4]; - uint8_t *end = pPackedBuf + packedBufLen; - - if (pMessageBuf == NULL || pPackedBuf == NULL) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "P7 Pack supplied pointers are null\n"); - return -1; - } - /* - printf("\n P7 MESSAGE SENT: \n"); - for(int i=0; i< packedBufLen; i++){ - printf("%d", *(uint8_t *)(pMessageBuf + i)); - } - printf("\n"); - */ - // process the header - if(!(push16(pMessageHeader->phy_id, &pWritePackedMessage, end) && - push16(pMessageHeader->message_id, &pWritePackedMessage, end) && - push16(0/*pMessageHeader->message_length*/, &pWritePackedMessage, end) && - push16(pMessageHeader->m_segment_sequence, &pWritePackedMessage, end) && - push32(0/*pMessageHeader->checksum*/, &pWritePackedMessage, end) && - push32(pMessageHeader->transmit_timestamp, &pWritePackedMessage, end))) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "P7 Pack header failed\n"); - return -1; - } - - if (pMessageHeader->message_id != NFAPI_TIMING_INFO) - { - //NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() message_id:0x%04x phy_id:%u m_segment_sequence:%u timestamp:%u\n", __FUNCTION__, pMessageHeader->message_id, pMessageHeader->phy_id, pMessageHeader->m_segment_sequence, pMessageHeader->transmit_timestamp); - } - // look for the specific message - uint8_t result = 0; - switch (pMessageHeader->message_id) - { - case NFAPI_DL_CONFIG_REQUEST: - //NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() NFAPI_DL_CONFIG_REQUEST\n", __FUNCTION__); - result = pack_dl_config_request(pMessageHeader, &pWritePackedMessage, end, config); - break; - - case NFAPI_UL_CONFIG_REQUEST: - result = pack_ul_config_request(pMessageHeader, &pWritePackedMessage, end, config); - break; - case NFAPI_TX_REQUEST: - //NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() NFAPI_TX_REQUEST\n", __FUNCTION__); - result = pack_tx_request(pMessageHeader, &pWritePackedMessage, end, config); - break; - case NFAPI_HI_DCI0_REQUEST: - result = pack_hi_dci0_request(pMessageHeader, &pWritePackedMessage, end, config); - break; - - case NFAPI_UE_RELEASE_REQUEST: - result =pack_ue_release_request(pMessageHeader, &pWritePackedMessage, end, config); - break; - - case NFAPI_UE_RELEASE_RESPONSE: - result =pack_ue_release_response(pMessageHeader, &pWritePackedMessage, end, config); - break; - - case NFAPI_HARQ_INDICATION: - result = pack_harq_indication(pMessageHeader, &pWritePackedMessage, end, config); - break; - - case NFAPI_CRC_INDICATION: - result = pack_crc_indication(pMessageHeader, &pWritePackedMessage, end, config); - break; - - case NFAPI_RX_ULSCH_INDICATION: - //printf("RX ULSCH\n"); - result = pack_rx_ulsch_indication(pMessageHeader, &pWritePackedMessage, end, config); - break; - - case NFAPI_RACH_INDICATION: - result = pack_rach_indication(pMessageHeader, &pWritePackedMessage, end, config); - break; - - case NFAPI_SRS_INDICATION: - result = pack_srs_indication(pMessageHeader, &pWritePackedMessage, end, config); - break; - - case NFAPI_RX_SR_INDICATION: - result = pack_sr_indication(pMessageHeader, &pWritePackedMessage, end, config); - break; - - case NFAPI_RX_CQI_INDICATION: - result = pack_cqi_indication(pMessageHeader, &pWritePackedMessage, end, config); - break; - - case NFAPI_LBT_DL_CONFIG_REQUEST: - result = pack_lbt_dl_config_request(pMessageHeader, &pWritePackedMessage, end, config); - break; - - case NFAPI_LBT_DL_INDICATION: - result = pack_lbt_dl_indication(pMessageHeader, &pWritePackedMessage, end, config); - break; - - case NFAPI_NB_HARQ_INDICATION: - result = pack_nb_harq_indication(pMessageHeader, &pWritePackedMessage, end, config); - break; - - case NFAPI_NRACH_INDICATION: - result = pack_nrach_indication(pMessageHeader, &pWritePackedMessage, end, config); - break; - - case NFAPI_DL_NODE_SYNC: - result = pack_dl_node_sync(pMessageHeader, &pWritePackedMessage, end, config); - break; - - case NFAPI_UL_NODE_SYNC: - result = pack_ul_node_sync(pMessageHeader, &pWritePackedMessage, end, config); - break; - - case NFAPI_TIMING_INFO: - result = pack_timing_info(pMessageHeader, &pWritePackedMessage, end, config); - break; - - default: - { - if(pMessageHeader->message_id >= NFAPI_VENDOR_EXT_MSG_MIN && - pMessageHeader->message_id <= NFAPI_VENDOR_EXT_MSG_MAX) - { - if(config && config->pack_p7_vendor_extension) - { - result = (config->pack_p7_vendor_extension)(pMessageHeader, &pWritePackedMessage, end, config); - } - else - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s VE NFAPI message ID %d. No ve ecoder provided\n", __FUNCTION__, pMessageHeader->message_id); - } - } - else - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s NFAPI Unknown message ID %d\n", __FUNCTION__, pMessageHeader->message_id); - } - } - break; - } - - if(result == 0) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "P7 Pack failed to pack message\n"); - return -1; - } - - // check for a valid message length - uintptr_t msgHead = (uintptr_t)pPackedBuf; - uintptr_t msgEnd = (uintptr_t)pWritePackedMessage; - uint32_t packedMsgLen = msgEnd - msgHead; - uint16_t packedMsgLen16; - if (packedMsgLen > 0xFFFF || packedMsgLen > packedBufLen) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "Packed message length error %d, buffer supplied %d\n", packedMsgLen, packedBufLen); - return -1; - } - else - { - packedMsgLen16 = (uint16_t)packedMsgLen; - } - - // Update the message length in the header - pMessageHeader->message_length = packedMsgLen16; - - if(!push16(packedMsgLen16, &pPackedLengthField, end)) - return -1; - - if(1) - { - //quick test - if(pMessageHeader->message_length != packedMsgLen) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "nfapi packedMsgLen(%d) != message_length(%d) id %d\n", packedMsgLen, pMessageHeader->message_length, pMessageHeader->message_id); - } - } - - return (packedMsgLen); -} - -// Unpack routines -// NR: -static uint8_t unpack_dl_tti_csi_rs_pdu_rel15_value(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_nr_dl_tti_csi_rs_pdu_rel15_t* value = (nfapi_nr_dl_tti_csi_rs_pdu_rel15_t*)tlv; - - return( - pull16(ppReadPackedMsg, &value->bwp_size, end) && - pull16(ppReadPackedMsg, &value->bwp_start, end) && - - pull8(ppReadPackedMsg, &value->subcarrier_spacing, end) && - pull8(ppReadPackedMsg, &value->cyclic_prefix, end) && - - pull16(ppReadPackedMsg, &value->start_rb, end) && - pull16(ppReadPackedMsg, &value->nr_of_rbs, end) && - - pull8(ppReadPackedMsg, &value->csi_type, end) && - pull8(ppReadPackedMsg, &value->row, end) && - - pull16(ppReadPackedMsg, &value->freq_domain, end) && - pull8(ppReadPackedMsg, &value->symb_l0, end) && - - pull8(ppReadPackedMsg, &value->symb_l1, end) && - pull8(ppReadPackedMsg, &value->cdm_type, end) && - - pull8(ppReadPackedMsg, &value->freq_density, end) && - pull16(ppReadPackedMsg, &value->scramb_id, end) && - - pull8(ppReadPackedMsg, &value->power_control_offset, end) && - pull8(ppReadPackedMsg, &value->power_control_offset_ss, end) - ); - -} - - -static uint8_t unpack_dl_tti_pdcch_pdu_rel15_value(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_nr_dl_tti_pdcch_pdu_rel15_t* value = (nfapi_nr_dl_tti_pdcch_pdu_rel15_t*)tlv; - - for(uint8_t i = 0; i < MAX_DCI_CORESET; ++i) - { - if(!(pull16(ppReadPackedMsg, &value->dci_pdu[i].RNTI, end) && - pull16(ppReadPackedMsg, &value->dci_pdu[i].ScramblingId, end) && - - pull16(ppReadPackedMsg, &value->dci_pdu[i].ScramblingRNTI, end) && - pull8(ppReadPackedMsg, &value->dci_pdu[i].CceIndex, end) && - pull8(ppReadPackedMsg, &value->dci_pdu[i].AggregationLevel, end) && - pull8(ppReadPackedMsg, &value->dci_pdu[i].beta_PDCCH_1_0, end) && - - pull8(ppReadPackedMsg, &value->dci_pdu[i].powerControlOffsetSS, end) && - pull16(ppReadPackedMsg, &value->dci_pdu[i].PayloadSizeBits, end) && - - pullarray8(ppReadPackedMsg, value->dci_pdu[i].Payload, value->dci_pdu[i].PayloadSizeBits, value->dci_pdu[i].PayloadSizeBits, end))) - - return 0; - } - - // TODO: resolve the packaging of array (currently sending a single element) - return( - pull16(ppReadPackedMsg, &value->BWPSize, end) && - pull16(ppReadPackedMsg, &value->BWPStart, end) && - pull8(ppReadPackedMsg, &value->SubcarrierSpacing, end) && - pull8(ppReadPackedMsg, &value->CyclicPrefix, end) && - - pull8(ppReadPackedMsg, &value->StartSymbolIndex, end) && - pull8(ppReadPackedMsg, &value->DurationSymbols, end) && - pullarray8(ppReadPackedMsg, value->FreqDomainResource, 6, 6, end) && - pull8(ppReadPackedMsg, &value->CceRegMappingType, end) && - - pull8(ppReadPackedMsg, &value->RegBundleSize, end) && - pull8(ppReadPackedMsg, &value->InterleaverSize, end) && - pull8(ppReadPackedMsg, &value->CoreSetType, end) && - pull16(ppReadPackedMsg, &value->ShiftIndex, end) && - - pull8(ppReadPackedMsg, &value->precoderGranularity, end) && - pull16(ppReadPackedMsg, &value->numDlDci, end)); - -} - - -static uint8_t unpack_dl_tti_pdsch_pdu_rel15_value(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_nr_dl_tti_pdsch_pdu_rel15_t* value = (nfapi_nr_dl_tti_pdsch_pdu_rel15_t*)tlv; - - // TODO: resolve the packaging of array (currently sending a single element) - return( - pull16(ppReadPackedMsg, &value->pduBitmap, end) && - pull16(ppReadPackedMsg, &value->rnti, end) && - pull16(ppReadPackedMsg, &value->pduIndex, end) && - pull16(ppReadPackedMsg, &value->BWPSize, end) && - - pull16(ppReadPackedMsg, &value->BWPStart, end) && - pull8(ppReadPackedMsg, &value->SubcarrierSpacing, end) && - pull8(ppReadPackedMsg, &value->CyclicPrefix, end) && - pull8(ppReadPackedMsg, &value->NrOfCodewords, end) && - - pullarray16(ppReadPackedMsg, value->targetCodeRate, 2, 1, end) && - pullarray8(ppReadPackedMsg, value->qamModOrder, 2, 1, end) && - pullarray8(ppReadPackedMsg, value->mcsIndex, 2, 1, end) && - pullarray8(ppReadPackedMsg, value->mcsTable, 2, 1, end) && - - pullarray8(ppReadPackedMsg, value->rvIndex, 2, 1, end) && - pullarray32(ppReadPackedMsg, value->TBSize, 2, 1, end) && - pull16(ppReadPackedMsg, &value->dataScramblingId, end) && - pull8(ppReadPackedMsg, &value->nrOfLayers, end) && - - pull8(ppReadPackedMsg, &value->transmissionScheme, end) && - pull8(ppReadPackedMsg, &value->refPoint, end) && - pull16(ppReadPackedMsg, &value->dlDmrsSymbPos, end) && - pull8(ppReadPackedMsg, &value->dmrsConfigType, end) && - - pull16(ppReadPackedMsg, &value->dlDmrsScramblingId, end) && - pull8(ppReadPackedMsg, &value->SCID, end) && - pull8(ppReadPackedMsg, &value->numDmrsCdmGrpsNoData, end) && - pull16(ppReadPackedMsg, &value->dmrsPorts, end) && - - pull8(ppReadPackedMsg, &value->resourceAlloc, end) && - pull16(ppReadPackedMsg, &value->rbStart, end) && - pull16(ppReadPackedMsg, &value->rbSize, end) && - - pull8(ppReadPackedMsg, &value->VRBtoPRBMapping, end) && - pull8(ppReadPackedMsg, &value->StartSymbolIndex, end) && - pull8(ppReadPackedMsg, &value->NrOfSymbols, end) && - pull8(ppReadPackedMsg, &value->PTRSPortIndex, end) && - - pull8(ppReadPackedMsg, &value->PTRSTimeDensity, end) && - pull8(ppReadPackedMsg, &value->PTRSFreqDensity, end) && - pull8(ppReadPackedMsg, &value->PTRSReOffset, end) - ); - -} - - -static uint8_t unpack_dl_tti_ssb_pdu_rel15_value(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - printf("ssb received and unpacked. \n"); - nfapi_nr_dl_tti_ssb_pdu_rel15_t* value = (nfapi_nr_dl_tti_ssb_pdu_rel15_t*)tlv; - - return( - pull16(ppReadPackedMsg, &value->PhysCellId, end) && - pull8(ppReadPackedMsg, &value->BetaPss, end) && - pull8(ppReadPackedMsg, &value->SsbBlockIndex, end) && - pull8(ppReadPackedMsg, &value->SsbSubcarrierOffset, end) && - pull16(ppReadPackedMsg, &value->ssbOffsetPointA, end) && - pull8(ppReadPackedMsg, &value->bchPayloadFlag, end) && - pull32(ppReadPackedMsg, &value->bchPayload, end) - // TODO: pack precoding_and_beamforming too - ); - -} - - -// LTE: -static uint8_t unpack_dl_config_dci_dl_pdu_rel8_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_dl_config_dci_dl_pdu_rel8_t* dci_dl_pdu_rel8 = (nfapi_dl_config_dci_dl_pdu_rel8_t*)tlv; - - return (pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->dci_format, end) && - pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->cce_idx, end) && - pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->aggregation_level, end) && - pull16(ppReadPackedMsg, &dci_dl_pdu_rel8->rnti, end) && - pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->resource_allocation_type, end) && - pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->virtual_resource_block_assignment_flag, end) && - pull32(ppReadPackedMsg, &dci_dl_pdu_rel8->resource_block_coding, end) && - pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->mcs_1, end) && - pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->redundancy_version_1, end) && - pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->new_data_indicator_1, end) && - pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->transport_block_to_codeword_swap_flag, end) && - pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->mcs_2, end) && - pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->redundancy_version_2, end) && - pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->new_data_indicator_2, end) && - pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->harq_process, end) && - pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->tpmi, end) && - pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->pmi, end) && - pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->precoding_information, end) && - pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->tpc, end) && - pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->downlink_assignment_index, end) && - pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->ngap, end) && - pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->transport_block_size_index, end) && - pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->downlink_power_offset, end) && - pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->allocate_prach_flag, end) && - pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->preamble_index, end) && - pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->prach_mask_index, end) && - pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->rnti_type, end) && - pull16(ppReadPackedMsg, &dci_dl_pdu_rel8->transmission_power, end)); - -} - -static uint8_t unpack_dl_config_dci_dl_pdu_rel9_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_dl_config_dci_dl_pdu_rel9_t* dci_dl_pdu_rel9 = (nfapi_dl_config_dci_dl_pdu_rel9_t*)tlv; - - return ( pull8(ppReadPackedMsg, &dci_dl_pdu_rel9->mcch_flag, end) && - pull8(ppReadPackedMsg, &dci_dl_pdu_rel9->mcch_change_notification, end) && - pull8(ppReadPackedMsg, &dci_dl_pdu_rel9->scrambling_identity, end)); -} - -static uint8_t unpack_dl_config_dci_dl_pdu_rel10_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_dl_config_dci_dl_pdu_rel10_t* dci_dl_pdu_rel10 = (nfapi_dl_config_dci_dl_pdu_rel10_t*)tlv; - - return (pull8(ppReadPackedMsg, &dci_dl_pdu_rel10->cross_carrier_scheduling_flag, end) && - pull8(ppReadPackedMsg, &dci_dl_pdu_rel10->carrier_indicator, end) && - pull8(ppReadPackedMsg, &dci_dl_pdu_rel10->srs_flag, end) && - pull8(ppReadPackedMsg, &dci_dl_pdu_rel10->srs_request, end) && - pull8(ppReadPackedMsg, &dci_dl_pdu_rel10->antenna_ports_scrambling_and_layers, end) && - pull8(ppReadPackedMsg, &dci_dl_pdu_rel10->total_dci_length_including_padding, end) && - pull8(ppReadPackedMsg, &dci_dl_pdu_rel10->n_dl_rb, end)); -} - -static uint8_t unpack_dl_config_dci_dl_pdu_rel11_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_dl_config_dci_dl_pdu_rel11_t* dci_dl_pdu_rel11 = (nfapi_dl_config_dci_dl_pdu_rel11_t*)tlv; - - return (pull8(ppReadPackedMsg, &dci_dl_pdu_rel11->harq_ack_resource_offset, end) && - pull8(ppReadPackedMsg, &dci_dl_pdu_rel11->pdsch_re_mapping_quasi_co_location_indicator, end)); -} - -static uint8_t unpack_dl_config_dci_dl_pdu_rel12_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_dl_config_dci_dl_pdu_rel12_t* dci_dl_pdu_rel12 = (nfapi_dl_config_dci_dl_pdu_rel12_t*)tlv; - - return (pull8(ppReadPackedMsg, &dci_dl_pdu_rel12->primary_cell_type, end) && - pull8(ppReadPackedMsg, &dci_dl_pdu_rel12->ul_dl_configuration_flag, end) && - pull8(ppReadPackedMsg, &dci_dl_pdu_rel12->number_ul_dl_configurations, end) && - pullarray8(ppReadPackedMsg, dci_dl_pdu_rel12->ul_dl_configuration_indication, NFAPI_MAX_UL_DL_CONFIGURATIONS, dci_dl_pdu_rel12->number_ul_dl_configurations, end)); -} - -static uint8_t unpack_tpm_value(uint8_t **ppReadPackedMsg, nfapi_dl_config_dci_dl_tpm_t *value, uint8_t *end) -{ - if(!(pull8(ppReadPackedMsg, &value->num_prb_per_subband, end) && - pull8(ppReadPackedMsg, &value->number_of_subbands, end) && - pull8(ppReadPackedMsg, &value->num_antennas, end))) - return 0; - - - uint8_t idx = 0; - for(idx = 0; idx < value->number_of_subbands; ++idx) - { - nfapi_dl_config_dci_dl_tpm_subband_info_t* subband_info = &(value->subband_info[idx]); - - if(!(pull8(ppReadPackedMsg, &subband_info->subband_index, end) && - pull8(ppReadPackedMsg, &subband_info->scheduled_ues, end))) - return 0; - - uint8_t antenna_idx = 0; - uint8_t scheduled_ue_idx = 0; - - for(antenna_idx = 0; antenna_idx < value->num_antennas; ++antenna_idx) - { - for(scheduled_ue_idx = 0; scheduled_ue_idx < subband_info->scheduled_ues; ++scheduled_ue_idx) - { - if(!pull16(ppReadPackedMsg, &(subband_info->precoding_value[antenna_idx][scheduled_ue_idx]), end)) - return 0; - } - } - - } - - - return 1; - -} - - -static uint8_t unpack_dl_config_dci_dl_pdu_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_dl_config_dci_dl_pdu_rel13_t* dci_dl_pdu_rel13 = (nfapi_dl_config_dci_dl_pdu_rel13_t*)tlv; - - // If the length is greater than 5 then the TPM struct flag and possiably the TPM structure have been - // added - uint8_t tpm_struct_flag_present = dci_dl_pdu_rel13->tl.length > 5; - dci_dl_pdu_rel13->tpm_struct_flag = 0; - - return (pull8(ppReadPackedMsg, &dci_dl_pdu_rel13->laa_end_partial_sf_flag, end) && - pull8(ppReadPackedMsg, &dci_dl_pdu_rel13->laa_end_partial_sf_configuration, end) && - pull8(ppReadPackedMsg, &dci_dl_pdu_rel13->initial_lbt_sf, end) && - pull8(ppReadPackedMsg, &dci_dl_pdu_rel13->codebook_size_determination, end) && - pull8(ppReadPackedMsg, &dci_dl_pdu_rel13->drms_table_flag, end) && - ( (tpm_struct_flag_present == 1) ? pull8(ppReadPackedMsg, &dci_dl_pdu_rel13->tpm_struct_flag, end) : 1) && - ( (tpm_struct_flag_present == 1 && dci_dl_pdu_rel13->tpm_struct_flag == 1) ? unpack_tpm_value(ppReadPackedMsg, &dci_dl_pdu_rel13->tpm, end) : 1)); - -} - -static uint8_t unpack_dl_config_bch_pdu_rel8_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_dl_config_bch_pdu_rel8_t* bch_pdu_rel8 = (nfapi_dl_config_bch_pdu_rel8_t*)tlv; - - return ( pull16(ppReadPackedMsg, &bch_pdu_rel8->length, end) && - pull16(ppReadPackedMsg, (uint16_t *)&bch_pdu_rel8->pdu_index, end) && - pull16(ppReadPackedMsg, &bch_pdu_rel8->transmission_power, end)); -} - -static uint8_t unpack_dl_config_mch_pdu_rel8_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_dl_config_mch_pdu_rel8_t* mch_pdu_rel8 = (nfapi_dl_config_mch_pdu_rel8_t*)tlv; - - return (pull16(ppReadPackedMsg, &mch_pdu_rel8->length, end) && - pull16(ppReadPackedMsg, (uint16_t *)&mch_pdu_rel8->pdu_index, end) && - pull16(ppReadPackedMsg, &mch_pdu_rel8->rnti, end) && - pull8(ppReadPackedMsg, &mch_pdu_rel8->resource_allocation_type, end) && - pull32(ppReadPackedMsg, &mch_pdu_rel8->resource_block_coding, end) && - pull8(ppReadPackedMsg, &mch_pdu_rel8->modulation, end) && - pull16(ppReadPackedMsg, &mch_pdu_rel8->transmission_power, end) && - pull16(ppReadPackedMsg, &mch_pdu_rel8->mbsfn_area_id, end)); -} - -static uint8_t unpack_dl_config_dlsch_pdu_rel8_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_dl_config_dlsch_pdu_rel8_t* dlsch_pdu_rel8 = (nfapi_dl_config_dlsch_pdu_rel8_t*)tlv; - - if (!(pull16(ppReadPackedMsg, &dlsch_pdu_rel8->length, end) && - pull16(ppReadPackedMsg, (uint16_t *)&dlsch_pdu_rel8->pdu_index, end) && - pull16(ppReadPackedMsg, &dlsch_pdu_rel8->rnti, end) && - pull8(ppReadPackedMsg, &dlsch_pdu_rel8->resource_allocation_type, end) && - pull8(ppReadPackedMsg, &dlsch_pdu_rel8->virtual_resource_block_assignment_flag, end) && - pull32(ppReadPackedMsg, &dlsch_pdu_rel8->resource_block_coding, end) && - pull8(ppReadPackedMsg, &dlsch_pdu_rel8->modulation, end) && - pull8(ppReadPackedMsg, &dlsch_pdu_rel8->redundancy_version, end) && - pull8(ppReadPackedMsg, &dlsch_pdu_rel8->transport_blocks, end) && - pull8(ppReadPackedMsg, &dlsch_pdu_rel8->transport_block_to_codeword_swap_flag, end) && - pull8(ppReadPackedMsg, &dlsch_pdu_rel8->transmission_scheme, end) && - pull8(ppReadPackedMsg, &dlsch_pdu_rel8->number_of_layers, end) && - pull8(ppReadPackedMsg, &dlsch_pdu_rel8->number_of_subbands, end) && - pullarray8(ppReadPackedMsg, dlsch_pdu_rel8->codebook_index, NFAPI_MAX_NUM_SUBBANDS, dlsch_pdu_rel8->number_of_subbands, end) && - pull8(ppReadPackedMsg, &dlsch_pdu_rel8->ue_category_capacity, end) && - pull8(ppReadPackedMsg, &dlsch_pdu_rel8->pa, end) && - pull8(ppReadPackedMsg, &dlsch_pdu_rel8->delta_power_offset_index, end) && - pull8(ppReadPackedMsg, &dlsch_pdu_rel8->ngap, end) && - pull8(ppReadPackedMsg, &dlsch_pdu_rel8->nprb, end) && - pull8(ppReadPackedMsg, &dlsch_pdu_rel8->transmission_mode, end) && - pull8(ppReadPackedMsg, &dlsch_pdu_rel8->num_bf_prb_per_subband, end) && - pull8(ppReadPackedMsg, &dlsch_pdu_rel8->num_bf_vector, end))) - return 0; - - uint16_t j = 0; - for(j = 0; j < dlsch_pdu_rel8->num_bf_vector; ++j) - { - if(!(pull8(ppReadPackedMsg, &dlsch_pdu_rel8->bf_vector[j].subband_index, end) && - pull8(ppReadPackedMsg, &dlsch_pdu_rel8->bf_vector[j].num_antennas, end) && - pullarray16(ppReadPackedMsg, dlsch_pdu_rel8->bf_vector[j].bf_value, NFAPI_MAX_NUM_ANTENNAS, dlsch_pdu_rel8->bf_vector[j].num_antennas, end))) - return 0; - } - return 1; -} -static uint8_t unpack_dl_config_dlsch_pdu_rel9_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_dl_config_dlsch_pdu_rel9_t* dlsch_pdu_rel9 = (nfapi_dl_config_dlsch_pdu_rel9_t*)tlv; - return ( pull8(ppReadPackedMsg, &dlsch_pdu_rel9->nscid, end) ); -} -static uint8_t unpack_dl_config_dlsch_pdu_rel10_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_dl_config_dlsch_pdu_rel10_t* dlsch_pdu_rel10 = (nfapi_dl_config_dlsch_pdu_rel10_t*)tlv; - - return ( pull8(ppReadPackedMsg, &dlsch_pdu_rel10->csi_rs_flag, end) && - pull8(ppReadPackedMsg, &dlsch_pdu_rel10->csi_rs_resource_config_r10, end) && - pull16(ppReadPackedMsg, &dlsch_pdu_rel10->csi_rs_zero_tx_power_resource_config_bitmap_r10, end) && - pull8(ppReadPackedMsg, &dlsch_pdu_rel10->csi_rs_number_nzp_configuration, end) && - pullarray8(ppReadPackedMsg, dlsch_pdu_rel10->csi_rs_resource_config, NFAPI_MAX_CSI_RS_RESOURCE_CONFIG, dlsch_pdu_rel10->csi_rs_number_nzp_configuration, end) && - pull8(ppReadPackedMsg, &dlsch_pdu_rel10->pdsch_start, end)) ; -} -static uint8_t unpack_dl_config_dlsch_pdu_rel11_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_dl_config_dlsch_pdu_rel11_t* dlsch_pdu_rel11 = (nfapi_dl_config_dlsch_pdu_rel11_t*)tlv; - - return ( pull8(ppReadPackedMsg, &dlsch_pdu_rel11->drms_config_flag, end) && - pull16(ppReadPackedMsg, &dlsch_pdu_rel11->drms_scrambling, end) && - pull8(ppReadPackedMsg, &dlsch_pdu_rel11->csi_config_flag, end) && - pull16(ppReadPackedMsg, &dlsch_pdu_rel11->csi_scrambling, end) && - pull8(ppReadPackedMsg, &dlsch_pdu_rel11->pdsch_re_mapping_flag, end) && - pull8(ppReadPackedMsg, &dlsch_pdu_rel11->pdsch_re_mapping_atenna_ports, end) && - pull8(ppReadPackedMsg, &dlsch_pdu_rel11->pdsch_re_mapping_freq_shift, end)); -} -static uint8_t unpack_dl_config_dlsch_pdu_rel12_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_dl_config_dlsch_pdu_rel12_t* dlsch_pdu_rel12 = (nfapi_dl_config_dlsch_pdu_rel12_t*)tlv; - - return ( pull8(ppReadPackedMsg, &dlsch_pdu_rel12->altcqi_table_r12, end) && - pull8(ppReadPackedMsg, &dlsch_pdu_rel12->maxlayers, end) && - pull8(ppReadPackedMsg, &dlsch_pdu_rel12->n_dl_harq, end)); -} -static uint8_t unpack_dl_config_dlsch_pdu_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_dl_config_dlsch_pdu_rel13_t* dlsch_pdu_rel13 = (nfapi_dl_config_dlsch_pdu_rel13_t*)tlv; - - return ( pull8(ppReadPackedMsg, &dlsch_pdu_rel13->dwpts_symbols, end) && - pull8(ppReadPackedMsg, &dlsch_pdu_rel13->initial_lbt_sf, end) && - pull8(ppReadPackedMsg, &dlsch_pdu_rel13->ue_type, end) && - pull8(ppReadPackedMsg, &dlsch_pdu_rel13->pdsch_payload_type, end) && - pull16(ppReadPackedMsg, &dlsch_pdu_rel13->initial_transmission_sf_io, end) && - pull8(ppReadPackedMsg, &dlsch_pdu_rel13->drms_table_flag, end)); -} - -static uint8_t unpack_dl_config_pch_pdu_rel8_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_dl_config_pch_pdu_rel8_t* pch_pdu_rel8 = (nfapi_dl_config_pch_pdu_rel8_t*)tlv; - - return ( pull16(ppReadPackedMsg, &pch_pdu_rel8->length, end) && - pull16(ppReadPackedMsg, (uint16_t *)&pch_pdu_rel8->pdu_index, end) && - pull16(ppReadPackedMsg, &pch_pdu_rel8->p_rnti, end) && - pull8(ppReadPackedMsg, &pch_pdu_rel8->resource_allocation_type, end) && - pull8(ppReadPackedMsg, &pch_pdu_rel8->virtual_resource_block_assignment_flag, end) && - pull32(ppReadPackedMsg, &pch_pdu_rel8->resource_block_coding, end) && - pull8(ppReadPackedMsg, &pch_pdu_rel8->mcs, end) && - pull8(ppReadPackedMsg, &pch_pdu_rel8->redundancy_version, end) && - pull8(ppReadPackedMsg, &pch_pdu_rel8->number_of_transport_blocks, end) && - pull8(ppReadPackedMsg, &pch_pdu_rel8->transport_block_to_codeword_swap_flag, end) && - pull8(ppReadPackedMsg, &pch_pdu_rel8->transmission_scheme, end) && - pull8(ppReadPackedMsg, &pch_pdu_rel8->number_of_layers, end) && - pull8(ppReadPackedMsg, &pch_pdu_rel8->codebook_index, end) && - pull8(ppReadPackedMsg, &pch_pdu_rel8->ue_category_capacity, end) && - pull8(ppReadPackedMsg, &pch_pdu_rel8->pa, end) && - pull16(ppReadPackedMsg, &pch_pdu_rel8->transmission_power, end) && - pull8(ppReadPackedMsg, &pch_pdu_rel8->nprb, end) && - pull8(ppReadPackedMsg, &pch_pdu_rel8->ngap, end)); -} -static uint8_t unpack_dl_config_pch_pdu_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_dl_config_pch_pdu_rel13_t* pch_pdu_rel13 = (nfapi_dl_config_pch_pdu_rel13_t*)tlv; - - return ( pull8(ppReadPackedMsg, &pch_pdu_rel13->ue_mode, end) && - pull16(ppReadPackedMsg, &pch_pdu_rel13->initial_transmission_sf_io, end)); -} - -static uint8_t unpack_dl_config_prs_pdu_rel9_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_dl_config_prs_pdu_rel9_t* prs_pdu_rel9 = (nfapi_dl_config_prs_pdu_rel9_t*)tlv; - - return ( pull16(ppReadPackedMsg, &prs_pdu_rel9->transmission_power, end) && - pull8(ppReadPackedMsg, &prs_pdu_rel9->prs_bandwidth, end) && - pull8(ppReadPackedMsg, &prs_pdu_rel9->prs_cyclic_prefix_type, end) && - pull8(ppReadPackedMsg, &prs_pdu_rel9->prs_muting, end)); -} - -static uint8_t unpack_dl_config_csi_rs_pdu_rel10_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_dl_config_csi_rs_pdu_rel10_t* csi_rs_pdu_rel10 = (nfapi_dl_config_csi_rs_pdu_rel10_t*)tlv; - - return ( pull8(ppReadPackedMsg, &csi_rs_pdu_rel10->csi_rs_antenna_port_count_r10, end) && - pull8(ppReadPackedMsg, &csi_rs_pdu_rel10->csi_rs_resource_config_r10, end) && - pull16(ppReadPackedMsg, &csi_rs_pdu_rel10->transmission_power, end) && - pull16(ppReadPackedMsg, &csi_rs_pdu_rel10->csi_rs_zero_tx_power_resource_config_bitmap_r10, end) && - pull8(ppReadPackedMsg, &csi_rs_pdu_rel10->csi_rs_number_of_nzp_configuration, end) && - pullarray8(ppReadPackedMsg, csi_rs_pdu_rel10->csi_rs_resource_config, NFAPI_MAX_CSI_RS_RESOURCE_CONFIG, csi_rs_pdu_rel10->csi_rs_number_of_nzp_configuration, end)); -} - -static uint8_t unpack_dl_config_csi_rs_pdu_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_dl_config_csi_rs_pdu_rel13_t* csi_rs_pdu_rel13 = (nfapi_dl_config_csi_rs_pdu_rel13_t*)tlv; - - if (!(pull8(ppReadPackedMsg, &csi_rs_pdu_rel13->csi_rs_class, end) && - pull8(ppReadPackedMsg, &csi_rs_pdu_rel13->cdm_type, end) && - pull8(ppReadPackedMsg, &csi_rs_pdu_rel13->num_bf_vector, end))) - return 0; - - - uint16_t idx =0; - for(idx = 0; idx < csi_rs_pdu_rel13->num_bf_vector; ++idx) - { - if(!(pull8(ppReadPackedMsg, &csi_rs_pdu_rel13->bf_vector[idx].csi_rs_resource_index, end))) - return 0; - NFAPI_TRACE(NFAPI_TRACE_ERROR, "FIXME : HOW TO DECODE BF VALUE \n"); - //pullarray16(ppReadPackedMsg, &csi_rs_pdu_rel13->bf_vector[idx].bf_vector, ??); - } - return 1; -} - -static uint8_t unpack_dl_config_epdcch_params_rel11_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_dl_config_epdcch_parameters_rel11_t* epdcch_params_rel11 = (nfapi_dl_config_epdcch_parameters_rel11_t*)tlv; - - return (pull8(ppReadPackedMsg, &epdcch_params_rel11->epdcch_resource_assignment_flag, end) && - pull16(ppReadPackedMsg, &epdcch_params_rel11->epdcch_id, end) && - pull8(ppReadPackedMsg, &epdcch_params_rel11->epdcch_start_symbol, end) && - pull8(ppReadPackedMsg, &epdcch_params_rel11->epdcch_num_prb, end) && - pullarray8(ppReadPackedMsg, epdcch_params_rel11->epdcch_prb_index, NFAPI_MAX_EPDCCH_PRB, epdcch_params_rel11->epdcch_num_prb, end) && - pull8(ppReadPackedMsg, &epdcch_params_rel11->bf_vector.subband_index, end) && - pull8(ppReadPackedMsg, &epdcch_params_rel11->bf_vector.num_antennas, end) && - pullarray16(ppReadPackedMsg, epdcch_params_rel11->bf_vector.bf_value, NFAPI_MAX_NUM_ANTENNAS, epdcch_params_rel11->bf_vector.num_antennas, end)); -} - -static uint8_t unpack_dl_config_epdcch_params_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_dl_config_epdcch_parameters_rel13_t* epdcch_params_rel13 = (nfapi_dl_config_epdcch_parameters_rel13_t*)tlv; - - return ( pull8(ppReadPackedMsg, &epdcch_params_rel13->dwpts_symbols, end) && - pull8(ppReadPackedMsg, &epdcch_params_rel13->initial_lbt_sf, end)); -} - -static uint8_t unpack_dl_config_mpdcch_pdu_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_dl_config_mpdcch_pdu_rel13_t* mpdcch_params_rel13 = (nfapi_dl_config_mpdcch_pdu_rel13_t*)tlv; - - - return ( pull8(ppReadPackedMsg, &mpdcch_params_rel13->mpdcch_narrow_band, end) && - pull8(ppReadPackedMsg, &mpdcch_params_rel13->number_of_prb_pairs, end) && - pull8(ppReadPackedMsg, &mpdcch_params_rel13->resource_block_assignment, end) && - pull8(ppReadPackedMsg, &mpdcch_params_rel13->mpdcch_tansmission_type, end) && - pull8(ppReadPackedMsg, &mpdcch_params_rel13->start_symbol, end) && - pull8(ppReadPackedMsg, &mpdcch_params_rel13->ecce_index, end) && - pull8(ppReadPackedMsg, &mpdcch_params_rel13->aggregation_level, end) && - pull8(ppReadPackedMsg, &mpdcch_params_rel13->rnti_type, end) && - pull16(ppReadPackedMsg, &mpdcch_params_rel13->rnti, end) && - pull8(ppReadPackedMsg, &mpdcch_params_rel13->ce_mode, end) && - pull16(ppReadPackedMsg, &mpdcch_params_rel13->drms_scrambling_init, end) && - pull16(ppReadPackedMsg, &mpdcch_params_rel13->initial_transmission_sf_io, end) && - pull16(ppReadPackedMsg, &mpdcch_params_rel13->transmission_power, end) && - pull8(ppReadPackedMsg, &mpdcch_params_rel13->dci_format, end) && - pull16(ppReadPackedMsg, &mpdcch_params_rel13->resource_block_coding, end) && - pull8(ppReadPackedMsg, &mpdcch_params_rel13->mcs, end) && - pull8(ppReadPackedMsg, &mpdcch_params_rel13->pdsch_reptition_levels, end) && - pull8(ppReadPackedMsg, &mpdcch_params_rel13->redundancy_version, end) && - pull8(ppReadPackedMsg, &mpdcch_params_rel13->new_data_indicator, end) && - pull8(ppReadPackedMsg, &mpdcch_params_rel13->harq_process, end) && - pull8(ppReadPackedMsg, &mpdcch_params_rel13->tpmi_length, end) && - pull8(ppReadPackedMsg, &mpdcch_params_rel13->tpmi, end) && - pull8(ppReadPackedMsg, &mpdcch_params_rel13->pmi_flag, end) && - pull8(ppReadPackedMsg, &mpdcch_params_rel13->pmi, end) && - pull8(ppReadPackedMsg, &mpdcch_params_rel13->harq_resource_offset, end) && - pull8(ppReadPackedMsg, &mpdcch_params_rel13->dci_subframe_repetition_number, end) && - pull8(ppReadPackedMsg, &mpdcch_params_rel13->tpc, end) && - pull8(ppReadPackedMsg, &mpdcch_params_rel13->downlink_assignment_index_length, end) && - pull8(ppReadPackedMsg, &mpdcch_params_rel13->downlink_assignment_index, end) && - pull8(ppReadPackedMsg, &mpdcch_params_rel13->allocate_prach_flag, end) && - pull8(ppReadPackedMsg, &mpdcch_params_rel13->preamble_index, end) && - pull8(ppReadPackedMsg, &mpdcch_params_rel13->prach_mask_index, end) && - pull8(ppReadPackedMsg, &mpdcch_params_rel13->starting_ce_level, end) && - pull8(ppReadPackedMsg, &mpdcch_params_rel13->srs_request, end) && - pull8(ppReadPackedMsg, &mpdcch_params_rel13->antenna_ports_and_scrambling_identity_flag, end) && - pull8(ppReadPackedMsg, &mpdcch_params_rel13->antenna_ports_and_scrambling_identity, end) && - pull8(ppReadPackedMsg, &mpdcch_params_rel13->frequency_hopping_enabled_flag, end) && - pull8(ppReadPackedMsg, &mpdcch_params_rel13->paging_direct_indication_differentiation_flag, end) && - pull8(ppReadPackedMsg, &mpdcch_params_rel13->direct_indication, end) && - pull8(ppReadPackedMsg, &mpdcch_params_rel13->total_dci_length_including_padding, end) && - pull8(ppReadPackedMsg, &mpdcch_params_rel13->number_of_tx_antenna_ports, end) && - pullarray16(ppReadPackedMsg, mpdcch_params_rel13->precoding_value, NFAPI_MAX_TX_PHYSICAL_ANTENNA_PORTS, mpdcch_params_rel13->number_of_tx_antenna_ports, end)); -} - - -static uint8_t unpack_dl_config_nbch_pdu_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_dl_config_nbch_pdu_rel13_t* nbch_params_rel13 = (nfapi_dl_config_nbch_pdu_rel13_t*)tlv; - - return ( pull16(ppReadPackedMsg, &nbch_params_rel13->length, end) && - pull16(ppReadPackedMsg, (uint16_t *)&nbch_params_rel13->pdu_index, end) && - pull16(ppReadPackedMsg, &nbch_params_rel13->transmission_power, end) && - pull16(ppReadPackedMsg, &nbch_params_rel13->hyper_sfn_2_lsbs, end)); -} - -static uint8_t unpack_dl_config_npdcch_pdu_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_dl_config_npdcch_pdu_rel13_t* npdcch_params_rel13 = (nfapi_dl_config_npdcch_pdu_rel13_t*)tlv; - - return ( pull16(ppReadPackedMsg, &npdcch_params_rel13->length, end) && - pull16(ppReadPackedMsg, (uint16_t *)&npdcch_params_rel13->pdu_index, end) && - pull8(ppReadPackedMsg, &npdcch_params_rel13->ncce_index, end) && - pull8(ppReadPackedMsg, &npdcch_params_rel13->aggregation_level, end) && - pull8(ppReadPackedMsg, &npdcch_params_rel13->start_symbol, end) && - pull8(ppReadPackedMsg, &npdcch_params_rel13->rnti_type, end) && - pull16(ppReadPackedMsg, &npdcch_params_rel13->rnti, end) && - pull8(ppReadPackedMsg, &npdcch_params_rel13->scrambling_reinitialization_batch_index, end) && - pull8(ppReadPackedMsg, &npdcch_params_rel13->nrs_antenna_ports_assumed_by_the_ue, end) && - pull8(ppReadPackedMsg, &npdcch_params_rel13->dci_format, end) && - pull8(ppReadPackedMsg, &npdcch_params_rel13->scheduling_delay, end) && - pull8(ppReadPackedMsg, &npdcch_params_rel13->resource_assignment, end) && - pull8(ppReadPackedMsg, &npdcch_params_rel13->repetition_number, end) && - pull8(ppReadPackedMsg, &npdcch_params_rel13->mcs, end) && - pull8(ppReadPackedMsg, &npdcch_params_rel13->new_data_indicator, end) && - pull8(ppReadPackedMsg, &npdcch_params_rel13->harq_ack_resource, end) && - pull8(ppReadPackedMsg, &npdcch_params_rel13->npdcch_order_indication, end) && - pull8(ppReadPackedMsg, &npdcch_params_rel13->starting_number_of_nprach_repetitions, end) && - pull8(ppReadPackedMsg, &npdcch_params_rel13->subcarrier_indication_of_nprach, end) && - pull8(ppReadPackedMsg, &npdcch_params_rel13->paging_direct_indication_differentation_flag, end) && - pull8(ppReadPackedMsg, &npdcch_params_rel13->direct_indication, end) && - pull8(ppReadPackedMsg, &npdcch_params_rel13->dci_subframe_repetition_number, end) && - pull8(ppReadPackedMsg, &npdcch_params_rel13->total_dci_length_including_padding, end)); -} - -static uint8_t unpack_dl_config_ndlsch_pdu_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_dl_config_ndlsch_pdu_rel13_t* ndlsch_params_rel13 = (nfapi_dl_config_ndlsch_pdu_rel13_t*)tlv; - - return ( pull16(ppReadPackedMsg, &ndlsch_params_rel13->length, end) && - pull16(ppReadPackedMsg, (uint16_t *)&ndlsch_params_rel13->pdu_index, end) && - pull8(ppReadPackedMsg, &ndlsch_params_rel13->start_symbol, end) && - pull8(ppReadPackedMsg, &ndlsch_params_rel13->rnti_type, end) && - pull16(ppReadPackedMsg, &ndlsch_params_rel13->rnti, end) && - pull16(ppReadPackedMsg, &ndlsch_params_rel13->resource_assignment, end) && - pull16(ppReadPackedMsg, &ndlsch_params_rel13->repetition_number, end) && - pull8(ppReadPackedMsg, &ndlsch_params_rel13->modulation, end) && - pull8(ppReadPackedMsg, &ndlsch_params_rel13->number_of_subframes_for_resource_assignment, end) && - pull8(ppReadPackedMsg, &ndlsch_params_rel13->scrambling_sequence_initialization_cinit, end) && - pull16(ppReadPackedMsg, &ndlsch_params_rel13->sf_idx, end) && - pull8(ppReadPackedMsg, &ndlsch_params_rel13->nrs_antenna_ports_assumed_by_the_ue, end)); -} - - -static uint8_t unpack_dl_tti_request_body_value(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg) -{ - nfapi_nr_dl_tti_request_pdu_t* value = (nfapi_nr_dl_tti_request_pdu_t*)msg; - - if(!(pull16(ppReadPackedMsg, &value->PDUSize, end) && - pull16(ppReadPackedMsg, &value->PDUType, end) )) - return 0; - - - // first match the pdu type, then call the respective function - switch(value->PDUType) - { - case NFAPI_NR_DL_TTI_CSI_RS_PDU_TYPE: - { - if(!(unpack_dl_tti_csi_rs_pdu_rel15_value(&value->csi_rs_pdu.csi_rs_pdu_rel15,ppReadPackedMsg,end))) - return 0; - } - break; - - case NFAPI_NR_DL_TTI_PDCCH_PDU_TYPE: - { - if(!(unpack_dl_tti_pdcch_pdu_rel15_value(&value->pdcch_pdu.pdcch_pdu_rel15,ppReadPackedMsg,end))) - return 0; - } - break; - case NFAPI_NR_DL_TTI_PDSCH_PDU_TYPE: - { - if(!(unpack_dl_tti_pdsch_pdu_rel15_value(&value->pdsch_pdu.pdsch_pdu_rel15,ppReadPackedMsg,end))) - return 0; - } - break; - case NFAPI_NR_DL_TTI_SSB_PDU_TYPE: - { - if(!(unpack_dl_tti_ssb_pdu_rel15_value(&value->ssb_pdu.ssb_pdu_rel15,ppReadPackedMsg,end))) - return 0; - } - break; - - default: - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "FIXME : Invalid DL_TTI pdu type %d \n", value->PDUType ); - } - break; - } - - return 1; -} - - - - -static uint8_t unpack_dl_config_request_body_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) -{ - nfapi_dl_config_request_body_t* value = (nfapi_dl_config_request_body_t*)tlv; - - if(!(pull8(ppReadPackedMsg, &value->number_pdcch_ofdm_symbols, end) && - pull8(ppReadPackedMsg, &value->number_dci, end) && - pull16(ppReadPackedMsg, &value->number_pdu, end) && - pull8(ppReadPackedMsg, &value->number_pdsch_rnti, end) && - pull16(ppReadPackedMsg, &value->transmission_power_pcfich, end))) - return 0; - - if(value->number_pdu > NFAPI_DL_CONFIG_MAX_PDU) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s number of dl config pdu's exceed maxium (count:%d max:%d)\n", __FUNCTION__, value->number_pdu, NFAPI_DL_CONFIG_MAX_PDU); - return 0; - } - - if(value->number_pdu) - { - value->dl_config_pdu_list = (nfapi_dl_config_request_pdu_t*)nfapi_p7_allocate(sizeof(nfapi_dl_config_request_pdu_t) * value->number_pdu, config); - if(value->dl_config_pdu_list == NULL) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s failed to allocate dl config pdu list (count:%d)\n", __FUNCTION__, value->number_pdu); - return 0; - } - } - else - { - value->dl_config_pdu_list = 0; - } - - uint16_t i; - uint16_t total_number_of_pdus = value->number_pdu; - for(i = 0; i < total_number_of_pdus; ++i) - { - nfapi_dl_config_request_pdu_t* pdu = &(value->dl_config_pdu_list[i]); - - if(!(pull8(ppReadPackedMsg, &pdu->pdu_type, end) && - pull8(ppReadPackedMsg, &pdu->pdu_size, end))) - return 0; - - uint8_t *packedPduEnd = (*ppReadPackedMsg) + pdu->pdu_size - 2; - - if(packedPduEnd > end) - { - // pdu end of beyond buffer end - return 0; - } - - switch(pdu->pdu_type) - { - case NFAPI_DL_CONFIG_DCI_DL_PDU_TYPE: - { - unpack_tlv_t unpack_fns[] = - { - { NFAPI_DL_CONFIG_REQUEST_DCI_DL_PDU_REL8_TAG, &pdu->dci_dl_pdu.dci_dl_pdu_rel8, &unpack_dl_config_dci_dl_pdu_rel8_value}, - { NFAPI_DL_CONFIG_REQUEST_DCI_DL_PDU_REL9_TAG, &pdu->dci_dl_pdu.dci_dl_pdu_rel9, &unpack_dl_config_dci_dl_pdu_rel9_value}, - { NFAPI_DL_CONFIG_REQUEST_DCI_DL_PDU_REL10_TAG, &pdu->dci_dl_pdu.dci_dl_pdu_rel10, &unpack_dl_config_dci_dl_pdu_rel10_value}, - { NFAPI_DL_CONFIG_REQUEST_DCI_DL_PDU_REL11_TAG, &pdu->dci_dl_pdu.dci_dl_pdu_rel11, &unpack_dl_config_dci_dl_pdu_rel11_value}, - { NFAPI_DL_CONFIG_REQUEST_DCI_DL_PDU_REL12_TAG, &pdu->dci_dl_pdu.dci_dl_pdu_rel12, &unpack_dl_config_dci_dl_pdu_rel12_value}, - { NFAPI_DL_CONFIG_REQUEST_DCI_DL_PDU_REL13_TAG, &pdu->dci_dl_pdu.dci_dl_pdu_rel13, &unpack_dl_config_dci_dl_pdu_rel13_value}, - }; - - unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); - } - break; - case NFAPI_DL_CONFIG_BCH_PDU_TYPE: - { - unpack_tlv_t unpack_fns[] = - { - { NFAPI_DL_CONFIG_REQUEST_BCH_PDU_REL8_TAG, &pdu->bch_pdu.bch_pdu_rel8, &unpack_dl_config_bch_pdu_rel8_value}, - }; - - unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); - } - break; - case NFAPI_DL_CONFIG_MCH_PDU_TYPE: - { - unpack_tlv_t unpack_fns[] = - { - { NFAPI_DL_CONFIG_REQUEST_MCH_PDU_REL8_TAG, &pdu->mch_pdu.mch_pdu_rel8, &unpack_dl_config_mch_pdu_rel8_value}, - }; - - unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); - } - break; - case NFAPI_DL_CONFIG_DLSCH_PDU_TYPE: - { - unpack_tlv_t unpack_fns[] = - { - { NFAPI_DL_CONFIG_REQUEST_DLSCH_PDU_REL8_TAG, &pdu->dlsch_pdu.dlsch_pdu_rel8, &unpack_dl_config_dlsch_pdu_rel8_value}, - { NFAPI_DL_CONFIG_REQUEST_DLSCH_PDU_REL9_TAG, &pdu->dlsch_pdu.dlsch_pdu_rel9, &unpack_dl_config_dlsch_pdu_rel9_value}, - { NFAPI_DL_CONFIG_REQUEST_DLSCH_PDU_REL10_TAG, &pdu->dlsch_pdu.dlsch_pdu_rel10, &unpack_dl_config_dlsch_pdu_rel10_value}, - { NFAPI_DL_CONFIG_REQUEST_DLSCH_PDU_REL11_TAG, &pdu->dlsch_pdu.dlsch_pdu_rel11, &unpack_dl_config_dlsch_pdu_rel11_value}, - { NFAPI_DL_CONFIG_REQUEST_DLSCH_PDU_REL12_TAG, &pdu->dlsch_pdu.dlsch_pdu_rel12, &unpack_dl_config_dlsch_pdu_rel12_value}, - { NFAPI_DL_CONFIG_REQUEST_DLSCH_PDU_REL13_TAG, &pdu->dlsch_pdu.dlsch_pdu_rel13, &unpack_dl_config_dlsch_pdu_rel13_value}, - }; - - unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); - } - break; - case NFAPI_DL_CONFIG_PCH_PDU_TYPE: - { - unpack_tlv_t unpack_fns[] = - { - { NFAPI_DL_CONFIG_REQUEST_PCH_PDU_REL8_TAG, &pdu->pch_pdu.pch_pdu_rel8, &unpack_dl_config_pch_pdu_rel8_value}, - { NFAPI_DL_CONFIG_REQUEST_PCH_PDU_REL13_TAG, &pdu->pch_pdu.pch_pdu_rel13, &unpack_dl_config_pch_pdu_rel13_value}, - }; - - unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); - } - break; - case NFAPI_DL_CONFIG_PRS_PDU_TYPE: - { - unpack_tlv_t unpack_fns[] = - { - { NFAPI_DL_CONFIG_REQUEST_PRS_PDU_REL9_TAG, &pdu->prs_pdu.prs_pdu_rel9, &unpack_dl_config_prs_pdu_rel9_value}, - }; - - unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); - } - break; - case NFAPI_DL_CONFIG_CSI_RS_PDU_TYPE: - { - unpack_tlv_t unpack_fns[] = - { - { NFAPI_DL_CONFIG_REQUEST_CSI_RS_PDU_REL10_TAG, &pdu->csi_rs_pdu.csi_rs_pdu_rel10, &unpack_dl_config_csi_rs_pdu_rel10_value}, - { NFAPI_DL_CONFIG_REQUEST_CSI_RS_PDU_REL13_TAG, &pdu->csi_rs_pdu.csi_rs_pdu_rel13, &unpack_dl_config_csi_rs_pdu_rel13_value}, - }; - - unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); - } - break; - case NFAPI_DL_CONFIG_EPDCCH_DL_PDU_TYPE: - { - unpack_tlv_t unpack_fns[] = - { - { NFAPI_DL_CONFIG_REQUEST_EPDCCH_PDU_REL8_TAG, &pdu->epdcch_pdu.epdcch_pdu_rel8, &unpack_dl_config_dci_dl_pdu_rel8_value}, - { NFAPI_DL_CONFIG_REQUEST_EPDCCH_PDU_REL9_TAG, &pdu->epdcch_pdu.epdcch_pdu_rel9, &unpack_dl_config_dci_dl_pdu_rel9_value}, - { NFAPI_DL_CONFIG_REQUEST_EPDCCH_PDU_REL10_TAG, &pdu->epdcch_pdu.epdcch_pdu_rel10, &unpack_dl_config_dci_dl_pdu_rel10_value}, - { NFAPI_DL_CONFIG_REQUEST_EPDCCH_PDU_REL11_TAG, &pdu->epdcch_pdu.epdcch_pdu_rel11, &unpack_dl_config_dci_dl_pdu_rel11_value}, - { NFAPI_DL_CONFIG_REQUEST_EPDCCH_PDU_REL12_TAG, &pdu->epdcch_pdu.epdcch_pdu_rel12, &unpack_dl_config_dci_dl_pdu_rel12_value}, - { NFAPI_DL_CONFIG_REQUEST_EPDCCH_PDU_REL13_TAG, &pdu->epdcch_pdu.epdcch_pdu_rel13, &unpack_dl_config_dci_dl_pdu_rel13_value}, - { NFAPI_DL_CONFIG_REQUEST_EPDCCH_PARAM_REL11_TAG, &pdu->epdcch_pdu.epdcch_params_rel11, &unpack_dl_config_epdcch_params_rel11_value}, - { NFAPI_DL_CONFIG_REQUEST_EPDCCH_PARAM_REL13_TAG, &pdu->epdcch_pdu.epdcch_params_rel13, &unpack_dl_config_epdcch_params_rel13_value}, - }; - - unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); - } - break; - case NFAPI_DL_CONFIG_MPDCCH_PDU_TYPE: - { - unpack_tlv_t unpack_fns[] = - { - { NFAPI_DL_CONFIG_REQUEST_MPDCCH_PDU_REL13_TAG, &pdu->mpdcch_pdu.mpdcch_pdu_rel13, &unpack_dl_config_mpdcch_pdu_rel13_value}, - }; - - unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); - } - break; - case NFAPI_DL_CONFIG_NBCH_PDU_TYPE: - { - unpack_tlv_t unpack_fns[] = - { - { NFAPI_DL_CONFIG_REQUEST_NBCH_PDU_REL13_TAG, &pdu->nbch_pdu.nbch_pdu_rel13, &unpack_dl_config_nbch_pdu_rel13_value}, - }; - - unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); - } - break; - case NFAPI_DL_CONFIG_NPDCCH_PDU_TYPE: - { - unpack_tlv_t unpack_fns[] = - { - { NFAPI_DL_CONFIG_REQUEST_NPDCCH_PDU_REL13_TAG, &pdu->npdcch_pdu.npdcch_pdu_rel13, &unpack_dl_config_npdcch_pdu_rel13_value}, - }; - - unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); - - } - break; - case NFAPI_DL_CONFIG_NDLSCH_PDU_TYPE: - { - unpack_tlv_t unpack_fns[] = - { - { NFAPI_DL_CONFIG_REQUEST_NDLSCH_PDU_REL13_TAG, &pdu->ndlsch_pdu.ndlsch_pdu_rel13, &unpack_dl_config_ndlsch_pdu_rel13_value}, - }; - - unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); - - } - break; - default: - // Need to log an error - break; - } - } - - return 1; -} - - -static uint8_t unpack_dl_tti_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config) -{ - nfapi_nr_dl_tti_request_t *pNfapiMsg = (nfapi_nr_dl_tti_request_t*)msg; - - if (!(pull16(ppReadPackedMsg,&pNfapiMsg->SFN, end) && - pull16(ppReadPackedMsg, &pNfapiMsg->Slot, end) && - pull8(ppReadPackedMsg, &pNfapiMsg->dl_tti_request_body.nGroup, end) && - pull8(ppReadPackedMsg, &pNfapiMsg->dl_tti_request_body.nPDUs, end) && - pullarray8(ppReadPackedMsg,pNfapiMsg->dl_tti_request_body.nUe ,256,pNfapiMsg->dl_tti_request_body.nGroup, end) - //pusharray8(pNfapiMsg->PduIdx[0] ,256,256, ppWritePackedMsg, end) - )) - return 0; - - int arr[12]; - for(int i=0;idl_tti_request_body.nGroup;i++) - { - for(int j=0;jdl_tti_request_body.nUe[i];j++) - { - arr[j] = pNfapiMsg->dl_tti_request_body.PduIdx[i][j]; - } - if(!(pullarrays32(ppReadPackedMsg,arr,12,pNfapiMsg->dl_tti_request_body.nUe[i], end))) - return 0; - } - - for(int i=0;idl_tti_request_body.nPDUs;i++) - { - if(!unpack_dl_tti_request_body_value(ppReadPackedMsg, end, &pNfapiMsg->dl_tti_request_body.dl_tti_pdu_list[i])) - return 0; - } - -return 1; -} - - -static uint8_t unpack_ul_tti_request_prach_pdu(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_nr_prach_pdu_t* prach_pdu = (nfapi_nr_prach_pdu_t*)tlv; - - return( - pull16(ppReadPackedMsg, &prach_pdu->phys_cell_id, end) && - pull8(ppReadPackedMsg, &prach_pdu->num_prach_ocas, end) && - pull8(ppReadPackedMsg, &prach_pdu->prach_format, end) && - pull8(ppReadPackedMsg, &prach_pdu->num_ra, end) && - pull8(ppReadPackedMsg, &prach_pdu->prach_start_symbol, end) && - pull16(ppReadPackedMsg, &prach_pdu->num_cs, end) - // TODO: ignoring beamforming tlv for now - ); -} - - -static uint8_t unpack_ul_tti_request_pucch_pdu(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_nr_pucch_pdu_t* pucch_pdu = (nfapi_nr_pucch_pdu_t*)tlv; - - return( - pull16(ppReadPackedMsg, &pucch_pdu->rnti, end) && - pull32(ppReadPackedMsg, &pucch_pdu->handle, end) && - pull16(ppReadPackedMsg, &pucch_pdu->bwp_size, end) && - pull16(ppReadPackedMsg, &pucch_pdu->bwp_start, end) && - pull8(ppReadPackedMsg, &pucch_pdu->subcarrier_spacing, end) && - pull8(ppReadPackedMsg, &pucch_pdu->cyclic_prefix, end) && - pull8(ppReadPackedMsg, &pucch_pdu->format_type, end) && - pull8(ppReadPackedMsg, &pucch_pdu->multi_slot_tx_indicator, end) && - pull16(ppReadPackedMsg, &pucch_pdu->prb_start, end) && - pull16(ppReadPackedMsg, &pucch_pdu->prb_size, end) && - pull8(ppReadPackedMsg, &pucch_pdu->start_symbol_index, end) && - pull8(ppReadPackedMsg, &pucch_pdu->nr_of_symbols, end) && - pull8(ppReadPackedMsg, &pucch_pdu->freq_hop_flag, end) && - pull16(ppReadPackedMsg, &pucch_pdu->second_hop_prb, end) && - pull8(ppReadPackedMsg, &pucch_pdu->group_hop_flag, end) && - pull8(ppReadPackedMsg, &pucch_pdu->sequence_hop_flag, end) && - pull16(ppReadPackedMsg, &pucch_pdu->hopping_id, end) && - pull16(ppReadPackedMsg, &pucch_pdu->initial_cyclic_shift, end) && - pull16(ppReadPackedMsg, &pucch_pdu->data_scrambling_id, end) && - pull8(ppReadPackedMsg, &pucch_pdu->time_domain_occ_idx, end) && - pull8(ppReadPackedMsg, &pucch_pdu->pre_dft_occ_idx, end) && - pull8(ppReadPackedMsg, &pucch_pdu->pre_dft_occ_len, end) && - pull8(ppReadPackedMsg, &pucch_pdu->add_dmrs_flag, end) && - pull16(ppReadPackedMsg, &pucch_pdu->dmrs_scrambling_id, end) && - pull8(ppReadPackedMsg, &pucch_pdu->dmrs_cyclic_shift, end) && - pull8(ppReadPackedMsg, &pucch_pdu->sr_flag, end) && - pull8(ppReadPackedMsg, &pucch_pdu->bit_len_harq, end) && - pull16(ppReadPackedMsg, &pucch_pdu->bit_len_csi_part1, end) && - pull16(ppReadPackedMsg, &pucch_pdu->bit_len_csi_part2, end) - // TODO: ignoring beamforming tlv for now - ); -} - - -static uint8_t unpack_ul_tti_request_pusch_pdu(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_nr_pusch_pdu_t* pusch_pdu = (nfapi_nr_pusch_pdu_t*)tlv; - - if (!( - pull16(ppReadPackedMsg, &pusch_pdu->pdu_bit_map, end) && - pull16(ppReadPackedMsg, &pusch_pdu->rnti, end) && - pull32(ppReadPackedMsg, &pusch_pdu->handle, end) && - pull16(ppReadPackedMsg, &pusch_pdu->bwp_size, end) && - pull16(ppReadPackedMsg, &pusch_pdu->bwp_start, end) && - pull8(ppReadPackedMsg, &pusch_pdu->subcarrier_spacing, end) && - pull8(ppReadPackedMsg, &pusch_pdu->cyclic_prefix, end) && - pull16(ppReadPackedMsg, &pusch_pdu->target_code_rate, end) && - pull8(ppReadPackedMsg, &pusch_pdu->qam_mod_order, end) && - pull8(ppReadPackedMsg, &pusch_pdu->mcs_index, end) && - pull8(ppReadPackedMsg, &pusch_pdu->mcs_table, end) && - pull8(ppReadPackedMsg, &pusch_pdu->transform_precoding, end) && - pull16(ppReadPackedMsg, &pusch_pdu->data_scrambling_id, end) && - pull8(ppReadPackedMsg, &pusch_pdu->nrOfLayers, end) && - pull16(ppReadPackedMsg, &pusch_pdu->ul_dmrs_symb_pos, end) && - pull8(ppReadPackedMsg, &pusch_pdu->dmrs_config_type, end) && - pull16(ppReadPackedMsg, &pusch_pdu->ul_dmrs_scrambling_id, end) && - pull8(ppReadPackedMsg, &pusch_pdu->scid, end) && - pull8(ppReadPackedMsg, &pusch_pdu->num_dmrs_cdm_grps_no_data, end) && - pull16(ppReadPackedMsg, &pusch_pdu->dmrs_ports, end) && - pull8(ppReadPackedMsg, &pusch_pdu->resource_alloc, end) && - pull8(ppReadPackedMsg, &pusch_pdu->resource_alloc,end) && - pull16(ppReadPackedMsg, &pusch_pdu->dmrs_ports, end) && - pull16(ppReadPackedMsg, &pusch_pdu->rb_start, end) && - pull16(ppReadPackedMsg, &pusch_pdu->rb_size, end) && - pull8(ppReadPackedMsg, &pusch_pdu->vrb_to_prb_mapping, end) && - pull8(ppReadPackedMsg, &pusch_pdu->frequency_hopping, end) && - pull16(ppReadPackedMsg, &pusch_pdu->tx_direct_current_location, end) && - pull8(ppReadPackedMsg, &pusch_pdu->uplink_frequency_shift_7p5khz, end) && - pull8(ppReadPackedMsg, &pusch_pdu->start_symbol_index, end) && - pull8(ppReadPackedMsg, &pusch_pdu->nr_of_symbols, end) - // TODO: ignoring beamforming tlv for now - )) - return 0; - - - //Pack Optional Data only included if indicated in pduBitmap - switch(pusch_pdu->pdu_bit_map){ - case PUSCH_PDU_BITMAP_PUSCH_DATA: - { - // pack optional TLVs - return( - pull8(ppReadPackedMsg, &pusch_pdu->pusch_data.rv_index, end) && - pull8(ppReadPackedMsg, &pusch_pdu->pusch_data.harq_process_id, end) && - pull32(ppReadPackedMsg, &pusch_pdu->pusch_data.tb_size, end) && - pull16(ppReadPackedMsg, &pusch_pdu->pusch_data.num_cb, end) && - pullarray8(ppReadPackedMsg, pusch_pdu->pusch_data.cb_present_and_position,1,1,end) - ); - } - break; - - case PUSCH_PDU_BITMAP_PUSCH_UCI: - { - return( - pull16(ppReadPackedMsg, &pusch_pdu->pusch_uci.harq_ack_bit_length, end) && - pull16(ppReadPackedMsg, &pusch_pdu->pusch_uci.csi_part1_bit_length, end) && - pull16(ppReadPackedMsg, &pusch_pdu->pusch_uci.csi_part2_bit_length, end) && - pull8(ppReadPackedMsg, &pusch_pdu->pusch_uci.alpha_scaling, end) && - pull8(ppReadPackedMsg, &pusch_pdu->pusch_uci.beta_offset_harq_ack, end) && - pull8(ppReadPackedMsg, &pusch_pdu->pusch_uci.beta_offset_csi1, end) && - pull8(ppReadPackedMsg, &pusch_pdu->pusch_uci.beta_offset_csi2, end) - ); - } - break; - - case PUSCH_PDU_BITMAP_PUSCH_PTRS: - { - return( - pull8(ppReadPackedMsg, &pusch_pdu->pusch_ptrs.num_ptrs_ports, end) && - pull8(ppReadPackedMsg, &pusch_pdu->pusch_ptrs.ptrs_ports_list->ptrs_dmrs_port, end) && -+ pull16(ppReadPackedMsg, &pusch_pdu->pusch_ptrs.ptrs_ports_list->ptrs_port_index, end) && -+ pull8(ppReadPackedMsg, &pusch_pdu->pusch_ptrs.ptrs_ports_list->ptrs_re_offset, end) && - pull8(ppReadPackedMsg, &pusch_pdu->pusch_ptrs.ptrs_time_density, end) && - pull8(ppReadPackedMsg, &pusch_pdu->pusch_ptrs.ptrs_freq_density, end) && - pull8(ppReadPackedMsg, &pusch_pdu->pusch_ptrs.ul_ptrs_power, end) - ); - } - break; - - case PUSCH_PDU_BITMAP_DFTS_OFDM: - { - return( - pull8(ppReadPackedMsg, &pusch_pdu->dfts_ofdm.low_papr_group_number, end) && - pull16(ppReadPackedMsg, &pusch_pdu->dfts_ofdm.low_papr_sequence_number, end) && - pull8(ppReadPackedMsg, &pusch_pdu->dfts_ofdm.ul_ptrs_sample_density, end) && - pull8(ppReadPackedMsg, &pusch_pdu->dfts_ofdm.ul_ptrs_time_density_transform_precoding, end) - ); - } - break; - - default: - { - NFAPI_TRACE(NFAPI_TRACE_INFO, "Invalid pdu bitmap %d \n", pusch_pdu->pdu_bit_map ); - } - } - - return 1; -} - - -static uint8_t unpack_ul_tti_request_srs_pdu(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_nr_srs_pdu_t* srs_pdu = (nfapi_nr_srs_pdu_t*)tlv; - - return( - pull16(ppReadPackedMsg, &srs_pdu->rnti, end) && - pull32(ppReadPackedMsg, &srs_pdu->handle, end) && - pull16(ppReadPackedMsg, &srs_pdu->bwp_size, end) && - pull16(ppReadPackedMsg, &srs_pdu->bwp_start, end) && - pull8(ppReadPackedMsg, &srs_pdu->subcarrier_spacing, end) && - pull8(ppReadPackedMsg, &srs_pdu->cyclic_prefix, end) && - pull8(ppReadPackedMsg, &srs_pdu->num_ant_ports, end) && - pull8(ppReadPackedMsg, &srs_pdu->num_symbols, end) && - pull8(ppReadPackedMsg, &srs_pdu->num_repetitions, end) && - pull8(ppReadPackedMsg, &srs_pdu->time_start_position, end) && - pull8(ppReadPackedMsg, &srs_pdu->config_index, end) && - pull16(ppReadPackedMsg, &srs_pdu->sequence_id, end) && - pull8(ppReadPackedMsg, &srs_pdu->bandwidth_index, end) && - pull8(ppReadPackedMsg, &srs_pdu->comb_size, end) && - pull8(ppReadPackedMsg, &srs_pdu->comb_offset, end) && - pull8(ppReadPackedMsg, &srs_pdu->cyclic_shift, end) && - pull8(ppReadPackedMsg, &srs_pdu->frequency_position, end) && - pull8(ppReadPackedMsg, &srs_pdu->frequency_shift, end) && - pull8(ppReadPackedMsg, &srs_pdu->frequency_hopping, end) && - pull8(ppReadPackedMsg, &srs_pdu->group_or_sequence_hopping, end) && - pull8(ppReadPackedMsg, &srs_pdu->resource_type, end) && - pull16(ppReadPackedMsg, &srs_pdu->t_srs, end) && - pull16(ppReadPackedMsg, &srs_pdu->t_offset, end) - // TODO: ignoring beamforming tlv for now - ); -} - - -static uint8_t unpack_ul_tti_pdu_list_value(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg) -{ - nfapi_nr_ul_tti_request_number_of_pdus_t* pNfapiMsg = (nfapi_nr_ul_tti_request_number_of_pdus_t*)msg; - - if(!(pull16(ppReadPackedMsg, &pNfapiMsg->pdu_size, end) && - pull16(ppReadPackedMsg, &pNfapiMsg->pdu_type, end) )) - return 0; - - - // first natch the pdu type, then call the respective function - switch(pNfapiMsg->pdu_type) - { - - case NFAPI_NR_UL_CONFIG_PRACH_PDU_TYPE: - { - if(!unpack_ul_tti_request_prach_pdu(&pNfapiMsg->prach_pdu, ppReadPackedMsg, end)) - return 0; - } - break; - - case NFAPI_NR_UL_CONFIG_PUCCH_PDU_TYPE: - { - if(!unpack_ul_tti_request_pucch_pdu(&pNfapiMsg->pucch_pdu, ppReadPackedMsg, end)) - return 0; - } - break; - - case NFAPI_NR_UL_CONFIG_PUSCH_PDU_TYPE: - { - if(!unpack_ul_tti_request_pusch_pdu(&pNfapiMsg->pusch_pdu, ppReadPackedMsg, end)) - return 0; - } - break; - - case NFAPI_NR_UL_CONFIG_SRS_PDU_TYPE: - { - if(!unpack_ul_tti_request_srs_pdu(&pNfapiMsg->srs_pdu, ppReadPackedMsg, end)) - return 0; - } - break; - - default: - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "FIXME : Invalid UL_TTI pdu type %d \n", pNfapiMsg->pdu_type ); - } - break; - - - } - - return 1; -} - - -static uint8_t unpack_ul_tti_groups_list_value(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg) -{ - nfapi_nr_ul_tti_request_number_of_groups_t* pNfapiMsg = (nfapi_nr_ul_tti_request_number_of_groups_t*)msg; - - if(!pull8(ppReadPackedMsg, &pNfapiMsg->n_ue, end)) - return 0; - for (int i = 0; i < pNfapiMsg->n_ue; i++) - { - if(!pull8(ppReadPackedMsg, &pNfapiMsg->ue_list[i].pdu_idx ,end) ) - return 0; - } - return 1; -} - - -static uint8_t unpack_ul_tti_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config) -{ - nfapi_nr_ul_tti_request_t *pNfapiMsg = (nfapi_nr_ul_tti_request_t*)msg; - - if (!( - pull16(ppReadPackedMsg, &pNfapiMsg->SFN, end) && - pull16(ppReadPackedMsg, &pNfapiMsg->Slot, end) && - pull8(ppReadPackedMsg, &pNfapiMsg->n_pdus, end) && - pull8(ppReadPackedMsg, &pNfapiMsg->n_group, end) && - pull8(ppReadPackedMsg, &pNfapiMsg->rach_present, end) && - pull8(ppReadPackedMsg, &pNfapiMsg->n_ulcch, end) && - pull8(ppReadPackedMsg, &pNfapiMsg->n_ulsch, end) )) - return 0; - - for(int i=0; i< pNfapiMsg->n_pdus; i++) - { - if (!unpack_ul_tti_pdu_list_value(ppReadPackedMsg, end, &pNfapiMsg->pdus_list[i])) - return 0; - } - - for(int i=0; i< pNfapiMsg->n_group; i++) - { - if (!unpack_ul_tti_groups_list_value(ppReadPackedMsg, end, &pNfapiMsg->groups_list[i])) - return 0; - } - - return 1; -} - - - -static uint8_t unpack_dl_config_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config) -{ - nfapi_dl_config_request_t *pNfapiMsg = (nfapi_dl_config_request_t*)msg; - - unpack_p7_tlv_t unpack_fns[] = - { - { NFAPI_DL_CONFIG_REQUEST_BODY_TAG, &pNfapiMsg->dl_config_request_body, &unpack_dl_config_request_body_value}, - }; - - return ( pull16(ppReadPackedMsg, &pNfapiMsg->sfn_sf, end) && - unpack_p7_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); -} - -static uint8_t unpack_ul_config_ulsch_pdu_rel8_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - - - - nfapi_ul_config_ulsch_pdu_rel8_t* ulsch_pdu_rel8 = (nfapi_ul_config_ulsch_pdu_rel8_t*)tlv; - - return (pull32(ppReadPackedMsg, &ulsch_pdu_rel8->handle, end) && - pull16(ppReadPackedMsg, &ulsch_pdu_rel8->size, end) && - pull16(ppReadPackedMsg, &ulsch_pdu_rel8->rnti, end) && - pull8(ppReadPackedMsg, &ulsch_pdu_rel8->resource_block_start, end) && - pull8(ppReadPackedMsg, &ulsch_pdu_rel8->number_of_resource_blocks, end) && - pull8(ppReadPackedMsg, &ulsch_pdu_rel8->modulation_type, end) && - pull8(ppReadPackedMsg, &ulsch_pdu_rel8->cyclic_shift_2_for_drms, end) && - pull8(ppReadPackedMsg, &ulsch_pdu_rel8->frequency_hopping_enabled_flag, end) && - pull8(ppReadPackedMsg, &ulsch_pdu_rel8->frequency_hopping_bits, end) && - pull8(ppReadPackedMsg, &ulsch_pdu_rel8->new_data_indication, end) && - pull8(ppReadPackedMsg, &ulsch_pdu_rel8->redundancy_version, end) && - pull8(ppReadPackedMsg, &ulsch_pdu_rel8->harq_process_number, end) && - pull8(ppReadPackedMsg, &ulsch_pdu_rel8->ul_tx_mode, end) && - pull8(ppReadPackedMsg, &ulsch_pdu_rel8->current_tx_nb, end) && - pull8(ppReadPackedMsg, &ulsch_pdu_rel8->n_srs, end )); -} - -static uint8_t unpack_ul_config_ulsch_pdu_rel10_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_ul_config_ulsch_pdu_rel10_t* ulsch_pdu_rel10 = (nfapi_ul_config_ulsch_pdu_rel10_t*)tlv; - - return (pull8(ppReadPackedMsg, &ulsch_pdu_rel10->resource_allocation_type, end) && - pull32(ppReadPackedMsg, &ulsch_pdu_rel10->resource_block_coding, end) && - pull8(ppReadPackedMsg, &ulsch_pdu_rel10->transport_blocks, end) && - pull8(ppReadPackedMsg, &ulsch_pdu_rel10->transmission_scheme, end) && - pull8(ppReadPackedMsg, &ulsch_pdu_rel10->number_of_layers, end) & - pull8(ppReadPackedMsg, &ulsch_pdu_rel10->codebook_index, end) && - pull8(ppReadPackedMsg, &ulsch_pdu_rel10->disable_sequence_hopping_flag, end)); -} -static uint8_t unpack_ul_config_ulsch_pdu_rel11_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_ul_config_ulsch_pdu_rel11_t* ulsch_pdu_rel11 = (nfapi_ul_config_ulsch_pdu_rel11_t*)tlv; - - return ( pull8(ppReadPackedMsg, &ulsch_pdu_rel11->virtual_cell_id_enabled_flag, end) && - pull16(ppReadPackedMsg, &ulsch_pdu_rel11->npusch_identity, end) && - pull8(ppReadPackedMsg, &ulsch_pdu_rel11->dmrs_config_flag, end) && - pull16(ppReadPackedMsg, &ulsch_pdu_rel11->ndmrs_csh_identity, end)); -} -static uint8_t unpack_ul_config_ulsch_pdu_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_ul_config_ulsch_pdu_rel13_t* ulsch_pdu_rel13 = (nfapi_ul_config_ulsch_pdu_rel13_t*)tlv; - - return (pull8(ppReadPackedMsg, &ulsch_pdu_rel13->ue_type, end) && - pull16(ppReadPackedMsg, &ulsch_pdu_rel13->total_number_of_repetitions, end) && - pull16(ppReadPackedMsg, &ulsch_pdu_rel13->repetition_number, end) && - pull16(ppReadPackedMsg, &ulsch_pdu_rel13->initial_transmission_sf_io, end) && - pull8(ppReadPackedMsg, &ulsch_pdu_rel13->empty_symbols_due_to_re_tunning, end)); -} -static uint8_t unpack_ul_config_cqi_ri_info_rel8_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_ul_config_cqi_ri_information_rel8_t* cqi_ri_info_rel8 = (nfapi_ul_config_cqi_ri_information_rel8_t*)tlv; - - return (pull8(ppReadPackedMsg, &cqi_ri_info_rel8->dl_cqi_pmi_size_rank_1, end) && - pull8(ppReadPackedMsg, &cqi_ri_info_rel8->dl_cqi_pmi_size_rank_greater_1, end) && - pull8(ppReadPackedMsg, &cqi_ri_info_rel8->ri_size, end) && - pull8(ppReadPackedMsg, &cqi_ri_info_rel8->delta_offset_cqi, end) && - pull8(ppReadPackedMsg, &cqi_ri_info_rel8->delta_offset_ri, end)); -} - -static uint8_t unpack_ul_config_cqi_ri_info_rel9_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_ul_config_cqi_ri_information_rel9_t* cqi_ri_info_rel9 = (nfapi_ul_config_cqi_ri_information_rel9_t*)tlv; - - if(!(pull8(ppReadPackedMsg, &cqi_ri_info_rel9->report_type, end) && - pull8(ppReadPackedMsg, &cqi_ri_info_rel9->delta_offset_cqi, end) && - pull8(ppReadPackedMsg, &cqi_ri_info_rel9->delta_offset_ri, end))) - return 0; - - switch(cqi_ri_info_rel9->report_type) - { - case NFAPI_CSI_REPORT_TYPE_PERIODIC: - { - if(!(pull8(ppReadPackedMsg, &cqi_ri_info_rel9->periodic_cqi_pmi_ri_report.dl_cqi_pmi_ri_size, end) && - pull8(ppReadPackedMsg, &cqi_ri_info_rel9->periodic_cqi_pmi_ri_report.control_type, end))) - return 0; - } - break; - case NFAPI_CSI_REPORT_TYPE_APERIODIC: - { - if(pull8(ppReadPackedMsg, &cqi_ri_info_rel9->aperiodic_cqi_pmi_ri_report.number_of_cc, end) ==0) - return 0; - - uint8_t i; - for(i = 0; i < cqi_ri_info_rel9->aperiodic_cqi_pmi_ri_report.number_of_cc; ++i) - { - if(pull8(ppReadPackedMsg, &cqi_ri_info_rel9->aperiodic_cqi_pmi_ri_report.cc[i].ri_size, end) == 0) - return 0; - - uint8_t j; - for(j = 0; j < 8; ++j) - { - if(pull8(ppReadPackedMsg, &cqi_ri_info_rel9->aperiodic_cqi_pmi_ri_report.cc[i].dl_cqi_pmi_size[j], end) == 0) - return 0; - } - } - } - break; - default: - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "FIXME : Invalid report type %d \n", cqi_ri_info_rel9->report_type ); - return 0; - } - break; - }; - return 1; -} - -// NOTE : This function is a little unconventional as we uese the side to -// determine the report type -static uint8_t unpack_ul_config_cqi_ri_info_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_ul_config_cqi_ri_information_rel13_t* cqi_ri_info_rel13 = (nfapi_ul_config_cqi_ri_information_rel13_t*)tlv; - if(cqi_ri_info_rel13->tl.length == 0) - { - cqi_ri_info_rel13->report_type = NFAPI_CSI_REPORT_TYPE_APERIODIC; - } - else - { - cqi_ri_info_rel13->report_type = NFAPI_CSI_REPORT_TYPE_PERIODIC; - if(pull16(ppReadPackedMsg, &cqi_ri_info_rel13->periodic_cqi_pmi_ri_report.dl_cqi_pmi_ri_size_2, end) == 0) - return 0; - } - return 1; -} -static uint8_t unpack_ul_config_cqi_init_tx_params_rel8_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_ul_config_initial_transmission_parameters_rel8_t* init_tx_params_rel8 = (nfapi_ul_config_initial_transmission_parameters_rel8_t*)tlv; - - return (pull8(ppReadPackedMsg, &init_tx_params_rel8->n_srs_initial, end) && - pull8(ppReadPackedMsg, &init_tx_params_rel8->initial_number_of_resource_blocks, end)); -} -static uint8_t unpack_ul_config_ulsch_harq_info_rel10_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_ul_config_ulsch_harq_information_rel10_t* harq_info_rel10 = (nfapi_ul_config_ulsch_harq_information_rel10_t*)tlv; - - return (pull8(ppReadPackedMsg, &harq_info_rel10->harq_size, end) && - pull8(ppReadPackedMsg, &harq_info_rel10->delta_offset_harq, end) && - pull8(ppReadPackedMsg, &harq_info_rel10->ack_nack_mode, end)); -} - -static uint8_t unpack_ul_config_ulsch_harq_info_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_ul_config_ulsch_harq_information_rel13_t* harq_info_rel13 = (nfapi_ul_config_ulsch_harq_information_rel13_t*)tlv; - - return (pull16(ppReadPackedMsg, &harq_info_rel13->harq_size_2, end) && - pull8(ppReadPackedMsg, &harq_info_rel13->delta_offset_harq_2, end)); -} - -static uint8_t unpack_ul_config_ue_info_rel8_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_ul_config_ue_information_rel8_t* ue_info_rel8 = (nfapi_ul_config_ue_information_rel8_t*)tlv; - - return (pull32(ppReadPackedMsg, &ue_info_rel8->handle, end) && - pull16(ppReadPackedMsg, (uint16_t *)&ue_info_rel8->rnti, end)); -} -static uint8_t unpack_ul_config_ue_info_rel11_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_ul_config_ue_information_rel11_t* ue_info_rel11 = (nfapi_ul_config_ue_information_rel11_t*)tlv; - - return (pull8(ppReadPackedMsg, &ue_info_rel11->virtual_cell_id_enabled_flag, end) && - pull16(ppReadPackedMsg, &ue_info_rel11->npusch_identity, end)); -} -static uint8_t unpack_ul_config_ue_info_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_ul_config_ue_information_rel13_t* ue_info_rel13 = (nfapi_ul_config_ue_information_rel13_t*)tlv; - - return (pull8(ppReadPackedMsg, &ue_info_rel13->ue_type, end) && - pull8(ppReadPackedMsg, &ue_info_rel13->empty_symbols, end) && - pull16(ppReadPackedMsg, &ue_info_rel13->total_number_of_repetitions, end) && - pull16(ppReadPackedMsg, &ue_info_rel13->repetition_number, end)); -} - -static uint8_t unpack_ul_config_cqi_info_rel8_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_ul_config_cqi_information_rel8_t* cqi_info_rel8 = (nfapi_ul_config_cqi_information_rel8_t*)tlv; - - return ( pull16(ppReadPackedMsg, &cqi_info_rel8->pucch_index, end) && - pull8(ppReadPackedMsg, &cqi_info_rel8->dl_cqi_pmi_size, end)); -} -static uint8_t unpack_ul_config_cqi_info_rel10_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_ul_config_cqi_information_rel10_t* cqi_info_rel10 = (nfapi_ul_config_cqi_information_rel10_t*)tlv; - - return (pull8(ppReadPackedMsg, &cqi_info_rel10->number_of_pucch_resource, end) && - pull16(ppReadPackedMsg, &cqi_info_rel10->pucch_index_p1, end)); -} -static uint8_t unpack_ul_config_cqi_info_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_ul_config_cqi_information_rel13_t* cqi_info_rel13 = (nfapi_ul_config_cqi_information_rel13_t*)tlv; - - return (pull8(ppReadPackedMsg, &cqi_info_rel13->csi_mode, end) && - pull16(ppReadPackedMsg, &cqi_info_rel13->dl_cqi_pmi_size_2, end) && - pull8(ppReadPackedMsg, &cqi_info_rel13->starting_prb, end) && - pull8(ppReadPackedMsg, &cqi_info_rel13->n_prb, end) && - pull8(ppReadPackedMsg, &cqi_info_rel13->cdm_index, end) && - pull8(ppReadPackedMsg, &cqi_info_rel13->n_srs, end)); -} - -static uint8_t unpack_ul_config_sr_info_rel8_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_ul_config_sr_information_rel8_t* sr_info_rel8 = (nfapi_ul_config_sr_information_rel8_t*)tlv; - - return ( pull16(ppReadPackedMsg, &sr_info_rel8->pucch_index, end)); -} - -static uint8_t unpack_ul_config_sr_info_rel10_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_ul_config_sr_information_rel10_t* sr_info_rel10 = (nfapi_ul_config_sr_information_rel10_t*)tlv; - - return (pull8(ppReadPackedMsg, &sr_info_rel10->number_of_pucch_resources, end) && - pull16(ppReadPackedMsg, &sr_info_rel10->pucch_index_p1, end)); -} - -static uint8_t unpack_ul_config_harq_info_rel10_tdd_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_ul_config_harq_information_rel10_tdd_t* harq_info_tdd_rel10 = (nfapi_ul_config_harq_information_rel10_tdd_t*)tlv; - - return (pull8(ppReadPackedMsg, &harq_info_tdd_rel10->harq_size, end) && - pull8(ppReadPackedMsg, &harq_info_tdd_rel10->ack_nack_mode, end) && - pull8(ppReadPackedMsg, &harq_info_tdd_rel10->number_of_pucch_resources, end) && - pull16(ppReadPackedMsg, &harq_info_tdd_rel10->n_pucch_1_0, end) && - pull16(ppReadPackedMsg, &harq_info_tdd_rel10->n_pucch_1_1, end) && - pull16(ppReadPackedMsg, &harq_info_tdd_rel10->n_pucch_1_2, end) && - pull16(ppReadPackedMsg, &harq_info_tdd_rel10->n_pucch_1_3, end)); -} - -static uint8_t unpack_ul_config_harq_info_rel8_fdd_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_ul_config_harq_information_rel8_fdd_t* harq_info_fdd_rel8 = (nfapi_ul_config_harq_information_rel8_fdd_t*)tlv; - - return (pull16(ppReadPackedMsg, &harq_info_fdd_rel8->n_pucch_1_0, end) && - pull8(ppReadPackedMsg, &harq_info_fdd_rel8->harq_size, end)); -} - -static uint8_t unpack_ul_config_harq_info_rel9_fdd_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_ul_config_harq_information_rel9_fdd_t* harq_info_fdd_rel9 = (nfapi_ul_config_harq_information_rel9_fdd_t*)tlv; - - return (pull8(ppReadPackedMsg, &harq_info_fdd_rel9->harq_size, end) && - pull8(ppReadPackedMsg, &harq_info_fdd_rel9->ack_nack_mode, end) && - pull8(ppReadPackedMsg, &harq_info_fdd_rel9->number_of_pucch_resources, end) && - pull16(ppReadPackedMsg, &harq_info_fdd_rel9->n_pucch_1_0, end) && - pull16(ppReadPackedMsg, &harq_info_fdd_rel9->n_pucch_1_1, end) && - pull16(ppReadPackedMsg, &harq_info_fdd_rel9->n_pucch_1_2, end) && - pull16(ppReadPackedMsg, &harq_info_fdd_rel9->n_pucch_1_3, end)); -} - -static uint8_t unpack_ul_config_harq_info_rel11_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_ul_config_harq_information_rel11_t* harq_info_rel11 = (nfapi_ul_config_harq_information_rel11_t*)tlv; - - return (pull8(ppReadPackedMsg, &harq_info_rel11->num_ant_ports, end) && - pull16(ppReadPackedMsg, &harq_info_rel11->n_pucch_2_0, end) && - pull16(ppReadPackedMsg, &harq_info_rel11->n_pucch_2_1, end) && - pull16(ppReadPackedMsg, &harq_info_rel11->n_pucch_2_2, end) && - pull16(ppReadPackedMsg, &harq_info_rel11->n_pucch_2_3, end)); -} - -static uint8_t unpack_ul_config_harq_info_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_ul_config_harq_information_rel13_t* harq_info_rel13 = (nfapi_ul_config_harq_information_rel13_t*)tlv; - - return (pull16(ppReadPackedMsg, &harq_info_rel13->harq_size_2, end) && - pull8(ppReadPackedMsg, &harq_info_rel13->starting_prb, end) && - pull8(ppReadPackedMsg, &harq_info_rel13->n_prb, end) && - pull8(ppReadPackedMsg, &harq_info_rel13->cdm_index, end) && - pull8(ppReadPackedMsg, &harq_info_rel13->n_srs, end)); -} - - -static uint8_t unpack_ul_config_srs_pdu_rel8_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_ul_config_srs_pdu_rel8_t* srs_pdu_rel8 = (nfapi_ul_config_srs_pdu_rel8_t*)tlv; - - return (pull32(ppReadPackedMsg, &srs_pdu_rel8->handle, end) && - pull16(ppReadPackedMsg, &srs_pdu_rel8->size, end) && - pull16(ppReadPackedMsg, &srs_pdu_rel8->rnti, end) && - pull8(ppReadPackedMsg, &srs_pdu_rel8->srs_bandwidth, end) && - pull8(ppReadPackedMsg, &srs_pdu_rel8->frequency_domain_position, end) && - pull8(ppReadPackedMsg, &srs_pdu_rel8->srs_hopping_bandwidth, end) && - pull8(ppReadPackedMsg, &srs_pdu_rel8->transmission_comb, end) && - pull16(ppReadPackedMsg, &srs_pdu_rel8->i_srs, end) && - pull8(ppReadPackedMsg, &srs_pdu_rel8->sounding_reference_cyclic_shift, end)); -} - -static uint8_t unpack_ul_config_srs_pdu_rel10_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_ul_config_srs_pdu_rel10_t* srs_pdu_rel10 = (nfapi_ul_config_srs_pdu_rel10_t*)tlv; - return pull8(ppReadPackedMsg, &srs_pdu_rel10->antenna_port, end); -} - -static uint8_t unpack_ul_config_srs_pdu_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_ul_config_srs_pdu_rel13_t* srs_pdu_rel13 = (nfapi_ul_config_srs_pdu_rel13_t*)tlv; - - return (pull8(ppReadPackedMsg, &srs_pdu_rel13->number_of_combs, end)); -} - -static uint8_t unpack_ul_nb_harq_info_rel13_fdd_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_ul_config_nb_harq_information_rel13_fdd_t* nb_harq_info_fdd_rel13 = (nfapi_ul_config_nb_harq_information_rel13_fdd_t*)tlv; - - return (pull8(ppReadPackedMsg, &nb_harq_info_fdd_rel13->harq_ack_resource, end)); -} - -static uint8_t unpack_ul_config_nulsch_pdu_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_ul_config_nulsch_pdu_rel13_t* nulsch_pdu_rel13 = (nfapi_ul_config_nulsch_pdu_rel13_t*)tlv; - - if(!(pull8(ppReadPackedMsg, &nulsch_pdu_rel13->nulsch_format, end) && - pull32(ppReadPackedMsg, &nulsch_pdu_rel13->handle, end) && - pull16(ppReadPackedMsg, &nulsch_pdu_rel13->size, end) && - pull16(ppReadPackedMsg, &nulsch_pdu_rel13->rnti, end) && - pull8(ppReadPackedMsg, &nulsch_pdu_rel13->subcarrier_indication, end) && - pull8(ppReadPackedMsg, &nulsch_pdu_rel13->resource_assignment, end) && - pull8(ppReadPackedMsg, &nulsch_pdu_rel13->mcs, end) && - pull8(ppReadPackedMsg, &nulsch_pdu_rel13->redudancy_version, end) && - pull8(ppReadPackedMsg, &nulsch_pdu_rel13->repetition_number, end) && - pull8(ppReadPackedMsg, &nulsch_pdu_rel13->new_data_indication, end) && - pull8(ppReadPackedMsg, &nulsch_pdu_rel13->n_srs, end) && - pull16(ppReadPackedMsg, &nulsch_pdu_rel13->scrambling_sequence_initialization_cinit, end) && - pull16(ppReadPackedMsg, &nulsch_pdu_rel13->sf_idx, end))) - return 0; - - unpack_tlv_t unpack_fns[] = - { - { NFAPI_UL_CONFIG_REQUEST_UE_INFORMATION_REL8_TAG, &nulsch_pdu_rel13->ue_information.ue_information_rel8, &unpack_ul_config_ue_info_rel8_value}, - { NFAPI_UL_CONFIG_REQUEST_UE_INFORMATION_REL11_TAG, &nulsch_pdu_rel13->ue_information.ue_information_rel11, &unpack_ul_config_ue_info_rel11_value}, - { NFAPI_UL_CONFIG_REQUEST_UE_INFORMATION_REL13_TAG, &nulsch_pdu_rel13->ue_information.ue_information_rel13, &unpack_ul_config_ue_info_rel13_value}, - { NFAPI_UL_CONFIG_REQUEST_NB_HARQ_INFORMATION_REL13_FDD_TAG, &nulsch_pdu_rel13->nb_harq_information.nb_harq_information_rel13_fdd, &unpack_ul_nb_harq_info_rel13_fdd_value}, - }; - - return unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, 0, 0); -} - -static uint8_t unpack_ul_config_nrach_pdu_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_ul_config_nrach_pdu_rel13_t* nrach_pdu_rel13 = (nfapi_ul_config_nrach_pdu_rel13_t*)tlv; - - return (pull8(ppReadPackedMsg, &nrach_pdu_rel13->nprach_config_0, end) && - pull8(ppReadPackedMsg, &nrach_pdu_rel13->nprach_config_1, end) && - pull8(ppReadPackedMsg, &nrach_pdu_rel13->nprach_config_2, end)); -} - - -static uint8_t unpack_ul_config_request_body_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) -{ - #define UL_CONFIG_ULSCH_PDU_UNPACK_FNS(_pdu) \ - { NFAPI_UL_CONFIG_REQUEST_ULSCH_PDU_REL8_TAG, &_pdu.ulsch_pdu_rel8, &unpack_ul_config_ulsch_pdu_rel8_value}, \ - { NFAPI_UL_CONFIG_REQUEST_ULSCH_PDU_REL10_TAG, &_pdu.ulsch_pdu_rel10, &unpack_ul_config_ulsch_pdu_rel10_value}, \ - { NFAPI_UL_CONFIG_REQUEST_ULSCH_PDU_REL11_TAG, &_pdu.ulsch_pdu_rel11, &unpack_ul_config_ulsch_pdu_rel11_value}, \ - { NFAPI_UL_CONFIG_REQUEST_ULSCH_PDU_REL13_TAG, &_pdu.ulsch_pdu_rel13, &unpack_ul_config_ulsch_pdu_rel13_value}, - - #define UL_CONFIG_CQI_RI_INFO_UNPACK_FNS(_pdu) \ - { NFAPI_UL_CONFIG_REQUEST_CQI_RI_INFORMATION_REL8_TAG, &_pdu.cqi_ri_information_rel8, &unpack_ul_config_cqi_ri_info_rel8_value}, \ - { NFAPI_UL_CONFIG_REQUEST_CQI_RI_INFORMATION_REL9_TAG, &_pdu.cqi_ri_information_rel9, &unpack_ul_config_cqi_ri_info_rel9_value}, \ - { NFAPI_UL_CONFIG_REQUEST_CQI_RI_INFORMATION_REL13_TAG, &_pdu.cqi_ri_information_rel13, &unpack_ul_config_cqi_ri_info_rel13_value}, - - #define UL_CONFIG_ULSCH_HARQ_INFO_UNPACK_FNS(_pdu) \ - { NFAPI_UL_CONFIG_REQUEST_ULSCH_HARQ_INFORMATION_REL10_TAG, &_pdu.harq_information_rel10, &unpack_ul_config_ulsch_harq_info_rel10_value},\ - { NFAPI_UL_CONFIG_REQUEST_ULSCH_HARQ_INFORMATION_REL13_TAG, &_pdu.harq_information_rel13, &unpack_ul_config_ulsch_harq_info_rel13_value}, - - #define UL_CONFIG_INIT_TX_PARAMS_UNPACK_FNS(_pdu) \ - { NFAPI_UL_CONFIG_REQUEST_INITIAL_TRANSMISSION_PARAMETERS_REL8_TAG, &_pdu.initial_transmission_parameters_rel8, &unpack_ul_config_cqi_init_tx_params_rel8_value}, - - #define UL_CONFIG_UCI_UE_INFO_UNPACK_FNS(_pdu) \ - { NFAPI_UL_CONFIG_REQUEST_UE_INFORMATION_REL8_TAG, &_pdu.ue_information_rel8, &unpack_ul_config_ue_info_rel8_value}, \ - { NFAPI_UL_CONFIG_REQUEST_UE_INFORMATION_REL11_TAG, &_pdu.ue_information_rel11, &unpack_ul_config_ue_info_rel11_value}, \ - { NFAPI_UL_CONFIG_REQUEST_UE_INFORMATION_REL13_TAG, &_pdu.ue_information_rel13, &unpack_ul_config_ue_info_rel13_value}, - - #define UL_CONFIG_UCI_CQI_INFO_UNPACK_FNS(_pdu) \ - { NFAPI_UL_CONFIG_REQUEST_CQI_INFORMATION_REL8_TAG, &_pdu.cqi_information_rel8, &unpack_ul_config_cqi_info_rel8_value}, \ - { NFAPI_UL_CONFIG_REQUEST_CQI_INFORMATION_REL10_TAG, &_pdu.cqi_information_rel10, &unpack_ul_config_cqi_info_rel10_value}, \ - { NFAPI_UL_CONFIG_REQUEST_CQI_INFORMATION_REL13_TAG, &_pdu.cqi_information_rel13, &unpack_ul_config_cqi_info_rel13_value}, - - #define UL_CONFIG_UCI_SR_INFO_UNPACK_FNS(_pdu) \ - { NFAPI_UL_CONFIG_REQUEST_SR_INFORMATION_REL8_TAG, &_pdu.sr_information_rel8, &unpack_ul_config_sr_info_rel8_value}, \ - { NFAPI_UL_CONFIG_REQUEST_SR_INFORMATION_REL10_TAG, &_pdu.sr_information_rel10, &unpack_ul_config_sr_info_rel10_value}, - - #define UL_CONFIG_UCI_HARQ_INFO_UNPACK_FNS(_pdu) \ - { NFAPI_UL_CONFIG_REQUEST_HARQ_INFORMATION_REL10_TDD_TAG, &_pdu.harq_information_rel10_tdd, &unpack_ul_config_harq_info_rel10_tdd_value}, \ - { NFAPI_UL_CONFIG_REQUEST_HARQ_INFORMATION_REL8_FDD_TAG, &_pdu.harq_information_rel8_fdd, &unpack_ul_config_harq_info_rel8_fdd_value}, \ - { NFAPI_UL_CONFIG_REQUEST_HARQ_INFORMATION_REL9_FDD_TAG, &_pdu.harq_information_rel9_fdd, &unpack_ul_config_harq_info_rel9_fdd_value}, \ - { NFAPI_UL_CONFIG_REQUEST_HARQ_INFORMATION_REL11_TAG, &_pdu.harq_information_rel11, &unpack_ul_config_harq_info_rel11_value}, \ - { NFAPI_UL_CONFIG_REQUEST_HARQ_INFORMATION_REL13_TAG, &_pdu.harq_information_rel13, &unpack_ul_config_harq_info_rel13_value}, - - #define UL_CONFIG_SRS_PDU_UNPACK_FNS(_pdu) \ - { NFAPI_UL_CONFIG_REQUEST_SRS_PDU_REL8_TAG, &_pdu.srs_pdu_rel8, &unpack_ul_config_srs_pdu_rel8_value}, \ - { NFAPI_UL_CONFIG_REQUEST_SRS_PDU_REL10_TAG, &_pdu.srs_pdu_rel10, &unpack_ul_config_srs_pdu_rel10_value}, \ - { NFAPI_UL_CONFIG_REQUEST_SRS_PDU_REL13_TAG, &_pdu.srs_pdu_rel13, &unpack_ul_config_srs_pdu_rel13_value}, - - #define UL_CONFIG_NULSCH_PDU_UNPACK_FNS(_pdu) \ - { NFAPI_UL_CONFIG_REQUEST_NULSCH_PDU_REL13_TAG, &_pdu.nulsch_pdu_rel13, &unpack_ul_config_nulsch_pdu_rel13_value}, - - #define UL_CONFIG_NRACH_PDU_UNPACK_FNS(_pdu) \ - { NFAPI_UL_CONFIG_REQUEST_NRACH_PDU_REL13_TAG, &_pdu.nrach_pdu_rel13, &unpack_ul_config_nrach_pdu_rel13_value}, - - - nfapi_ul_config_request_body_t* value = (nfapi_ul_config_request_body_t*)tlv; - - if(!(pull8(ppReadPackedMsg, &value->number_of_pdus, end) && - pull8(ppReadPackedMsg, &value->rach_prach_frequency_resources, end) && - pull8(ppReadPackedMsg, &value->srs_present, end))) - return 0; - - if(value->number_of_pdus > NFAPI_UL_CONFIG_MAX_PDU) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s number of ul config pdus exceed maxium (count:%d max:%d)\n", __FUNCTION__, value->number_of_pdus, NFAPI_UL_CONFIG_MAX_PDU); - return 0; - } - - if(value->number_of_pdus > 0) - { - value->ul_config_pdu_list = (nfapi_ul_config_request_pdu_t*)nfapi_p7_allocate(sizeof(nfapi_ul_config_request_pdu_t) * value->number_of_pdus, config); - - if(value->ul_config_pdu_list == NULL) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s failed to allocate ul config pdu list (count:%d)\n", __FUNCTION__, value->number_of_pdus); - return 0; - } - } - else - { - value->ul_config_pdu_list = 0; - } - - - uint16_t i; - uint16_t total_number_of_pdus = value->number_of_pdus; - for(i = 0; i < total_number_of_pdus; ++i) - { - nfapi_ul_config_request_pdu_t* pdu = &(value->ul_config_pdu_list[i]); - - if(!(pull8(ppReadPackedMsg, &pdu->pdu_type, end) && - pull8(ppReadPackedMsg, &pdu->pdu_size, end))) - return 0; - - uint8_t *packedPduEnd = (*ppReadPackedMsg) + pdu->pdu_size - 2; - - if(packedPduEnd > end) - { - // pdu end is past buffer end - return 0; - } - - switch(pdu->pdu_type) - { - case NFAPI_UL_CONFIG_ULSCH_PDU_TYPE: - { - unpack_tlv_t unpack_fns[] = - { - UL_CONFIG_ULSCH_PDU_UNPACK_FNS(pdu->ulsch_pdu) - }; - - unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); - } - break; - - case NFAPI_UL_CONFIG_ULSCH_CQI_RI_PDU_TYPE: - { - unpack_tlv_t unpack_fns[] = - { - UL_CONFIG_ULSCH_PDU_UNPACK_FNS(pdu->ulsch_cqi_ri_pdu.ulsch_pdu) - UL_CONFIG_CQI_RI_INFO_UNPACK_FNS(pdu->ulsch_cqi_ri_pdu.cqi_ri_information) - UL_CONFIG_INIT_TX_PARAMS_UNPACK_FNS(pdu->ulsch_cqi_ri_pdu.initial_transmission_parameters) - }; - - unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); - } - break; - case NFAPI_UL_CONFIG_ULSCH_HARQ_PDU_TYPE: - { - unpack_tlv_t unpack_fns[] = - { - UL_CONFIG_ULSCH_PDU_UNPACK_FNS(pdu->ulsch_harq_pdu.ulsch_pdu) - UL_CONFIG_ULSCH_HARQ_INFO_UNPACK_FNS(pdu->ulsch_harq_pdu.harq_information) - UL_CONFIG_INIT_TX_PARAMS_UNPACK_FNS(pdu->ulsch_harq_pdu.initial_transmission_parameters) - }; - - unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); - } - break; - case NFAPI_UL_CONFIG_ULSCH_CQI_HARQ_RI_PDU_TYPE: - { - unpack_tlv_t unpack_fns[] = - { - UL_CONFIG_ULSCH_PDU_UNPACK_FNS(pdu->ulsch_cqi_harq_ri_pdu.ulsch_pdu) - UL_CONFIG_CQI_RI_INFO_UNPACK_FNS(pdu->ulsch_cqi_harq_ri_pdu.cqi_ri_information) - UL_CONFIG_ULSCH_HARQ_INFO_UNPACK_FNS(pdu->ulsch_cqi_harq_ri_pdu.harq_information) - UL_CONFIG_INIT_TX_PARAMS_UNPACK_FNS(pdu->ulsch_cqi_harq_ri_pdu.initial_transmission_parameters) - }; - - unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); - } - break; - case NFAPI_UL_CONFIG_UCI_CQI_PDU_TYPE: - { - unpack_tlv_t unpack_fns[] = - { - UL_CONFIG_UCI_UE_INFO_UNPACK_FNS(pdu->uci_cqi_pdu.ue_information) - UL_CONFIG_UCI_CQI_INFO_UNPACK_FNS(pdu->uci_cqi_pdu.cqi_information) - }; - - unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); - } - break; - case NFAPI_UL_CONFIG_UCI_SR_PDU_TYPE: - { - unpack_tlv_t unpack_fns[] = - { - UL_CONFIG_UCI_UE_INFO_UNPACK_FNS(pdu->uci_sr_pdu.ue_information) - UL_CONFIG_UCI_SR_INFO_UNPACK_FNS(pdu->uci_sr_pdu.sr_information) - }; - - unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); - } - break; - case NFAPI_UL_CONFIG_UCI_HARQ_PDU_TYPE: - { - unpack_tlv_t unpack_fns[] = - { - UL_CONFIG_UCI_UE_INFO_UNPACK_FNS(pdu->uci_harq_pdu.ue_information) - UL_CONFIG_UCI_HARQ_INFO_UNPACK_FNS(pdu->uci_harq_pdu.harq_information) - }; - - unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); - } - break; - case NFAPI_UL_CONFIG_UCI_SR_HARQ_PDU_TYPE: - { - unpack_tlv_t unpack_fns[] = - { - UL_CONFIG_UCI_UE_INFO_UNPACK_FNS(pdu->uci_sr_harq_pdu.ue_information) - UL_CONFIG_UCI_SR_INFO_UNPACK_FNS(pdu->uci_sr_harq_pdu.sr_information) - UL_CONFIG_UCI_HARQ_INFO_UNPACK_FNS(pdu->uci_sr_harq_pdu.harq_information) - }; - - unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); - } - break; - case NFAPI_UL_CONFIG_UCI_CQI_HARQ_PDU_TYPE: - { - unpack_tlv_t unpack_fns[] = - { - UL_CONFIG_UCI_UE_INFO_UNPACK_FNS(pdu->uci_cqi_harq_pdu.ue_information) - UL_CONFIG_UCI_CQI_INFO_UNPACK_FNS(pdu->uci_cqi_harq_pdu.cqi_information) - UL_CONFIG_UCI_HARQ_INFO_UNPACK_FNS(pdu->uci_cqi_harq_pdu.harq_information) - }; - - unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); - } - break; - case NFAPI_UL_CONFIG_UCI_CQI_SR_PDU_TYPE: - { - unpack_tlv_t unpack_fns[] = - { - UL_CONFIG_UCI_UE_INFO_UNPACK_FNS(pdu->uci_cqi_sr_pdu.ue_information) - UL_CONFIG_UCI_CQI_INFO_UNPACK_FNS(pdu->uci_cqi_sr_pdu.cqi_information) - UL_CONFIG_UCI_SR_INFO_UNPACK_FNS(pdu->uci_cqi_sr_pdu.sr_information) - }; - - unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); - } - break; - case NFAPI_UL_CONFIG_UCI_CQI_SR_HARQ_PDU_TYPE: - { - unpack_tlv_t unpack_fns[] = - { - UL_CONFIG_UCI_UE_INFO_UNPACK_FNS(pdu->uci_cqi_sr_harq_pdu.ue_information) - UL_CONFIG_UCI_CQI_INFO_UNPACK_FNS(pdu->uci_cqi_sr_harq_pdu.cqi_information) - UL_CONFIG_UCI_SR_INFO_UNPACK_FNS(pdu->uci_cqi_sr_harq_pdu.sr_information) - UL_CONFIG_UCI_HARQ_INFO_UNPACK_FNS(pdu->uci_cqi_sr_harq_pdu.harq_information) - }; - - unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); - } - break; - case NFAPI_UL_CONFIG_SRS_PDU_TYPE: - { - unpack_tlv_t unpack_fns[] = - { - UL_CONFIG_SRS_PDU_UNPACK_FNS(pdu->srs_pdu) - }; - - unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); - } - break; - case NFAPI_UL_CONFIG_HARQ_BUFFER_PDU_TYPE: - { - unpack_tlv_t unpack_fns[] = - { - UL_CONFIG_UCI_UE_INFO_UNPACK_FNS(pdu->harq_buffer_pdu.ue_information) - }; - - unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); - } - break; - case NFAPI_UL_CONFIG_ULSCH_UCI_CSI_PDU_TYPE: - { - unpack_tlv_t unpack_fns[] = - { - UL_CONFIG_ULSCH_PDU_UNPACK_FNS(pdu->ulsch_uci_csi_pdu.ulsch_pdu) - UL_CONFIG_UCI_CQI_INFO_UNPACK_FNS(pdu->ulsch_uci_csi_pdu.csi_information) - }; - - unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); - } - break; - case NFAPI_UL_CONFIG_ULSCH_UCI_HARQ_PDU_TYPE: - { - unpack_tlv_t unpack_fns[] = - { - UL_CONFIG_ULSCH_PDU_UNPACK_FNS(pdu->ulsch_uci_harq_pdu.ulsch_pdu) - UL_CONFIG_UCI_HARQ_INFO_UNPACK_FNS(pdu->ulsch_uci_harq_pdu.harq_information) - }; - - unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); - } - break; - case NFAPI_UL_CONFIG_ULSCH_CSI_UCI_HARQ_PDU_TYPE: - { - unpack_tlv_t unpack_fns[] = - { - UL_CONFIG_ULSCH_PDU_UNPACK_FNS(pdu->ulsch_csi_uci_harq_pdu.ulsch_pdu) - UL_CONFIG_UCI_CQI_INFO_UNPACK_FNS(pdu->ulsch_csi_uci_harq_pdu.csi_information) - UL_CONFIG_UCI_HARQ_INFO_UNPACK_FNS(pdu->ulsch_csi_uci_harq_pdu.harq_information) - }; - - unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); - } - break; - case NFAPI_UL_CONFIG_NULSCH_PDU_TYPE: - { - unpack_tlv_t unpack_fns[] = - { - UL_CONFIG_NULSCH_PDU_UNPACK_FNS(pdu->nulsch_pdu) - }; - - unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); - } - break; - case NFAPI_UL_CONFIG_NRACH_PDU_TYPE: - { - unpack_tlv_t unpack_fns[] = - { - UL_CONFIG_NRACH_PDU_UNPACK_FNS(pdu->nrach_pdu) - }; - - unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); - } - break; - } - } - return 1; -} - - -static uint8_t unpack_ul_config_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config) -{ - nfapi_ul_config_request_t *pNfapiMsg = (nfapi_ul_config_request_t*)msg; - - unpack_p7_tlv_t unpack_fns[] = - { - { NFAPI_UL_CONFIG_REQUEST_BODY_TAG, &pNfapiMsg->ul_config_request_body, &unpack_ul_config_request_body_value}, - }; - - return (pull16(ppReadPackedMsg, &pNfapiMsg->sfn_sf, end) && - unpack_p7_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); -} - -static uint8_t unpack_hi_dci0_hi_pdu_rel8_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_hi_dci0_hi_pdu_rel8_t* hi_pdu_rel8 = (nfapi_hi_dci0_hi_pdu_rel8_t*)tlv; - - return( pull8(ppReadPackedMsg, &hi_pdu_rel8->resource_block_start, end) && - pull8(ppReadPackedMsg, &hi_pdu_rel8->cyclic_shift_2_for_drms, end) && - pull8(ppReadPackedMsg, &hi_pdu_rel8->hi_value, end) && - pull8(ppReadPackedMsg, &hi_pdu_rel8->i_phich, end) && - pull16(ppReadPackedMsg, &hi_pdu_rel8->transmission_power, end)); -} - -static uint8_t unpack_hi_dci0_hi_pdu_rel10_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_hi_dci0_hi_pdu_rel10_t* hi_pdu_rel10 = (nfapi_hi_dci0_hi_pdu_rel10_t*)tlv; - - return (pull8(ppReadPackedMsg, &hi_pdu_rel10->flag_tb2, end) && - pull8(ppReadPackedMsg, &hi_pdu_rel10->hi_value_2, end)); -} - -static uint8_t unpack_hi_dci0_dci_pdu_rel8_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_hi_dci0_dci_pdu_rel8_t* dci_pdu_rel8 = (nfapi_hi_dci0_dci_pdu_rel8_t*)tlv; - - return (pull8(ppReadPackedMsg, &dci_pdu_rel8->dci_format, end) && - pull8(ppReadPackedMsg, &dci_pdu_rel8->cce_index, end) && - pull8(ppReadPackedMsg, &dci_pdu_rel8->aggregation_level, end) && - pull16(ppReadPackedMsg, &dci_pdu_rel8->rnti, end) && - pull8(ppReadPackedMsg, &dci_pdu_rel8->resource_block_start, end) && - pull8(ppReadPackedMsg, &dci_pdu_rel8->number_of_resource_block, end) && - pull8(ppReadPackedMsg, &dci_pdu_rel8->mcs_1, end) && - pull8(ppReadPackedMsg, &dci_pdu_rel8->cyclic_shift_2_for_drms, end) && - pull8(ppReadPackedMsg, &dci_pdu_rel8->frequency_hopping_enabled_flag, end) && - pull8(ppReadPackedMsg, &dci_pdu_rel8->frequency_hopping_bits, end) && - pull8(ppReadPackedMsg, &dci_pdu_rel8->new_data_indication_1, end) && - pull8(ppReadPackedMsg, &dci_pdu_rel8->ue_tx_antenna_seleciton, end) && - pull8(ppReadPackedMsg, &dci_pdu_rel8->tpc, end) && - pull8(ppReadPackedMsg, &dci_pdu_rel8->cqi_csi_request, end) && - pull8(ppReadPackedMsg, &dci_pdu_rel8->ul_index, end) && - pull8(ppReadPackedMsg, &dci_pdu_rel8->dl_assignment_index, end) && - pull32(ppReadPackedMsg, &dci_pdu_rel8->tpc_bitmap, end) && - pull16(ppReadPackedMsg, &dci_pdu_rel8->transmission_power, end)); -} - -static uint8_t unpack_hi_dci0_dci_pdu_rel10_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_hi_dci0_dci_pdu_rel10_t* dci_pdu_rel10 = (nfapi_hi_dci0_dci_pdu_rel10_t*)tlv; - - return (pull8(ppReadPackedMsg, &dci_pdu_rel10->cross_carrier_scheduling_flag, end) && - pull8(ppReadPackedMsg, &dci_pdu_rel10->carrier_indicator, end) && - pull8(ppReadPackedMsg, &dci_pdu_rel10->size_of_cqi_csi_feild, end) && - pull8(ppReadPackedMsg, &dci_pdu_rel10->srs_flag, end) && - pull8(ppReadPackedMsg, &dci_pdu_rel10->srs_request, end) && - pull8(ppReadPackedMsg, &dci_pdu_rel10->resource_allocation_flag, end) && - pull8(ppReadPackedMsg, &dci_pdu_rel10->resource_allocation_type, end) && - pull32(ppReadPackedMsg, &dci_pdu_rel10->resource_block_coding, end) && - pull8(ppReadPackedMsg, &dci_pdu_rel10->mcs_2, end) && - pull8(ppReadPackedMsg, &dci_pdu_rel10->new_data_indication_2, end) && - pull8(ppReadPackedMsg, &dci_pdu_rel10->number_of_antenna_ports, end) && - pull8(ppReadPackedMsg, &dci_pdu_rel10->tpmi, end) && - pull8(ppReadPackedMsg, &dci_pdu_rel10->total_dci_length_including_padding, end) && - pull8(ppReadPackedMsg, &dci_pdu_rel10->n_ul_rb, end)); -} - -static uint8_t unpack_hi_dci0_dci_pdu_rel12_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_hi_dci0_dci_pdu_rel12_t* dci_pdu_rel12 = (nfapi_hi_dci0_dci_pdu_rel12_t*)tlv; - - return ( pull8(ppReadPackedMsg, &dci_pdu_rel12->pscch_resource, end) && - pull8(ppReadPackedMsg, &dci_pdu_rel12->time_resource_pattern, end)); -} - -static uint8_t unpack_hi_dci0_mpdcch_dci_pdu_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_hi_dci0_mpdcch_dci_pdu_rel13_t* value = (nfapi_hi_dci0_mpdcch_dci_pdu_rel13_t*)tlv; - - return (pull8(ppReadPackedMsg, &value->mpdcch_narrowband, end) && - pull8(ppReadPackedMsg, &value->number_of_prb_pairs, end) && - pull8(ppReadPackedMsg, &value->resource_block_assignment, end) && - pull8(ppReadPackedMsg, &value->mpdcch_transmission_type, end) && - pull8(ppReadPackedMsg, &value->start_symbol, end) && - pull8(ppReadPackedMsg, &value->ecce_index, end) && - pull8(ppReadPackedMsg, &value->aggreagation_level, end) && - pull8(ppReadPackedMsg, &value->rnti_type, end) && - pull16(ppReadPackedMsg, &value->rnti, end) && - pull8(ppReadPackedMsg, &value->ce_mode, end) && - pull16(ppReadPackedMsg, &value->drms_scrambling_init, end) && - pull16(ppReadPackedMsg, &value->initial_transmission_sf_io, end) && - pull16(ppReadPackedMsg, &value->transmission_power, end) && - pull8(ppReadPackedMsg, &value->dci_format, end) && - pull8(ppReadPackedMsg, &value->resource_block_start, end) && - pull8(ppReadPackedMsg, &value->number_of_resource_blocks, end) && - pull8(ppReadPackedMsg, &value->mcs, end) && - pull8(ppReadPackedMsg, &value->pusch_repetition_levels, end) && - pull8(ppReadPackedMsg, &value->frequency_hopping_flag, end) && - pull8(ppReadPackedMsg, &value->new_data_indication, end) && - pull8(ppReadPackedMsg, &value->harq_process, end) && - pull8(ppReadPackedMsg, &value->redudency_version, end) && - pull8(ppReadPackedMsg, &value->tpc, end) && - pull8(ppReadPackedMsg, &value->csi_request, end) && - pull8(ppReadPackedMsg, &value->ul_inex, end) && - pull8(ppReadPackedMsg, &value->dai_presence_flag, end) && - pull8(ppReadPackedMsg, &value->dl_assignment_index, end) && - pull8(ppReadPackedMsg, &value->srs_request, end) && - pull8(ppReadPackedMsg, &value->dci_subframe_repetition_number, end) && - pull32(ppReadPackedMsg, &value->tcp_bitmap, end) && - pull8(ppReadPackedMsg, &value->total_dci_length_include_padding, end) && - pull8(ppReadPackedMsg, &value->number_of_tx_antenna_ports, end) && - pullarray16(ppReadPackedMsg, value->precoding_value, NFAPI_MAX_TX_PHYSICAL_ANTENNA_PORTS, value->number_of_tx_antenna_ports, end)); -} - -static uint8_t unpack_hi_dci0_npdcch_dci_pdu_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_hi_dci0_npdcch_dci_pdu_rel13_t* value = (nfapi_hi_dci0_npdcch_dci_pdu_rel13_t*)tlv; - - return (pull8(ppReadPackedMsg, &value->ncce_index, end) && - pull8(ppReadPackedMsg, &value->aggregation_level, end) && - pull8(ppReadPackedMsg, &value->start_symbol, end) && - pull16(ppReadPackedMsg, &value->rnti, end) && - pull8(ppReadPackedMsg, &value->scrambling_reinitialization_batch_index, end) && - pull8(ppReadPackedMsg, &value->nrs_antenna_ports_assumed_by_the_ue, end) && - pull8(ppReadPackedMsg, &value->subcarrier_indication, end) && - pull8(ppReadPackedMsg, &value->resource_assignment, end) && - pull8(ppReadPackedMsg, &value->scheduling_delay, end) && - pull8(ppReadPackedMsg, &value->mcs, end) && - pull8(ppReadPackedMsg, &value->redudancy_version, end) && - pull8(ppReadPackedMsg, &value->repetition_number, end) && - pull8(ppReadPackedMsg, &value->new_data_indicator, end) && - pull8(ppReadPackedMsg, &value->dci_subframe_repetition_number, end)); -} - -static uint8_t unpack_hi_dci0_request_body_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) -{ - nfapi_hi_dci0_request_body_t* value = (nfapi_hi_dci0_request_body_t*)tlv; - - if(!(pull16(ppReadPackedMsg, &value->sfnsf, end) && - pull8(ppReadPackedMsg, &value->number_of_dci, end) && - pull8(ppReadPackedMsg, &value->number_of_hi, end))) - return 0; - - uint8_t totalNumPdus = value->number_of_hi + value->number_of_dci; - - if(totalNumPdus > NFAPI_HI_DCI0_MAX_PDU) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s number of dci0 pdu's exceed maxium (count:%d max:%d)\n", __FUNCTION__, totalNumPdus, NFAPI_HI_DCI0_MAX_PDU); - return 0; - } - - if(totalNumPdus > 0) - { - value->hi_dci0_pdu_list = (nfapi_hi_dci0_request_pdu_t*)nfapi_p7_allocate(sizeof(nfapi_hi_dci0_request_pdu_t) * totalNumPdus, config); - if(value->hi_dci0_pdu_list == NULL) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s failed to allocate hi dci0 pdu list (count:%d)\n", __FUNCTION__, totalNumPdus); - return 0; - } - } - else - { - value->hi_dci0_pdu_list = 0; - } - - uint8_t i; - for(i = 0; i < totalNumPdus; ++i) - { - nfapi_hi_dci0_request_pdu_t* pdu = &(value->hi_dci0_pdu_list[i]); - - if(!(pull8(ppReadPackedMsg, &pdu->pdu_type, end) && - pull8(ppReadPackedMsg, &pdu->pdu_size, end))) - return 0; - - uint8_t *packedPduEnd = (*ppReadPackedMsg) + pdu->pdu_size - 2; - - if(packedPduEnd > end) - { - // pdu end if past buffer end - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s pdu size to big %d %d\n", __FUNCTION__, packedPduEnd, end); - return 0; - } - - switch(pdu->pdu_type) - { - case NFAPI_HI_DCI0_HI_PDU_TYPE: - { - unpack_tlv_t unpack_fns[] = - { - { NFAPI_HI_DCI0_REQUEST_HI_PDU_REL8_TAG, &pdu->hi_pdu.hi_pdu_rel8, &unpack_hi_dci0_hi_pdu_rel8_value}, - { NFAPI_HI_DCI0_REQUEST_HI_PDU_REL10_TAG, &pdu->hi_pdu.hi_pdu_rel10, &unpack_hi_dci0_hi_pdu_rel10_value}, - }; - - unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); - } - break; - case NFAPI_HI_DCI0_DCI_PDU_TYPE: - { - unpack_tlv_t unpack_fns[] = - { - { NFAPI_HI_DCI0_REQUEST_DCI_PDU_REL8_TAG, &pdu->dci_pdu.dci_pdu_rel8, &unpack_hi_dci0_dci_pdu_rel8_value}, - { NFAPI_HI_DCI0_REQUEST_DCI_PDU_REL10_TAG, &pdu->dci_pdu.dci_pdu_rel10, &unpack_hi_dci0_dci_pdu_rel10_value}, - { NFAPI_HI_DCI0_REQUEST_DCI_PDU_REL12_TAG, &pdu->dci_pdu.dci_pdu_rel12, &unpack_hi_dci0_dci_pdu_rel12_value}, - }; - - unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); - } - break; - case NFAPI_HI_DCI0_EPDCCH_DCI_PDU_TYPE: - { - unpack_tlv_t unpack_fns[] = - { - { NFAPI_HI_DCI0_REQUEST_EPDCCH_DCI_PDU_REL8_TAG, &pdu->epdcch_dci_pdu.epdcch_dci_pdu_rel8, &unpack_hi_dci0_dci_pdu_rel8_value}, - { NFAPI_HI_DCI0_REQUEST_EPDCCH_DCI_PDU_REL10_TAG, &pdu->epdcch_dci_pdu.epdcch_dci_pdu_rel10, &unpack_hi_dci0_dci_pdu_rel10_value}, - { NFAPI_HI_DCI0_REQUEST_EPDCCH_PARAMETERS_REL11_TAG, &pdu->epdcch_dci_pdu.epdcch_parameters_rel11, &unpack_dl_config_epdcch_params_rel11_value}, - }; - - unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); - } - break; - case NFAPI_HI_DCI0_MPDCCH_DCI_PDU_TYPE: - { - unpack_tlv_t unpack_fns[] = - { - { NFAPI_HI_DCI0_REQUEST_MPDCCH_DCI_PDU_REL13_TAG, &pdu->mpdcch_dci_pdu.mpdcch_dci_pdu_rel13, &unpack_hi_dci0_mpdcch_dci_pdu_rel13_value}, - }; - - unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); - } - break; - case NFAPI_HI_DCI0_NPDCCH_DCI_PDU_TYPE: - { - unpack_tlv_t unpack_fns[] = - { - { NFAPI_HI_DCI0_REQUEST_NPDCCH_DCI_PDU_REL13_TAG, &pdu->npdcch_dci_pdu.npdcch_dci_pdu_rel13, &unpack_hi_dci0_npdcch_dci_pdu_rel13_value}, - }; - - unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); - } - break; - default: - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "FIXME : Invalid pdu type %d \n", pdu->pdu_type ); - } - break; - }; - } - - return 1; -} -//unpack_ul_dci_pdu_list_value - -static uint8_t unpack_ul_dci_pdu_list_value(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg) -{ - nfapi_nr_ul_dci_request_pdus_t* value = (nfapi_nr_ul_dci_request_pdus_t*)msg; - for(uint8_t i = 0; i < MAX_DCI_CORESET; ++i) - { - if(!(pull16(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].RNTI, end) && - pull16(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].ScramblingId, end) && - - pull16(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].ScramblingRNTI, end) && - pull8(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].CceIndex, end) && - pull8(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].AggregationLevel, end) && - pull8(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].beta_PDCCH_1_0, end) && - - pull8(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].powerControlOffsetSS, end) && - pull16(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].PayloadSizeBits, end) && - - pullarray8(ppReadPackedMsg, value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].Payload, value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].PayloadSizeBits, value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].PayloadSizeBits, end))) - - return 0; - } - - return (pull16(ppReadPackedMsg, &value->PDUType, end) && - pull16(ppReadPackedMsg, &value->PDUSize, end) && - pull16(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.BWPSize, end) && - pull16(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.BWPStart, end) && - pull8(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.SubcarrierSpacing, end) && - pull8(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.CyclicPrefix, end) && - - pull8(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.StartSymbolIndex, end) && - pull8(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.DurationSymbols, end) && - pullarray8(ppReadPackedMsg, value->pdcch_pdu.pdcch_pdu_rel15.FreqDomainResource, 6, 6, end) && - pull8(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.CceRegMappingType, end) && - - pull8(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.RegBundleSize, end) && - pull8(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.InterleaverSize, end) && - pull8(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.CoreSetType, end) && - pull16(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.ShiftIndex, end) && - pull8(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.precoderGranularity, end) && - pull16(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.numDlDci, end)); - -} - -static uint8_t unpack_ul_dci_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config) -{ -nfapi_nr_ul_dci_request_t *pNfapiMsg = (nfapi_nr_ul_dci_request_t*)msg; - - if (!(pull16(ppReadPackedMsg, &pNfapiMsg->SFN, end) && - pull16(ppReadPackedMsg, &pNfapiMsg->Slot, end) && - pull8(ppReadPackedMsg, &pNfapiMsg->numPdus, end) - )) - return 0; - for(int i=0; i< pNfapiMsg->numPdus; i++) - { - if (!unpack_ul_dci_pdu_list_value(ppReadPackedMsg, end, &pNfapiMsg->ul_dci_pdu_list[i])) - return 0; - } - - return 1; - -} - -static uint8_t unpack_hi_dci0_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config) -{ - nfapi_hi_dci0_request_t *pNfapiMsg = (nfapi_hi_dci0_request_t*)msg; - - unpack_p7_tlv_t unpack_fns[] = - { - { NFAPI_HI_DCI0_REQUEST_BODY_TAG, &pNfapiMsg->hi_dci0_request_body, &unpack_hi_dci0_request_body_value}, - }; - - return (pull16(ppReadPackedMsg, &pNfapiMsg->sfn_sf, end) && - unpack_p7_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); - -} -static uint8_t unpack_tx_data_pdu_list_value(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg) -{ - nfapi_nr_pdu_t* pNfapiMsg = (nfapi_nr_pdu_t*)msg; - - if(!(pull32(ppReadPackedMsg, &pNfapiMsg->num_TLV, end) && - pull16(ppReadPackedMsg, &pNfapiMsg->PDU_index, end) && - pull16(ppReadPackedMsg, &pNfapiMsg->PDU_length, end) - )) - return 0; - - uint16_t i = 0; - uint16_t total_number_of_tlvs = pNfapiMsg->num_TLV; - for(; i < total_number_of_tlvs; ++i) - { - - if (!(pull16(ppReadPackedMsg, &pNfapiMsg->TLVs[i].length, end) && - pull16(ppReadPackedMsg, &pNfapiMsg->TLVs[i].tag, end))) - return 0; - - switch(pNfapiMsg->TLVs[i].tag){ - case 0: - { - if(!pullarray32(ppReadPackedMsg, pNfapiMsg->TLVs[i].value.direct, 16384, pNfapiMsg->TLVs[i].length, end)) - return 0; - break; - - } - - case 1: - { - if(!pullarray32(ppReadPackedMsg, pNfapiMsg->TLVs[i].value.ptr, pNfapiMsg->TLVs[i].length , pNfapiMsg->TLVs[i].length, end)) - return 0; - break; - - } - - default: - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "FIXME : Invalid tag value %d \n", pNfapiMsg->TLVs[i].tag ); - break; - } - - } - } - - - return 1; -} - -static uint8_t unpack_tx_data_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config) -{ - nfapi_nr_tx_data_request_t *pNfapiMsg = (nfapi_nr_tx_data_request_t*)msg; - - if(!(pull16(ppReadPackedMsg, &pNfapiMsg->SFN, end) && - pull16(ppReadPackedMsg, &pNfapiMsg->Slot, end) && - pull16(ppReadPackedMsg, &pNfapiMsg->Number_of_PDUs, end))) - return 0; - - for(int i=0; i< pNfapiMsg->Number_of_PDUs; i++) - { - if (!unpack_tx_data_pdu_list_value(ppReadPackedMsg, end, &pNfapiMsg->pdu_list[i])) - return 0; - } - - return 1; -} - -static uint8_t unpack_tx_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config) -{ - uint8_t proceed = 1; - nfapi_tx_request_t *pNfapiMsg = (nfapi_tx_request_t*)msg; - - if(pull16(ppReadPackedMsg, &pNfapiMsg->sfn_sf, end) == 0) - return 0; - - while (((uint8_t*)(*ppReadPackedMsg) < end) && proceed) - { - nfapi_tl_t generic_tl; - if(unpack_tl(ppReadPackedMsg, &generic_tl, end) == 0) - return 0; - - switch(generic_tl.tag) - { - case NFAPI_TX_REQUEST_BODY_TAG: - { - pNfapiMsg->tx_request_body.tl = generic_tl; - - if( pull16(ppReadPackedMsg, &pNfapiMsg->tx_request_body.number_of_pdus, end) == 0) - return 0; - - if(pNfapiMsg->tx_request_body.number_of_pdus > NFAPI_TX_MAX_PDU) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s number of tx pdu's exceed maxium (count:%d max:%d)\n", __FUNCTION__, pNfapiMsg->tx_request_body.number_of_pdus, NFAPI_TX_MAX_PDU); - return 0; - } - - if(pNfapiMsg->tx_request_body.number_of_pdus > 0) - { - pNfapiMsg->tx_request_body.tx_pdu_list = (nfapi_tx_request_pdu_t*)nfapi_p7_allocate(sizeof(nfapi_tx_request_pdu_t) * pNfapiMsg->tx_request_body.number_of_pdus, config); - if(pNfapiMsg->tx_request_body.tx_pdu_list == NULL) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s failed to allocate tx pdu list (count:%d)\n", __FUNCTION__, pNfapiMsg->tx_request_body.number_of_pdus); - return 0; - } - } - else - { - pNfapiMsg->tx_request_body.tx_pdu_list = 0; - } - - - uint16_t i; - uint16_t totalNumPdus = pNfapiMsg->tx_request_body.number_of_pdus; - for(i = 0; i < totalNumPdus; ++i) - { - nfapi_tx_request_pdu_t* pdu = &(pNfapiMsg->tx_request_body.tx_pdu_list[i]); - if (pdu) { - uint16_t length = 0; - uint16_t index = 0; - - if(!(pull16(ppReadPackedMsg, &length, end) && - pull16(ppReadPackedMsg, &index, end))) - return 0; - - pdu->pdu_length = length; - pdu->pdu_index = index; - - - // TODO : May need to rethink this bit - pdu->num_segments = 1; - pdu->segments[0].segment_length = pdu->pdu_length; - pdu->segments[0].segment_data = nfapi_p7_allocate(pdu->pdu_length, config); - - if(pdu->segments[0].segment_data) - { - if(!pullarray8(ppReadPackedMsg, pdu->segments[0].segment_data, pdu->segments[0].segment_length, pdu->segments[0].segment_length, end)) - return 0; - if (pdu->segments[0].segment_length == 3) - { - NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() BCH? segment_data:%x %x %x\n", __FUNCTION__, - pdu->segments[0].segment_data[0], - pdu->segments[0].segment_data[1], - pdu->segments[0].segment_data[2] - ); - } - } - else - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "unpack_tx_request: Failed to allocate pdu (len:%d) %d/%d %d\n", pdu->pdu_length, totalNumPdus, i, pdu->pdu_index); - } - } else { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "NULL pdu\n"); - } - } - } - break; - default: - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "unpack_tx_request FIXME : Invalid pdu type %d \n", generic_tl.tag ); - } - break; - }; - } - - return 1; -} - -static uint8_t unpack_ue_release_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config) -{ - uint8_t proceed = 1; - nfapi_ue_release_request_t *pNfapiMsg = (nfapi_ue_release_request_t*)msg; - - if(pull16(ppReadPackedMsg, &pNfapiMsg->sfn_sf, end) == 0) - return 0; - - while (((uint8_t*)(*ppReadPackedMsg) < end) && proceed) - { - nfapi_tl_t generic_tl; - if(unpack_tl(ppReadPackedMsg, &generic_tl, end) == 0) - return 0; - - switch(generic_tl.tag) - { - case NFAPI_UE_RELEASE_BODY_TAG: - { - pNfapiMsg->ue_release_request_body.tl = generic_tl; - if( pull16(ppReadPackedMsg, &pNfapiMsg->ue_release_request_body.number_of_TLVs, end) == 0) - return 0; - - if(pNfapiMsg->ue_release_request_body.number_of_TLVs > NFAPI_RELEASE_MAX_RNTI) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s number of relese rnti's exceed maxium (count:%d max:%d)\n", __FUNCTION__, pNfapiMsg->ue_release_request_body.number_of_TLVs, NFAPI_RELEASE_MAX_RNTI); - return 0; - } else { - uint8_t j; - uint16_t num = pNfapiMsg->ue_release_request_body.number_of_TLVs; - for(j = 0; j < num; ++j){ - if(pull16(ppReadPackedMsg, &pNfapiMsg->ue_release_request_body.ue_release_request_TLVs_list[j].rnti, end) == 0){ - return 0; - } - } - } - } - break; - default: - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "unpack_ue_release_request FIXME : Invalid type %d \n", generic_tl.tag ); - } - break; - }; - } - - return 1; -} - -static uint8_t unpack_harq_indication_tdd_harq_data_bundling(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_harq_indication_tdd_harq_data_bundling_t* value = (nfapi_harq_indication_tdd_harq_data_bundling_t*)tlv; - - return (pull8(ppReadPackedMsg, &value->value_0, end) && - pull8(ppReadPackedMsg, &value->value_1, end)); -} - -static uint8_t unpack_harq_indication_tdd_harq_data_multiplexing(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_harq_indication_tdd_harq_data_multiplexing_t* value = (nfapi_harq_indication_tdd_harq_data_multiplexing_t*)tlv; - - return (pull8(ppReadPackedMsg, &value->value_0, end) && - pull8(ppReadPackedMsg, &value->value_1, end) && - pull8(ppReadPackedMsg, &value->value_2, end) && - pull8(ppReadPackedMsg, &value->value_3, end)); -} -static uint8_t unpack_harq_indication_tdd_harq_data_special_bundling(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_harq_indication_tdd_harq_data_special_bundling_t* value = (nfapi_harq_indication_tdd_harq_data_special_bundling_t*)tlv; - return ( pull8(ppReadPackedMsg, &value->value_0, end)); -} -static uint8_t unpack_harq_indication_tdd_harq_data(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_harq_indication_tdd_harq_data_t* value = (nfapi_harq_indication_tdd_harq_data_t*)tlv; - return (pull8(ppReadPackedMsg, &value->value_0, end)); -} - -static uint8_t unpack_harq_indication_tdd_rel8_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_harq_indication_tdd_rel8_t* value = (nfapi_harq_indication_tdd_rel8_t*)tlv; - - if(!(pull8(ppReadPackedMsg, &value->mode, end) && - pull8(ppReadPackedMsg, &value->number_of_ack_nack, end))) - return 0; - - uint8_t result = 0; - switch(value->mode) - { - case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_BUNDLING: - result = unpack_harq_indication_tdd_harq_data_bundling(&value->harq_data.bundling, ppReadPackedMsg, end); - break; - case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_MULIPLEXING: - result = unpack_harq_indication_tdd_harq_data_multiplexing(&value->harq_data.multiplex, ppReadPackedMsg, end); - break; - case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_SPECIAL_BUNDLING: - result = unpack_harq_indication_tdd_harq_data_special_bundling(&value->harq_data.special_bundling, ppReadPackedMsg, end); - break; - case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_FORMAT_3: - case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_CHANNEL_SELECTION: - result = 1; - break; - default: - // TODO add error message - return 0; - break; - } - return result; -} - -static uint8_t unpack_harq_indication_tdd_rel9_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_harq_indication_tdd_rel9_t* value = (nfapi_harq_indication_tdd_rel9_t*)tlv; - - if(!(pull8(ppReadPackedMsg, &value->mode, end) && - pull8(ppReadPackedMsg, &value->number_of_ack_nack, end))) - return 0; - - if(value->number_of_ack_nack > NFAPI_MAX_NUMBER_ACK_NACK_TDD) - { - // TODO : add error message - return 0; - } - - uint16_t idx = 0; - for(idx = 0; idx < value->number_of_ack_nack; ++idx) - { - uint8_t result = 0; - switch(value->mode) - { - case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_BUNDLING: - result = unpack_harq_indication_tdd_harq_data(&value->harq_data[idx].bundling, ppReadPackedMsg, end); - break; - case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_MULIPLEXING: - result = unpack_harq_indication_tdd_harq_data(&value->harq_data[idx].multiplex, ppReadPackedMsg, end); - break; - case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_SPECIAL_BUNDLING: - result = unpack_harq_indication_tdd_harq_data_special_bundling(&value->harq_data[idx].special_bundling, ppReadPackedMsg, end); - break; - case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_CHANNEL_SELECTION: - result = unpack_harq_indication_tdd_harq_data(&value->harq_data[idx].channel_selection, ppReadPackedMsg, end); - break; - case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_FORMAT_3: - result = unpack_harq_indication_tdd_harq_data(&value->harq_data[idx].format_3, ppReadPackedMsg, end); - break; - default: - // TODO add error message - return 0; - break; - } - - if(result == 0) - return 0; - } - return 1; -} - -static uint8_t unpack_harq_indication_tdd_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_harq_indication_tdd_rel13_t* value = (nfapi_harq_indication_tdd_rel13_t*)tlv; - - if(!(pull8(ppReadPackedMsg, &value->mode, end) && - pull16(ppReadPackedMsg, &value->number_of_ack_nack, end))) - return 0; - - if(value->number_of_ack_nack > NFAPI_MAX_NUMBER_ACK_NACK_TDD) - { - // TODO : add error message - return 0; - } - - uint16_t idx = 0; - for(idx = 0; idx < value->number_of_ack_nack; ++idx) - { - uint8_t result = 0; - switch(value->mode) - { - case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_BUNDLING: - result = unpack_harq_indication_tdd_harq_data(&value->harq_data[idx].bundling, ppReadPackedMsg, end); - break; - case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_MULIPLEXING: - result = unpack_harq_indication_tdd_harq_data(&value->harq_data[idx].multiplex, ppReadPackedMsg, end); - break; - case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_SPECIAL_BUNDLING: - result = unpack_harq_indication_tdd_harq_data_special_bundling(&value->harq_data[idx].special_bundling, ppReadPackedMsg, end); - break; - case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_CHANNEL_SELECTION: - result = unpack_harq_indication_tdd_harq_data(&value->harq_data[idx].channel_selection, ppReadPackedMsg, end); - break; - case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_FORMAT_3: - result = unpack_harq_indication_tdd_harq_data(&value->harq_data[idx].format_3, ppReadPackedMsg, end); - break; - case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_FORMAT_4: - result = unpack_harq_indication_tdd_harq_data(&value->harq_data[idx].format_4, ppReadPackedMsg, end); - break; - case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_FORMAT_5: - result = unpack_harq_indication_tdd_harq_data(&value->harq_data[idx].format_5, ppReadPackedMsg, end); - break; - default: - // TODO add error message - return 0; - break; - } - - if(result == 0) - return 0; - } - return 1; -} - -static uint8_t unpack_harq_indication_fdd_rel8_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_harq_indication_fdd_rel8_t* value = (nfapi_harq_indication_fdd_rel8_t*)tlv; - return (pull8(ppReadPackedMsg, &value->harq_tb1, end) && - pull8(ppReadPackedMsg, &value->harq_tb2, end)); -} - -static uint8_t unpack_harq_indication_fdd_rel9_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_harq_indication_fdd_rel9_t* value = (nfapi_harq_indication_fdd_rel9_t*)tlv; - - return (pull8(ppReadPackedMsg, &value->mode, end) && - pull8(ppReadPackedMsg, &value->number_of_ack_nack, end) && - pullarray8(ppReadPackedMsg, value->harq_tb_n, NFAPI_HARQ_ACK_NACK_REL9_MAX, value->number_of_ack_nack, end)); -} - -static uint8_t unpack_harq_indication_fdd_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_harq_indication_fdd_rel13_t* value = (nfapi_harq_indication_fdd_rel13_t*)tlv; - - return (pull8(ppReadPackedMsg, &value->mode, end) && - pull16(ppReadPackedMsg, &value->number_of_ack_nack, end) && - pullarray8(ppReadPackedMsg, value->harq_tb_n, NFAPI_HARQ_ACK_NACK_REL13_MAX, value->number_of_ack_nack, end)); -} - -static uint8_t unpack_ul_cqi_information_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_ul_cqi_information_t* value = (nfapi_ul_cqi_information_t*)tlv; - - return (pull8(ppReadPackedMsg, &value->ul_cqi, end) && - pull8(ppReadPackedMsg, &value->channel, end)); -} - - - -static uint8_t unpack_harq_indication_body_value(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) -{ - nfapi_harq_indication_body_t* value = (nfapi_harq_indication_body_t*)tlv; - uint8_t* harqBodyEnd = *ppReadPackedMsg + value->tl.length; - - if(harqBodyEnd > end) - return 0; - - if(pull16(ppReadPackedMsg, &value->number_of_harqs, end) == 0) - return 0; - - if(value->number_of_harqs > NFAPI_HARQ_IND_MAX_PDU) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s number of harq ind pdus exceed maxium (count:%d max:%d)\n", __FUNCTION__, value->number_of_harqs, NFAPI_HARQ_IND_MAX_PDU); - return 0; - } - - value->harq_pdu_list = (nfapi_harq_indication_pdu_t*)nfapi_p7_allocate(sizeof(nfapi_harq_indication_pdu_t) * value->number_of_harqs, config); - if(value->harq_pdu_list == NULL) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s failed to allocate harq ind pdu list (count:%d)\n", __FUNCTION__, value->number_of_harqs); - return 0; - } - - uint8_t i = 0; - for(i = 0; i < value->number_of_harqs; ++i) - { - nfapi_harq_indication_pdu_t* pdu = &(value->harq_pdu_list[i]); - if(pull16(ppReadPackedMsg, &pdu->instance_length, end) == 0) - return 0; - - uint8_t* harqPduInstanceEnd = *ppReadPackedMsg + pdu->instance_length; - - unpack_tlv_t unpack_fns[] = - { - { NFAPI_RX_UE_INFORMATION_TAG, &pdu->rx_ue_information, unpack_rx_ue_information_value }, - { NFAPI_HARQ_INDICATION_TDD_REL8_TAG, &pdu->harq_indication_tdd_rel8, &unpack_harq_indication_tdd_rel8_value}, - { NFAPI_HARQ_INDICATION_TDD_REL9_TAG, &pdu->harq_indication_tdd_rel9, &unpack_harq_indication_tdd_rel9_value}, - { NFAPI_HARQ_INDICATION_TDD_REL13_TAG, &pdu->harq_indication_tdd_rel13, &unpack_harq_indication_tdd_rel13_value}, - { NFAPI_HARQ_INDICATION_FDD_REL8_TAG, &pdu->harq_indication_fdd_rel8, &unpack_harq_indication_fdd_rel8_value}, - { NFAPI_HARQ_INDICATION_FDD_REL9_TAG, &pdu->harq_indication_fdd_rel9, &unpack_harq_indication_fdd_rel9_value}, - { NFAPI_HARQ_INDICATION_FDD_REL13_TAG, &pdu->harq_indication_fdd_rel13, &unpack_harq_indication_fdd_rel13_value}, - { NFAPI_UL_CQI_INFORMATION_TAG, &pdu->ul_cqi_information, &unpack_ul_cqi_information_value} - }; - - if(unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, harqPduInstanceEnd, 0, 0) == 0) - return 0; - - } - - return 1; -} - -static uint8_t unpack_harq_indication(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config) -{ - nfapi_harq_indication_t *pNfapiMsg = (nfapi_harq_indication_t*)msg; - - unpack_p7_tlv_t unpack_fns[] = - { - { NFAPI_HARQ_INDICATION_BODY_TAG, &pNfapiMsg->harq_indication_body, &unpack_harq_indication_body_value}, - }; - - return (pull16(ppReadPackedMsg, &pNfapiMsg->sfn_sf, end) && - unpack_p7_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); -} - -static uint8_t unpack_crc_indication_rel8_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_crc_indication_rel8_t* crc_pdu_rel8 = (nfapi_crc_indication_rel8_t*)tlv; - return ( pull8(ppReadPackedMsg, &crc_pdu_rel8->crc_flag, end) ); -} - -static uint8_t unpack_crc_indication_body_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) -{ - nfapi_crc_indication_body_t* value = (nfapi_crc_indication_body_t*)tlv; - uint8_t* crcBodyEnd = *ppReadPackedMsg + value->tl.length; - - if(crcBodyEnd > end) - return 0; - - if(pull16(ppReadPackedMsg, &value->number_of_crcs, end) == 0) - return 0; - - if(value->number_of_crcs > NFAPI_CRC_IND_MAX_PDU) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s number of crc ind pdu's exceed maxium (count:%d max:%d)\n", __FUNCTION__, value->number_of_crcs, NFAPI_CRC_IND_MAX_PDU); - return 0; - } - - if(value->number_of_crcs > 0) - { - value->crc_pdu_list = (nfapi_crc_indication_pdu_t*)nfapi_p7_allocate(sizeof(nfapi_crc_indication_pdu_t) * value->number_of_crcs, config); - if(value->crc_pdu_list == NULL) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s failed to allocate crc ind pdu list (count:%d)\n", __FUNCTION__, value->number_of_crcs); - return 0; - } - } - else - { - value->crc_pdu_list = 0; - } - - - uint8_t i = 0; - for(i = 0; i < value->number_of_crcs; ++i) - { - nfapi_crc_indication_pdu_t* pdu = &(value->crc_pdu_list[i]); - - if(pull16(ppReadPackedMsg, &pdu->instance_length, end) == 0) - return 0; - - uint8_t* crcPduInstanceEnd = *ppReadPackedMsg + pdu->instance_length; - - - unpack_tlv_t unpack_fns[] = - { - { NFAPI_RX_UE_INFORMATION_TAG, &pdu->rx_ue_information, unpack_rx_ue_information_value }, - { NFAPI_CRC_INDICATION_REL8_TAG, &pdu->crc_indication_rel8, unpack_crc_indication_rel8_value }, - }; - - if(unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, crcPduInstanceEnd, 0, 0) == 0) - return 0; - } - - return 1; -} - -static uint8_t unpack_crc_indication(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config) -{ - nfapi_crc_indication_t *pNfapiMsg = (nfapi_crc_indication_t*)msg; - - unpack_p7_tlv_t unpack_fns[] = - { - { NFAPI_CRC_INDICATION_BODY_TAG, &pNfapiMsg->crc_indication_body, &unpack_crc_indication_body_value}, - }; - - return (pull16(ppReadPackedMsg, &pNfapiMsg->sfn_sf, end) && - unpack_p7_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); -} - -static uint8_t unpack_rx_indication_rel8_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_rx_indication_rel8_t* value = (nfapi_rx_indication_rel8_t*)tlv; - - return (pull16(ppReadPackedMsg, &value->length, end) && - pull16(ppReadPackedMsg, &value->offset, end) && - pull8(ppReadPackedMsg, &value->ul_cqi, end) && - pull16(ppReadPackedMsg, &value->timing_advance, end)); -} -static uint8_t unpack_rx_indication_rel9_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_rx_indication_rel9_t* value = (nfapi_rx_indication_rel9_t*)tlv; - return (pull16(ppReadPackedMsg, &value->timing_advance_r9, end)); -} - -static uint8_t unpack_rx_indication_body_value(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) -{ - nfapi_rx_indication_body_t* value = (nfapi_rx_indication_body_t*)tlv; - - // the rxBodyEnd points to the end of the cqi PDU's - uint8_t* rxBodyEnd = *ppReadPackedMsg + value->tl.length; - uint8_t* rxPduEnd = rxBodyEnd; - - uint8_t* numberOfPdusAddress = *ppReadPackedMsg; - - if(rxBodyEnd > end) - { - // pdu end is past buffer end - return 0; - } - - if(pull16(ppReadPackedMsg, &value->number_of_pdus, end) == 0) - return 0; - - if(value->number_of_pdus > NFAPI_RX_IND_MAX_PDU) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s number of rx ind pdu's exceed maxium (count:%d max:%d)\n", __FUNCTION__, value->number_of_pdus, NFAPI_RX_IND_MAX_PDU); - return 0; - } - - if(value->number_of_pdus > 0) - { - value->rx_pdu_list = (nfapi_rx_indication_pdu_t*)nfapi_p7_allocate(sizeof(nfapi_rx_indication_pdu_t) * value->number_of_pdus, config); - if(value->rx_pdu_list == NULL) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s failed to allocate rx ind pdu list (count:%d)\n", __FUNCTION__, value->number_of_pdus); - return 0; - } - } - else - { - value->rx_pdu_list = 0; - } - - uint8_t i = 0; - nfapi_rx_indication_pdu_t* pdu = 0; - while((uint8_t*)(*ppReadPackedMsg) < rxBodyEnd && (uint8_t*)(*ppReadPackedMsg) < rxPduEnd) - { - nfapi_tl_t generic_tl; - if( unpack_tl(ppReadPackedMsg, &generic_tl, end) == 0) - return 0; - - switch(generic_tl.tag) - { - case NFAPI_RX_UE_INFORMATION_TAG: - { - pdu = &(value->rx_pdu_list[i++]); - pdu->rx_ue_information.tl = generic_tl; - if(unpack_rx_ue_information_value(&pdu->rx_ue_information, ppReadPackedMsg, end) == 0) - return 0; - } - break; - case NFAPI_RX_INDICATION_REL8_TAG: - { - if(pdu != 0) - { - pdu->rx_indication_rel8.tl = generic_tl; - if(unpack_rx_indication_rel8_value(&pdu->rx_indication_rel8, ppReadPackedMsg, end) == 0) - return 0; - - if(pdu->rx_indication_rel8.offset > 0) - { - // Need to check that the data is within the tlv - if(numberOfPdusAddress + pdu->rx_indication_rel8.offset + pdu->rx_indication_rel8.length <= rxBodyEnd) - { - // If this the first pdu set the rxPduEnd - if(numberOfPdusAddress + pdu->rx_indication_rel8.offset < rxPduEnd) - { - rxPduEnd = numberOfPdusAddress + pdu->rx_indication_rel8.offset; - - if(rxPduEnd > end) - { - // pdu end is past buffer end - return 0; - } - } - } - else - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "FIXME: the rx data is outside of the tlv\n"); - } - } - } - } - break; - case NFAPI_RX_INDICATION_REL9_TAG: - { - if(pdu != 0) - { - pdu->rx_indication_rel9.tl = generic_tl; - if(unpack_rx_indication_rel9_value(&pdu->rx_indication_rel9, ppReadPackedMsg, end) == 0) - return 0; - } - } - break; - default: - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "RX_ULSCH.indication Invalid pdu type %d \n", generic_tl.tag ); - } - break; - } - } - - uint8_t idx = 0; - for(idx = 0; idx < value->number_of_pdus; ++idx) - { - if(value->rx_pdu_list[idx].rx_indication_rel8.tl.tag == NFAPI_RX_INDICATION_REL8_TAG) - { - uint32_t length = value->rx_pdu_list[idx].rx_indication_rel8.length; - value->rx_pdu_list[idx].data = nfapi_p7_allocate(length, config); - if(pullarray8(ppReadPackedMsg, value->rx_pdu_list[idx].data, length, length, end) == 0) - { - return 0; - } - } - } - - return 1; -} - -static uint8_t unpack_rx_indication(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config) -{ - nfapi_rx_indication_t *pNfapiMsg = (nfapi_rx_indication_t*)msg; - - unpack_p7_tlv_t unpack_fns[] = - { - { NFAPI_RX_INDICATION_BODY_TAG, &pNfapiMsg->rx_indication_body, &unpack_rx_indication_body_value}, - }; - - return (pull16(ppReadPackedMsg, &pNfapiMsg->sfn_sf, end) && - unpack_p7_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); -} - -static uint8_t unpack_preamble_pdu_rel8_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_preamble_pdu_rel8_t* preamble_pdu_rel8 = (nfapi_preamble_pdu_rel8_t*)tlv; - - return (pull16(ppReadPackedMsg, &preamble_pdu_rel8->rnti, end) && - pull8(ppReadPackedMsg, &preamble_pdu_rel8->preamble, end) && - pull16(ppReadPackedMsg, &preamble_pdu_rel8->timing_advance, end)); -} - -static uint8_t unpack_preamble_pdu_rel9_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_preamble_pdu_rel9_t* preamble_pdu_rel9 = (nfapi_preamble_pdu_rel9_t*)tlv; - return pull16(ppReadPackedMsg, &preamble_pdu_rel9->timing_advance_r9, end); -} - -static uint8_t unpack_preamble_pdu_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_preamble_pdu_rel13_t* preamble_pdu_rel13 = (nfapi_preamble_pdu_rel13_t*)tlv; - return pull8(ppReadPackedMsg, &preamble_pdu_rel13->rach_resource_type, end); -} - -static uint8_t unpack_rach_indication_body_value(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) -{ - nfapi_rach_indication_body_t* value = (nfapi_rach_indication_body_t*)tlv; - uint8_t* rachBodyEnd = *ppReadPackedMsg + value->tl.length; - - if(rachBodyEnd > end) - return 0; - - if(pull16(ppReadPackedMsg, &value->number_of_preambles, end) == 0) - return 0; - - if(value->number_of_preambles > NFAPI_PREAMBLE_MAX_PDU) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s number of preamble du's exceed maxium (count:%d max:%d)\n", __FUNCTION__, value->number_of_preambles, NFAPI_PREAMBLE_MAX_PDU); - return 0; - } - - if(value->number_of_preambles > 0) - { - value->preamble_list = (nfapi_preamble_pdu_t*)nfapi_p7_allocate(sizeof(nfapi_preamble_pdu_t) * value->number_of_preambles, config); - if(value->preamble_list == NULL) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s failed to allocate preamble pdu list (count:%d)\n", __FUNCTION__, value->number_of_preambles); - return 0; - } - } - else - { - value->preamble_list = 0; - } - - - uint8_t i = 0; - for(i = 0; i < value->number_of_preambles; ++i) - { - nfapi_preamble_pdu_t* pdu = &(value->preamble_list[i]); - - if(pull16(ppReadPackedMsg, &pdu->instance_length, end) == 0) - return 0; - - uint8_t* preamblePduInstanceEnd = *ppReadPackedMsg + pdu->instance_length; - - - unpack_tlv_t unpack_fns[] = - { - { NFAPI_PREAMBLE_REL8_TAG, &pdu->preamble_rel8, unpack_preamble_pdu_rel8_value }, - { NFAPI_PREAMBLE_REL9_TAG, &pdu->preamble_rel9, unpack_preamble_pdu_rel9_value }, - { NFAPI_PREAMBLE_REL13_TAG, &pdu->preamble_rel13, unpack_preamble_pdu_rel13_value }, - }; - - if(unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, preamblePduInstanceEnd, 0, 0) == 0) - return 0; - } - return 1; -} - -static uint8_t unpack_rach_indication(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config) -{ - nfapi_rach_indication_t *pNfapiMsg = (nfapi_rach_indication_t*)msg; - - unpack_p7_tlv_t unpack_fns[] = - { - { NFAPI_RACH_INDICATION_BODY_TAG, &pNfapiMsg->rach_indication_body, &unpack_rach_indication_body_value}, - }; - - return (pull16(ppReadPackedMsg, &pNfapiMsg->sfn_sf, end) && - unpack_p7_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); -} - -static uint8_t unpack_srs_indication_fdd_rel8_value(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_srs_indication_fdd_rel8_t* srs_pdu_fdd_rel8 = (nfapi_srs_indication_fdd_rel8_t*)tlv; - - if(!(pull16(ppReadPackedMsg, &srs_pdu_fdd_rel8->doppler_estimation, end) && - pull16(ppReadPackedMsg, &srs_pdu_fdd_rel8->timing_advance, end) && - pull8(ppReadPackedMsg, &srs_pdu_fdd_rel8->number_of_resource_blocks, end) && - pull8(ppReadPackedMsg, &srs_pdu_fdd_rel8->rb_start, end) && - pullarray8(ppReadPackedMsg, srs_pdu_fdd_rel8->snr, NFAPI_NUM_RB_MAX, srs_pdu_fdd_rel8->number_of_resource_blocks, end))) - return 0; - return 1; -} - -static uint8_t unpack_srs_indication_fdd_rel9_value(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_srs_indication_fdd_rel9_t* srs_pdu_fdd_rel9 = (nfapi_srs_indication_fdd_rel9_t*)tlv; - return (pull16(ppReadPackedMsg, &srs_pdu_fdd_rel9->timing_advance_r9, end)); -} - -static uint8_t unpack_srs_indication_tdd_rel10_value(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_srs_indication_ttd_rel10_t* srs_pdu_tdd_rel10 = (nfapi_srs_indication_ttd_rel10_t*)tlv; - return (pull8(ppReadPackedMsg, &srs_pdu_tdd_rel10->uppts_symbol, end)); -} - -static uint8_t unpack_srs_indication_fdd_rel11_value(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_srs_indication_fdd_rel11_t* srs_pdu_fdd_rel11 = (nfapi_srs_indication_fdd_rel11_t*)tlv; - return ( pull16(ppReadPackedMsg, &srs_pdu_fdd_rel11->ul_rtoa, end)); -} - -static uint8_t unpack_tdd_channel_measurement_value(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_tdd_channel_measurement_t* value = (nfapi_tdd_channel_measurement_t*)tlv; - - if(!(pull8(ppReadPackedMsg, &value->num_prb_per_subband, end) && - pull8(ppReadPackedMsg, &value->number_of_subbands, end) && - pull8(ppReadPackedMsg, &value->num_atennas, end))) - return 0; - - if(value->number_of_subbands > NFAPI_MAX_NUM_SUBBANDS) - { - // todo : add error - return 0; - } - - if(value->num_atennas > NFAPI_MAX_NUM_PHYSICAL_ANTENNAS) - { - // todo : add error - return 0; - } - - uint8_t idx = 0; - for(idx = 0; idx < value->number_of_subbands; ++idx) - { - if(!(pull8(ppReadPackedMsg, &value->subands[idx].subband_index, end) && - pullarray16(ppReadPackedMsg, value->subands[idx].channel, NFAPI_MAX_NUM_PHYSICAL_ANTENNAS, value->num_atennas, end))) - return 0; - } - - return 1; -} - - -static uint8_t unpack_srs_indication_body_value(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) -{ - nfapi_srs_indication_body_t* value = (nfapi_srs_indication_body_t*)tlv; - uint8_t* srsBodyEnd = *ppReadPackedMsg + value->tl.length; - - if(srsBodyEnd > end) - return 0; - - if(pull8(ppReadPackedMsg, &value->number_of_ues, end) == 0) - return 0; - - if(value->number_of_ues > NFAPI_SRS_IND_MAX_PDU) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s number of srs ind pdu's exceed maxium (count:%d max:%d)\n", __FUNCTION__, value->number_of_ues, NFAPI_SRS_IND_MAX_PDU); - return 0; - } - - if(value->number_of_ues > 0) - { - value->srs_pdu_list = (nfapi_srs_indication_pdu_t*)nfapi_p7_allocate(sizeof(nfapi_srs_indication_pdu_t) * value->number_of_ues, config); - if(value->srs_pdu_list == NULL) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s failed to allocate srs ind pdu list (count:%d)\n", __FUNCTION__, value->number_of_ues); - return 0; - } - } - else - { - value->srs_pdu_list = 0; - } - - - - uint8_t i = 0; - for(i = 0; i < value->number_of_ues; ++i) - { - nfapi_srs_indication_pdu_t* pdu = &(value->srs_pdu_list[i]); - - - if(pull16(ppReadPackedMsg, &pdu->instance_length, end) == 0) - return 0; - - uint8_t* srsPduInstanceEnd = *ppReadPackedMsg + pdu->instance_length; - - - unpack_tlv_t unpack_fns[] = - { - { NFAPI_RX_UE_INFORMATION_TAG, &pdu->rx_ue_information, unpack_rx_ue_information_value }, - { NFAPI_SRS_INDICATION_FDD_REL8_TAG, &pdu->srs_indication_fdd_rel8, unpack_srs_indication_fdd_rel8_value}, - { NFAPI_SRS_INDICATION_FDD_REL9_TAG, &pdu->srs_indication_fdd_rel9, unpack_srs_indication_fdd_rel9_value}, - { NFAPI_SRS_INDICATION_TDD_REL10_TAG, &pdu->srs_indication_tdd_rel10, unpack_srs_indication_tdd_rel10_value}, - { NFAPI_SRS_INDICATION_FDD_REL11_TAG, &pdu->srs_indication_fdd_rel11, unpack_srs_indication_fdd_rel11_value}, - { NFAPI_TDD_CHANNEL_MEASUREMENT_TAG, &pdu->tdd_channel_measurement, unpack_tdd_channel_measurement_value}, - }; - - if(unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, srsPduInstanceEnd, 0, 0) == 0) - return 0; - } - return 1; -} - -static uint8_t unpack_srs_indication(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config) -{ - nfapi_srs_indication_t *pNfapiMsg = (nfapi_srs_indication_t*)msg; - - unpack_p7_tlv_t unpack_fns[] = - { - { NFAPI_SRS_INDICATION_BODY_TAG, &pNfapiMsg->srs_indication_body, &unpack_srs_indication_body_value}, - }; - - return (pull16(ppReadPackedMsg, &pNfapiMsg->sfn_sf, end) && - unpack_p7_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); -} - - -static uint8_t unpack_sr_indication_body_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) -{ - nfapi_sr_indication_body_t* value = (nfapi_sr_indication_body_t*)tlv; - uint8_t* srBodyEnd = *ppReadPackedMsg + value->tl.length; - - if(srBodyEnd > end) - return 0; - - if(pull16(ppReadPackedMsg, &value->number_of_srs, end) == 0) - return 0; - - if(value->number_of_srs > NFAPI_SR_IND_MAX_PDU) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s number of sr ind pdu's exceed maxium (count:%d max:%d)\n", __FUNCTION__, value->number_of_srs, NFAPI_SR_IND_MAX_PDU); - return 0; - } - - if(value->number_of_srs > 0) - { - value->sr_pdu_list = (nfapi_sr_indication_pdu_t*)nfapi_p7_allocate(sizeof(nfapi_sr_indication_pdu_t) * value->number_of_srs, config); - if(value->sr_pdu_list == NULL) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s failed to allocate sr ind pdu list (count:%d)\n", __FUNCTION__, value->number_of_srs); - return 0; - } - } - else - { - value->sr_pdu_list = 0; - } - - uint8_t i = 0; - for(i = 0; i < value->number_of_srs; ++i) - { - nfapi_sr_indication_pdu_t* pdu = &(value->sr_pdu_list[i]); - - if(pull16(ppReadPackedMsg, &pdu->instance_length, end) == 0) - return 0; - - uint8_t* srPduInstanceEnd = *ppReadPackedMsg + pdu->instance_length; - - - unpack_tlv_t unpack_fns[] = - { - { NFAPI_RX_UE_INFORMATION_TAG, &pdu->rx_ue_information, unpack_rx_ue_information_value }, - { NFAPI_UL_CQI_INFORMATION_TAG, &pdu->ul_cqi_information, unpack_ul_cqi_information_value }, - }; - - if(unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, srPduInstanceEnd, 0, 0) == 0) - return 0; - } - - return 1; - -} - -static int unpack_sr_indication(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config) -{ - nfapi_sr_indication_t *pNfapiMsg = (nfapi_sr_indication_t*)msg; - - unpack_p7_tlv_t unpack_fns[] = - { - { NFAPI_SR_INDICATION_BODY_TAG, &pNfapiMsg->sr_indication_body, &unpack_sr_indication_body_value}, - }; - - return (pull16(ppReadPackedMsg, &pNfapiMsg->sfn_sf, end) && - unpack_p7_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); -} -static uint8_t unpack_cqi_indication_rel8_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_cqi_indication_rel8_t* cqi_pdu_rel8 = (nfapi_cqi_indication_rel8_t*)tlv; - - return (pull16(ppReadPackedMsg, &cqi_pdu_rel8->length, end) && - pull16(ppReadPackedMsg, &cqi_pdu_rel8->data_offset, end) && - pull8(ppReadPackedMsg, &cqi_pdu_rel8->ul_cqi, end) && - pull8(ppReadPackedMsg, &cqi_pdu_rel8->ri, end) && - pull16(ppReadPackedMsg, &cqi_pdu_rel8->timing_advance, end)); - -} - -static uint8_t unpack_cqi_indication_rel9_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_cqi_indication_rel9_t* cqi_pdu_rel9 = (nfapi_cqi_indication_rel9_t*)tlv; - - if(!(pull16(ppReadPackedMsg, &cqi_pdu_rel9->length, end) && - pull16(ppReadPackedMsg, &cqi_pdu_rel9->data_offset, end) && - pull8(ppReadPackedMsg, &cqi_pdu_rel9->ul_cqi, end) && - pull8(ppReadPackedMsg, &cqi_pdu_rel9->number_of_cc_reported, end))) - return 0; - - if(cqi_pdu_rel9->number_of_cc_reported > NFAPI_CC_MAX) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "FIXME : out of bound array\n"); - return 0; - } - - if(!(pullarray8(ppReadPackedMsg, cqi_pdu_rel9->ri, NFAPI_CC_MAX, cqi_pdu_rel9->number_of_cc_reported, end) && - pull16(ppReadPackedMsg, &cqi_pdu_rel9->timing_advance, end) && - pull16(ppReadPackedMsg, &cqi_pdu_rel9->timing_advance_r9, end))) - return 0; - - return 1; -} - -static uint8_t unpack_cqi_indication_body_value(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) -{ - nfapi_cqi_indication_body_t* value = (nfapi_cqi_indication_body_t*)tlv; - - // the cqiBodyEnd points to the end of the cqi PDU's - uint8_t* cqiBodyEnd = *ppReadPackedMsg + value->tl.length; - - //uint8_t* cqiPduEnd = cqiBodyEnd; - //uint8_t* numberOfPdusAddress = *ppReadPackedMsg; - - if(cqiBodyEnd > end) - return 0; - - if(pull16(ppReadPackedMsg, &value->number_of_cqis, end) == 0) - return 0; - - if(value->number_of_cqis > NFAPI_CQI_IND_MAX_PDU) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s number of cqi ind pdu's exceed maxium (count:%d max:%d)\n", __FUNCTION__, value->number_of_cqis, NFAPI_CQI_IND_MAX_PDU); - return -1; - } - - if(value->number_of_cqis > 0) - { - value->cqi_pdu_list = (nfapi_cqi_indication_pdu_t*)nfapi_p7_allocate(sizeof(nfapi_cqi_indication_pdu_t) * value->number_of_cqis, config); - if(value->cqi_pdu_list == NULL) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s failed to allocate cqi ind pdu list (count:%d)\n", __FUNCTION__, value->number_of_cqis); - return 0; - } - } - else - { - value->cqi_pdu_list = 0; - } - - if(value->number_of_cqis > 0) - { - value->cqi_raw_pdu_list = (nfapi_cqi_indication_raw_pdu_t*)nfapi_p7_allocate(sizeof(nfapi_cqi_indication_raw_pdu_t) * value->number_of_cqis, config); - if(value->cqi_raw_pdu_list == NULL) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s failed to allocate raw cqi ind pdu list (count:%d)\n", __FUNCTION__, value->number_of_cqis); - return 0; - } - } - else - { - value->cqi_raw_pdu_list = 0; - } - - uint8_t i = 0; - for(i = 0; i < value->number_of_cqis; ++i) - { - nfapi_cqi_indication_pdu_t* pdu = &(value->cqi_pdu_list[i]); - memset(pdu, 0, sizeof(nfapi_cqi_indication_pdu_t)); - - if(pull16(ppReadPackedMsg, &pdu->instance_length, end) == 0) - return 0; - - uint8_t* cqiPduInstanceEnd = *ppReadPackedMsg + pdu->instance_length; - - - while((uint8_t*)(*ppReadPackedMsg) < cqiPduInstanceEnd) - { - nfapi_tl_t generic_tl; - if(unpack_tl(ppReadPackedMsg, &generic_tl, end) == 0) - return 0; - - switch(generic_tl.tag) - { - case NFAPI_RX_UE_INFORMATION_TAG: - pdu->rx_ue_information.tl = generic_tl; - if(unpack_rx_ue_information_value(&pdu->rx_ue_information, ppReadPackedMsg, end) == 0) - return 0; - break; - case NFAPI_CQI_INDICATION_REL8_TAG: - pdu->cqi_indication_rel8.tl = generic_tl; - if(unpack_cqi_indication_rel8_value(&pdu->cqi_indication_rel8, ppReadPackedMsg, end) == 0) - return 0; - - break; - case NFAPI_CQI_INDICATION_REL9_TAG: - pdu->cqi_indication_rel9.tl = generic_tl; - if(unpack_cqi_indication_rel9_value(&pdu->cqi_indication_rel9, ppReadPackedMsg, end) == 0) - return 0; - - break; - case NFAPI_UL_CQI_INFORMATION_TAG: - pdu->ul_cqi_information.tl = generic_tl; - if(unpack_ul_cqi_information_value(&pdu->ul_cqi_information, ppReadPackedMsg, end) == 0) - return 0; - break; - default: - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "RX_CQI.indication Invalid pdu type %d \n", generic_tl.tag ); - } - break; - - }; - } - } - - uint8_t idx = 0; - for(idx = 0; idx < value->number_of_cqis; ++idx) - { - if(value->cqi_pdu_list[idx].cqi_indication_rel8.tl.tag == NFAPI_CQI_INDICATION_REL8_TAG) - { - if(pullarray8(ppReadPackedMsg, &(value->cqi_raw_pdu_list[idx].pdu[0]), NFAPI_CQI_RAW_MAX_LEN, value->cqi_pdu_list[idx].cqi_indication_rel8.length, end) == 0) - return 0; - } - else if(value->cqi_pdu_list[idx].cqi_indication_rel9.tl.tag == NFAPI_CQI_INDICATION_REL9_TAG) - { - if(pullarray8(ppReadPackedMsg, &(value->cqi_raw_pdu_list[idx].pdu[0]), NFAPI_CQI_RAW_MAX_LEN, value->cqi_pdu_list[idx].cqi_indication_rel9.length, end) == 0) - return 0; - } - } - - - return 1; - -} - -static uint8_t unpack_cqi_indication(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config) -{ - nfapi_cqi_indication_t *pNfapiMsg = (nfapi_cqi_indication_t*)msg; - - unpack_p7_tlv_t unpack_fns[] = - { - { NFAPI_CQI_INDICATION_BODY_TAG, &pNfapiMsg->cqi_indication_body, &unpack_cqi_indication_body_value}, - }; - - return (pull16(ppReadPackedMsg, &pNfapiMsg->sfn_sf, end) && - unpack_p7_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); -} -static uint8_t unpack_lbt_pdsch_req_pdu_rel13_value(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_lbt_pdsch_req_pdu_rel13_t* value = (nfapi_lbt_pdsch_req_pdu_rel13_t*)tlv; - - return (pull32(ppReadPackedMsg, &value->handle, end) && - pull32(ppReadPackedMsg, &value->mp_cca, end) && - pull32(ppReadPackedMsg, &value->n_cca, end) && - pull32(ppReadPackedMsg, &value->offset, end) && - pull32(ppReadPackedMsg, &value->lte_txop_sf, end) && - pull16(ppReadPackedMsg, &value->txop_sfn_sf_end, end) && - pull32(ppReadPackedMsg, &value->lbt_mode, end)); -} - -static uint8_t unpack_lbt_drs_req_pdu_rel13_value(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_lbt_drs_req_pdu_rel13_t* value = (nfapi_lbt_drs_req_pdu_rel13_t*)tlv; - - return (pull32(ppReadPackedMsg, &value->handle, end) && - pull32(ppReadPackedMsg, &value->offset, end) && - pull16(ppReadPackedMsg, &value->sfn_sf_end, end) && - pull32(ppReadPackedMsg, &value->lbt_mode, end)); -} - - -static uint8_t unpack_lbt_config_request_body_value(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) -{ - nfapi_lbt_dl_config_request_body_t* value = (nfapi_lbt_dl_config_request_body_t*)tlv; - - if(pull16(ppReadPackedMsg, &value->number_of_pdus, end) == 0) - return 0; - - if(value->number_of_pdus > NFAPI_LBT_DL_CONFIG_REQ_MAX_PDU) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s number of lbt dl config pdu's exceed maxium (count:%d max:%d)\n", __FUNCTION__, value->number_of_pdus, NFAPI_LBT_DL_CONFIG_REQ_MAX_PDU); - return 0; - } - - if(value->number_of_pdus) - { - value->lbt_dl_config_req_pdu_list = (nfapi_lbt_dl_config_request_pdu_t*)nfapi_p7_allocate(sizeof(nfapi_lbt_dl_config_request_pdu_t) * value->number_of_pdus, config); - if(value->lbt_dl_config_req_pdu_list == NULL) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s failed to allocate lbt dl config pdu list (count:%d)\n", __FUNCTION__, value->number_of_pdus); - return 0; - } - } - else - { - value->lbt_dl_config_req_pdu_list = 0; - } - - - uint16_t i; - uint16_t total_number_of_pdus = value->number_of_pdus; - for(i = 0; i < total_number_of_pdus; ++i) - { - nfapi_lbt_dl_config_request_pdu_t* pdu = &(value->lbt_dl_config_req_pdu_list[i]); - - if(!(pull8(ppReadPackedMsg, &pdu->pdu_type, end) && - pull8(ppReadPackedMsg, &pdu->pdu_size, end))) - return 0; - - uint8_t *packedPduEnd = (*ppReadPackedMsg) + pdu->pdu_size - 2; - - if(packedPduEnd > end) - return 0; - - switch(pdu->pdu_type) - { - case NFAPI_LBT_DL_CONFIG_REQUEST_PDSCH_PDU_TYPE: - { - unpack_tlv_t unpack_fns[] = - { - { NFAPI_LBT_PDSCH_REQ_PDU_REL13_TAG, &pdu->lbt_pdsch_req_pdu.lbt_pdsch_req_pdu_rel13, &unpack_lbt_pdsch_req_pdu_rel13_value}, - }; - - unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); - } - break; - case NFAPI_LBT_DL_CONFIG_REQUEST_DRS_PDU_TYPE: - { - unpack_tlv_t unpack_fns[] = - { - { NFAPI_LBT_DRS_REQ_PDU_REL13_TAG, &pdu->lbt_drs_req_pdu.lbt_drs_req_pdu_rel13, &unpack_lbt_drs_req_pdu_rel13_value}, - }; - - unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); - } - break; - default: - NFAPI_TRACE(NFAPI_TRACE_ERROR, "LBT_DL_CONFIG.request body invalid pdu type %d\n", pdu->pdu_type); - return 0; - } - } - - return 1; -} -static uint8_t unpack_lbt_dl_config_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config) -{ - nfapi_lbt_dl_config_request_t *pNfapiMsg = (nfapi_lbt_dl_config_request_t*)msg; - - unpack_p7_tlv_t unpack_fns[] = - { - { NFAPI_LBT_DL_CONFIG_REQUEST_BODY_TAG, &pNfapiMsg->lbt_dl_config_request_body, &unpack_lbt_config_request_body_value}, - }; - - return (pull16(ppReadPackedMsg, &pNfapiMsg->sfn_sf, end) && - unpack_p7_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); -} - -static uint8_t unpack_lbt_pdsch_rsp_pdu_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_lbt_pdsch_rsp_pdu_rel13_t* value = (nfapi_lbt_pdsch_rsp_pdu_rel13_t*)tlv; - - return (pull32(ppReadPackedMsg, &value->handle, end) && - pull32(ppReadPackedMsg, &value->result, end) && - pull32(ppReadPackedMsg, &value->lte_txop_symbols, end) && - pull32(ppReadPackedMsg, &value->initial_partial_sf, end)); - -} -static uint8_t unpack_lbt_drs_rsp_pdu_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_lbt_drs_rsp_pdu_rel13_t* value = (nfapi_lbt_drs_rsp_pdu_rel13_t*)tlv; - - return (pull32(ppReadPackedMsg, &value->handle, end) && - pull32(ppReadPackedMsg, &value->result, end)); -} - -static uint8_t unpack_lbt_indication_body_value(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) -{ - nfapi_lbt_dl_indication_body_t* value = (nfapi_lbt_dl_indication_body_t*)tlv; - - if(pull16(ppReadPackedMsg, &value->number_of_pdus, end) == 0) - return 0; - - if(value->number_of_pdus > NFAPI_LBT_IND_MAX_PDU) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s number of lbt dl ind pdu's exceed maxium (count:%d max:%d)\n", __FUNCTION__, value->number_of_pdus, NFAPI_LBT_IND_MAX_PDU); - return 0; - } - - if(value->number_of_pdus > 0) - { - value->lbt_indication_pdu_list = (nfapi_lbt_dl_indication_pdu_t*)nfapi_p7_allocate(sizeof(nfapi_lbt_dl_indication_pdu_t) * value->number_of_pdus, config); - if(value->lbt_indication_pdu_list == NULL) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s failed to allocate lbt dl ind config pdu list (count:%d)\n", __FUNCTION__, value->number_of_pdus); - return 0; - } - } - else - { - value->lbt_indication_pdu_list = 0; - } - - uint16_t i; - uint16_t total_number_of_pdus = value->number_of_pdus; - for(i = 0; i < total_number_of_pdus; ++i) - { - nfapi_lbt_dl_indication_pdu_t* pdu = &(value->lbt_indication_pdu_list[i]); - - if(!(pull8(ppReadPackedMsg, &pdu->pdu_type, end) && - pull8(ppReadPackedMsg, &pdu->pdu_size, end))) - return 0; - - uint8_t *packedPduEnd = (*ppReadPackedMsg) + pdu->pdu_size - 2; - - if(packedPduEnd > end) - return 0; - - switch(pdu->pdu_type) - { - case NFAPI_LBT_DL_RSP_PDSCH_PDU_TYPE: - { - unpack_tlv_t unpack_fns[] = - { - { NFAPI_LBT_PDSCH_RSP_PDU_REL13_TAG, &pdu->lbt_pdsch_rsp_pdu.lbt_pdsch_rsp_pdu_rel13, &unpack_lbt_pdsch_rsp_pdu_rel13_value}, - }; - - unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); - } - break; - case NFAPI_LBT_DL_RSP_DRS_PDU_TYPE: - { - unpack_tlv_t unpack_fns[] = - { - { NFAPI_LBT_DRS_RSP_PDU_REL13_TAG, &pdu->lbt_drs_rsp_pdu.lbt_drs_rsp_pdu_rel13, &unpack_lbt_drs_rsp_pdu_rel13_value}, - }; - - unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); - } - break; - default: - NFAPI_TRACE(NFAPI_TRACE_ERROR, "LBT_DL.indication body invalid pdu type %d\n", pdu->pdu_type); - return 0; - } - } - - return 1; -} -static uint8_t unpack_lbt_dl_indication(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config) -{ - nfapi_lbt_dl_indication_t *pNfapiMsg = (nfapi_lbt_dl_indication_t*)msg; - - unpack_p7_tlv_t unpack_fns[] = - { - { NFAPI_LBT_DL_INDICATION_BODY_TAG, &pNfapiMsg->lbt_dl_indication_body, &unpack_lbt_indication_body_value}, - }; - - return (pull16(ppReadPackedMsg, &pNfapiMsg->sfn_sf, end) && - unpack_p7_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); -} - -static uint8_t unpack_nb_harq_indication_fdd_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_nb_harq_indication_fdd_rel13_t* value = (nfapi_nb_harq_indication_fdd_rel13_t*)tlv; - return (pull8(ppReadPackedMsg, &value->harq_tb1, end)); -} - - -static uint8_t unpack_nb_harq_indication_body_value(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) -{ - nfapi_nb_harq_indication_body_t* value = (nfapi_nb_harq_indication_body_t*)tlv; - uint8_t* nbharqBodyEnd = *ppReadPackedMsg + value->tl.length; - - if(nbharqBodyEnd > end) - return 0; - - if(pull16(ppReadPackedMsg, &value->number_of_harqs, end) == 0) - return 0; - - if(value->number_of_harqs > NFAPI_HARQ_IND_MAX_PDU) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s number of harq ind pdus exceed maxium (count:%d max:%d)\n", __FUNCTION__, value->number_of_harqs, NFAPI_HARQ_IND_MAX_PDU); - return 0; - } - - value->nb_harq_pdu_list = (nfapi_nb_harq_indication_pdu_t*)nfapi_p7_allocate(sizeof(nfapi_nb_harq_indication_pdu_t) * value->number_of_harqs, config); - if(value->nb_harq_pdu_list == NULL) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s failed to allocate harq ind pdu list (count:%d)\n", __FUNCTION__, value->number_of_harqs); - return 0; - } - - uint8_t i = 0; - for(i = 0; i < value->number_of_harqs; ++i) - { - nfapi_nb_harq_indication_pdu_t* pdu = &(value->nb_harq_pdu_list[i]); - if(pull16(ppReadPackedMsg, &pdu->instance_length, end) == 0) - return 0; - - uint8_t* harqPduInstanceEnd = *ppReadPackedMsg + pdu->instance_length; - - unpack_tlv_t unpack_fns[] = - { - { NFAPI_RX_UE_INFORMATION_TAG, &pdu->rx_ue_information, unpack_rx_ue_information_value }, - { NFAPI_NB_HARQ_INDICATION_FDD_REL13_TAG, &pdu->nb_harq_indication_fdd_rel13, &unpack_nb_harq_indication_fdd_rel13_value}, - { NFAPI_UL_CQI_INFORMATION_TAG, &pdu->ul_cqi_information, &unpack_ul_cqi_information_value} - }; - - if(unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, harqPduInstanceEnd, 0, 0) == 0) - return 0; - - } - - return 1; -} - -static uint8_t unpack_nb_harq_indication(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config) -{ - nfapi_nb_harq_indication_t *pNfapiMsg = (nfapi_nb_harq_indication_t*)msg; - - unpack_p7_tlv_t unpack_fns[] = - { - { NFAPI_NB_HARQ_INDICATION_BODY_TAG, &pNfapiMsg->nb_harq_indication_body, &unpack_nb_harq_indication_body_value}, - }; - - return (pull16(ppReadPackedMsg, &pNfapiMsg->sfn_sf, end) && - unpack_p7_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); -} - -static uint8_t unpack_nrach_indication_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_nrach_indication_pdu_rel13_t* value = (nfapi_nrach_indication_pdu_rel13_t*)tlv; - - return (pull16(ppReadPackedMsg, &value->rnti, end) && - pull8(ppReadPackedMsg, &value->initial_sc, end) && - pull16(ppReadPackedMsg, &value->timing_advance, end) && - pull8(ppReadPackedMsg, &value->nrach_ce_level, end)); -} - -static uint8_t unpack_ue_release_resp(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config) -{ - nfapi_ue_release_response_t *pNfapiMsg = (nfapi_ue_release_response_t*)msg; - if(pull32(ppReadPackedMsg, &pNfapiMsg->error_code, end) == 0){ - return 0; - } - else{ - NFAPI_TRACE(NFAPI_TRACE_INFO, "ue_release_response:error_code = %d\n", pNfapiMsg->error_code); - } - return 1; -} - -static uint8_t unpack_nrach_indication_body_value(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) -{ - nfapi_nrach_indication_body_t* value = (nfapi_nrach_indication_body_t*)tlv; - uint8_t* nrachBodyEnd = *ppReadPackedMsg + value->tl.length; - - if(nrachBodyEnd > end) - return 0; - - if(pull8(ppReadPackedMsg, &value->number_of_initial_scs_detected, end) == 0) - return 0; - - if(value->number_of_initial_scs_detected > NFAPI_PREAMBLE_MAX_PDU) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s number of detected scs ind pdus exceed maxium (count:%d max:%d)\n", __FUNCTION__, value->number_of_initial_scs_detected, NFAPI_PREAMBLE_MAX_PDU); - return 0; - } - - value->nrach_pdu_list = (nfapi_nrach_indication_pdu_t*)nfapi_p7_allocate(sizeof(nfapi_nrach_indication_pdu_t) * value->number_of_initial_scs_detected, config); - if(value->nrach_pdu_list == NULL) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s failed to allocate nrach ind pdu list (count:%d)\n", __FUNCTION__, value->number_of_initial_scs_detected); - return 0; - } - - uint8_t i = 0; - for(i = 0; i < value->number_of_initial_scs_detected; ++i) - { - nfapi_nrach_indication_pdu_t* pdu = &(value->nrach_pdu_list[i]); - - uint8_t* nrachPduInstanceEnd = *ppReadPackedMsg + 4 + 6; - - unpack_tlv_t unpack_fns[] = - { - { NFAPI_NRACH_INDICATION_REL13_TAG, &pdu->nrach_indication_rel13, &unpack_nrach_indication_rel13_value}, - }; - - if(unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, nrachPduInstanceEnd, 0, 0) == 0) - return 0; - - } - - return 1; -} - -static uint8_t unpack_nrach_indication(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config) -{ - nfapi_nrach_indication_t *pNfapiMsg = (nfapi_nrach_indication_t*)msg; - - unpack_p7_tlv_t unpack_fns[] = - { - { NFAPI_NRACH_INDICATION_BODY_TAG, &pNfapiMsg->nrach_indication_body, &unpack_nrach_indication_body_value}, - }; - - return (pull16(ppReadPackedMsg, &pNfapiMsg->sfn_sf, end) && - unpack_p7_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); -} - -static uint8_t unpack_nr_dl_node_sync(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config) -{ - nfapi_nr_dl_node_sync_t *pNfapiMsg = (nfapi_nr_dl_node_sync_t*)msg; - - unpack_p7_tlv_t unpack_fns[] = - { - }; - - return (pull32(ppReadPackedMsg, &pNfapiMsg->t1, end) && - pulls32(ppReadPackedMsg, &pNfapiMsg->delta_sfn_slot, end) && - unpack_p7_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); -} - -static uint8_t unpack_dl_node_sync(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config) -{ - nfapi_dl_node_sync_t *pNfapiMsg = (nfapi_dl_node_sync_t*)msg; - - unpack_p7_tlv_t unpack_fns[] = - { - }; - - return (pull32(ppReadPackedMsg, &pNfapiMsg->t1, end) && - pulls32(ppReadPackedMsg, &pNfapiMsg->delta_sfn_sf, end) && - unpack_p7_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); -} - - -static uint8_t unpack_nr_ul_node_sync(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config) -{ - nfapi_nr_ul_node_sync_t *pNfapiMsg = (nfapi_nr_ul_node_sync_t*)msg; - - unpack_p7_tlv_t unpack_fns[] = - { - }; - - return (pull32(ppReadPackedMsg, &pNfapiMsg->t1, end) && - pull32(ppReadPackedMsg, &pNfapiMsg->t2, end) && - pull32(ppReadPackedMsg, &pNfapiMsg->t3, end) && - unpack_p7_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); -} - - -static uint8_t unpack_ul_node_sync(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config) -{ - nfapi_ul_node_sync_t *pNfapiMsg = (nfapi_ul_node_sync_t*)msg; - - unpack_p7_tlv_t unpack_fns[] = - { - }; - - return (pull32(ppReadPackedMsg, &pNfapiMsg->t1, end) && - pull32(ppReadPackedMsg, &pNfapiMsg->t2, end) && - pull32(ppReadPackedMsg, &pNfapiMsg->t3, end) && - unpack_p7_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); -} - -static uint8_t unpack_timing_info(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config) -{ - nfapi_timing_info_t *pNfapiMsg = (nfapi_timing_info_t*)msg; - - unpack_p7_tlv_t unpack_fns[] = - { - }; - - return (pull32(ppReadPackedMsg, &pNfapiMsg->last_sfn_sf, end) && - pull32(ppReadPackedMsg, &pNfapiMsg->time_since_last_timing_info, end) && - pull32(ppReadPackedMsg, &pNfapiMsg->dl_config_jitter, end) && - pull32(ppReadPackedMsg, &pNfapiMsg->tx_request_jitter, end) && - pull32(ppReadPackedMsg, &pNfapiMsg->ul_config_jitter, end) && - pull32(ppReadPackedMsg, &pNfapiMsg->hi_dci0_jitter, end) && - pulls32(ppReadPackedMsg, &pNfapiMsg->dl_config_latest_delay, end) && - pulls32(ppReadPackedMsg, &pNfapiMsg->tx_request_latest_delay, end) && - pulls32(ppReadPackedMsg, &pNfapiMsg->ul_config_latest_delay, end) && - pulls32(ppReadPackedMsg, &pNfapiMsg->hi_dci0_latest_delay, end) && - pulls32(ppReadPackedMsg, &pNfapiMsg->dl_config_earliest_arrival, end) && - pulls32(ppReadPackedMsg, &pNfapiMsg->tx_request_earliest_arrival, end) && - pulls32(ppReadPackedMsg, &pNfapiMsg->ul_config_earliest_arrival, end) && - pulls32(ppReadPackedMsg, &pNfapiMsg->hi_dci0_earliest_arrival, end) && - unpack_p7_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); -} - - -static uint8_t unpack_nr_timing_info(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config) -{ - nfapi_nr_timing_info_t *pNfapiMsg = (nfapi_nr_timing_info_t*)msg; - - unpack_p7_tlv_t unpack_fns[] = - { - }; - - return (pull32(ppReadPackedMsg, &pNfapiMsg->last_sfn, end) && - pull32(ppReadPackedMsg, &pNfapiMsg->last_slot, end) && - pull32(ppReadPackedMsg, &pNfapiMsg->time_since_last_timing_info, end) && - pull32(ppReadPackedMsg, &pNfapiMsg->dl_tti_jitter, end) && - pull32(ppReadPackedMsg, &pNfapiMsg->tx_data_request_jitter, end) && - pull32(ppReadPackedMsg, &pNfapiMsg->ul_tti_jitter, end) && - pull32(ppReadPackedMsg, &pNfapiMsg->ul_dci_jitter, end) && - pulls32(ppReadPackedMsg, &pNfapiMsg->dl_tti_latest_delay, end) && - pulls32(ppReadPackedMsg, &pNfapiMsg->tx_data_request_latest_delay, end) && - pulls32(ppReadPackedMsg, &pNfapiMsg->ul_tti_latest_delay, end) && - pulls32(ppReadPackedMsg, &pNfapiMsg->ul_dci_latest_delay, end) && - pulls32(ppReadPackedMsg, &pNfapiMsg->dl_tti_earliest_arrival, end) && - pulls32(ppReadPackedMsg, &pNfapiMsg->tx_data_request_earliest_arrival, end) && - pulls32(ppReadPackedMsg, &pNfapiMsg->ul_tti_earliest_arrival, end) && - pulls32(ppReadPackedMsg, &pNfapiMsg->ul_dci_earliest_arrival, end) && - unpack_p7_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); -} - - - -// unpack length check - -static int check_unpack_length(nfapi_message_id_e msgId, uint32_t unpackedBufLen) -{ - int retLen = 0; - - switch (msgId) - { - case NFAPI_DL_CONFIG_REQUEST: - if (unpackedBufLen >= sizeof(nfapi_dl_config_request_t)) - retLen = sizeof(nfapi_dl_config_request_t); - break; - - case NFAPI_UL_CONFIG_REQUEST: - if (unpackedBufLen >= sizeof(nfapi_ul_config_request_t)) - retLen = sizeof(nfapi_ul_config_request_t); - break; - - case NFAPI_SUBFRAME_INDICATION: - if (unpackedBufLen >= sizeof(nfapi_subframe_indication_t)) - retLen = sizeof(nfapi_subframe_indication_t); - break; - - case NFAPI_HI_DCI0_REQUEST: - if (unpackedBufLen >= sizeof(nfapi_hi_dci0_request_t)) - retLen = sizeof(nfapi_hi_dci0_request_t); - break; - - case NFAPI_TX_REQUEST: - if (unpackedBufLen >= sizeof(nfapi_tx_request_t)) - retLen = sizeof(nfapi_tx_request_t); - break; - - case NFAPI_HARQ_INDICATION: - if (unpackedBufLen >= sizeof(nfapi_harq_indication_t)) - retLen = sizeof(nfapi_harq_indication_t); - break; - - case NFAPI_CRC_INDICATION: - if (unpackedBufLen >= sizeof(nfapi_crc_indication_t)) - retLen = sizeof(nfapi_crc_indication_t); - break; - - case NFAPI_RX_ULSCH_INDICATION: - if (unpackedBufLen >= sizeof(nfapi_rx_indication_t)) - retLen = sizeof(nfapi_rx_indication_t); - break; - - case NFAPI_RACH_INDICATION: - if (unpackedBufLen >= sizeof(nfapi_rach_indication_t)) - retLen = sizeof(nfapi_rach_indication_t); - break; - - case NFAPI_SRS_INDICATION: - if (unpackedBufLen >= sizeof(nfapi_srs_indication_t)) - retLen = sizeof(nfapi_srs_indication_t); - break; - - case NFAPI_RX_SR_INDICATION: - if (unpackedBufLen >= sizeof(nfapi_sr_indication_t)) - retLen = sizeof(nfapi_sr_indication_t); - break; - - case NFAPI_RX_CQI_INDICATION: - if (unpackedBufLen >= sizeof(nfapi_cqi_indication_t)) - retLen = sizeof(nfapi_cqi_indication_t); - break; - - case NFAPI_LBT_DL_CONFIG_REQUEST: - if (unpackedBufLen >= sizeof(nfapi_lbt_dl_config_request_t)) - retLen = sizeof(nfapi_lbt_dl_config_request_t); - break; - - case NFAPI_LBT_DL_INDICATION: - if (unpackedBufLen >= sizeof(nfapi_lbt_dl_indication_t)) - retLen = sizeof(nfapi_lbt_dl_indication_t); - break; - - case NFAPI_NB_HARQ_INDICATION: - if (unpackedBufLen >= sizeof(nfapi_nb_harq_indication_t)) - retLen = sizeof(nfapi_nb_harq_indication_t); - break; - - case NFAPI_NRACH_INDICATION: - if (unpackedBufLen >= sizeof(nfapi_nrach_indication_t)) - retLen = sizeof(nfapi_nrach_indication_t); - break; - - case NFAPI_DL_NODE_SYNC: - if (unpackedBufLen >= sizeof(nfapi_dl_node_sync_t)) - retLen = sizeof(nfapi_dl_node_sync_t); - break; - - case NFAPI_UL_NODE_SYNC: - if (unpackedBufLen >= sizeof(nfapi_ul_node_sync_t)) - retLen = sizeof(nfapi_ul_node_sync_t); - break; - - case NFAPI_TIMING_INFO: - if (unpackedBufLen >= sizeof(nfapi_timing_info_t)) - retLen = sizeof(nfapi_timing_info_t); - break; - - case NFAPI_UE_RELEASE_REQUEST: - if (unpackedBufLen >= sizeof(nfapi_ue_release_request_t)) - retLen = sizeof(nfapi_ue_release_request_t); - break; - - case NFAPI_UE_RELEASE_RESPONSE: - if (unpackedBufLen >= sizeof(nfapi_ue_release_response_t)) - retLen = sizeof(nfapi_ue_release_response_t); - break; - - default: - NFAPI_TRACE(NFAPI_TRACE_ERROR, "Unknown message ID %d\n", msgId); - break; - } - - return retLen; -} - -static int check_nr_unpack_length(nfapi_message_id_e msgId, uint32_t unpackedBufLen) -{ - int retLen = 0; - - switch (msgId) - { - case NFAPI_NR_PHY_MSG_TYPE_DL_TTI_REQUEST: - if (unpackedBufLen >= sizeof(nfapi_nr_dl_tti_request_t)) - retLen = sizeof(nfapi_nr_dl_tti_request_t); - break; - - case NFAPI_NR_PHY_MSG_TYPE_UL_TTI_REQUEST: - if (unpackedBufLen >= sizeof(nfapi_nr_ul_tti_request_t)) - retLen = sizeof(nfapi_nr_ul_tti_request_t); - break; - - case NFAPI_SUBFRAME_INDICATION: - if (unpackedBufLen >= sizeof(nfapi_subframe_indication_t)) - retLen = sizeof(nfapi_subframe_indication_t); - break; - - case NFAPI_NR_PHY_MSG_TYPE_UL_DCI_REQUEST: - if (unpackedBufLen >= sizeof(nfapi_nr_ul_dci_request_t)) - retLen = sizeof(nfapi_nr_ul_dci_request_t); - break; - - case NFAPI_NR_PHY_MSG_TYPE_TX_DATA_REQUEST: - if (unpackedBufLen >= sizeof(nfapi_nr_tx_data_request_t)) - retLen = sizeof(nfapi_nr_tx_data_request_t); - break; - - case NFAPI_HARQ_INDICATION: - if (unpackedBufLen >= sizeof(nfapi_harq_indication_t)) - retLen = sizeof(nfapi_harq_indication_t); - break; - - case NFAPI_CRC_INDICATION: - if (unpackedBufLen >= sizeof(nfapi_crc_indication_t)) - retLen = sizeof(nfapi_crc_indication_t); - break; - - case NFAPI_RX_ULSCH_INDICATION: - if (unpackedBufLen >= sizeof(nfapi_rx_indication_t)) - retLen = sizeof(nfapi_rx_indication_t); - break; - - case NFAPI_RACH_INDICATION: - if (unpackedBufLen >= sizeof(nfapi_rach_indication_t)) - retLen = sizeof(nfapi_rach_indication_t); - break; - - case NFAPI_SRS_INDICATION: - if (unpackedBufLen >= sizeof(nfapi_srs_indication_t)) - retLen = sizeof(nfapi_srs_indication_t); - break; - - case NFAPI_RX_SR_INDICATION: - if (unpackedBufLen >= sizeof(nfapi_sr_indication_t)) - retLen = sizeof(nfapi_sr_indication_t); - break; - - case NFAPI_RX_CQI_INDICATION: - if (unpackedBufLen >= sizeof(nfapi_cqi_indication_t)) - retLen = sizeof(nfapi_cqi_indication_t); - break; - - case NFAPI_LBT_DL_CONFIG_REQUEST: - if (unpackedBufLen >= sizeof(nfapi_lbt_dl_config_request_t)) - retLen = sizeof(nfapi_lbt_dl_config_request_t); - break; - - case NFAPI_LBT_DL_INDICATION: - if (unpackedBufLen >= sizeof(nfapi_lbt_dl_indication_t)) - retLen = sizeof(nfapi_lbt_dl_indication_t); - break; - - case NFAPI_NB_HARQ_INDICATION: - if (unpackedBufLen >= sizeof(nfapi_nb_harq_indication_t)) - retLen = sizeof(nfapi_nb_harq_indication_t); - break; - - case NFAPI_NRACH_INDICATION: - if (unpackedBufLen >= sizeof(nfapi_nrach_indication_t)) - retLen = sizeof(nfapi_nrach_indication_t); - break; - - case NFAPI_NR_PHY_MSG_TYPE_DL_NODE_SYNC: - if (unpackedBufLen >= sizeof(nfapi_nr_dl_node_sync_t)) - retLen = sizeof(nfapi_nr_dl_node_sync_t); - break; - - case NFAPI_NR_PHY_MSG_TYPE_UL_NODE_SYNC: - if (unpackedBufLen >= sizeof(nfapi_nr_ul_node_sync_t)) - retLen = sizeof(nfapi_nr_ul_node_sync_t); - break; - - case NFAPI_TIMING_INFO: - if (unpackedBufLen >= sizeof(nfapi_timing_info_t)) - retLen = sizeof(nfapi_timing_info_t); - break; - - case NFAPI_UE_RELEASE_REQUEST: - if (unpackedBufLen >= sizeof(nfapi_ue_release_request_t)) - retLen = sizeof(nfapi_ue_release_request_t); - break; - - case NFAPI_UE_RELEASE_RESPONSE: - if (unpackedBufLen >= sizeof(nfapi_ue_release_response_t)) - retLen = sizeof(nfapi_ue_release_response_t); - break; - - default: - NFAPI_TRACE(NFAPI_TRACE_ERROR, "Unknown message ID %d\n", msgId); - break; - } - - return retLen; -} - - - -// Main unpack functions - public - -int nfapi_p7_message_header_unpack(void *pMessageBuf, uint32_t messageBufLen, void *pUnpackedBuf, uint32_t unpackedBufLen, nfapi_p7_codec_config_t* config) -{ - nfapi_p7_message_header_t *pMessageHeader = pUnpackedBuf; - uint8_t *pReadPackedMessage = pMessageBuf; - uint8_t *end = pMessageBuf + messageBufLen; - - if (pMessageBuf == NULL || pUnpackedBuf == NULL) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "P7 header unpack supplied pointers are null\n"); - return -1; - } - - if (messageBufLen < NFAPI_P7_HEADER_LENGTH || unpackedBufLen < sizeof(nfapi_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; - } - - // process the header - if(!(pull16(&pReadPackedMessage, &pMessageHeader->phy_id, end) && - pull16(&pReadPackedMessage, &pMessageHeader->message_id, end) && - pull16(&pReadPackedMessage, &pMessageHeader->message_length, end) && - pull16(&pReadPackedMessage, &pMessageHeader->m_segment_sequence, end) && - pull32(&pReadPackedMessage, &pMessageHeader->checksum, end) && - pull32(&pReadPackedMessage, &pMessageHeader->transmit_timestamp, end))) - return -1; - - return 0; -} - -int nfapi_p7_message_unpack(void *pMessageBuf, uint32_t messageBufLen, void *pUnpackedBuf, uint32_t unpackedBufLen, nfapi_p7_codec_config_t* config) -{ - int result = 0; - nfapi_p7_message_header_t *pMessageHeader = (nfapi_p7_message_header_t*)pUnpackedBuf; - uint8_t *pReadPackedMessage = pMessageBuf; - uint8_t *end = pMessageBuf + messageBufLen; - - if (pMessageBuf == NULL || pUnpackedBuf == NULL) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "P7 unpack supplied pointers are null\n"); - return -1; - } - - if (messageBufLen < NFAPI_P7_HEADER_LENGTH || unpackedBufLen < sizeof(nfapi_p7_message_header_t)) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "P7 unpack supplied message buffer is too small %d, %d\n", messageBufLen, unpackedBufLen); - return -1; - } - /* - uint8_t *ptr = pMessageBuf; - printf("\n Read P7 message unpack: "); - while(ptr < end){ - printf(" %d ", *ptr); - ptr++; - } - printf("\n"); -*/ - // clean the supplied buffer for - tag value blanking - (void)memset(pUnpackedBuf, 0, unpackedBufLen); - - // process the header - if(!(pull16(&pReadPackedMessage, &pMessageHeader->phy_id, end) && - pull16(&pReadPackedMessage, &pMessageHeader->message_id, end) && - pull16(&pReadPackedMessage, &pMessageHeader->message_length, end) && - pull16(&pReadPackedMessage, &pMessageHeader->m_segment_sequence, end) && - pull32(&pReadPackedMessage, &pMessageHeader->checksum, end) && - pull32(&pReadPackedMessage, &pMessageHeader->transmit_timestamp, end))) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "P7 unpack header failed\n"); - return -1; - } - - 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; - } - - /* - if(check_unpack_length(pMessageHeader->message_id, unpackedBufLen) == 0) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "P7 unpack unpack buffer is not large enough \n"); - return -1; - } - */ - - // look for the specific message - switch (pMessageHeader->message_id) - { - case NFAPI_DL_CONFIG_REQUEST: - if (check_unpack_length(NFAPI_DL_CONFIG_REQUEST, unpackedBufLen)) - result = unpack_dl_config_request(&pReadPackedMessage, end, pMessageHeader, config); - else - return -1; - break; - - case NFAPI_UL_CONFIG_REQUEST: - if (check_unpack_length(NFAPI_UL_CONFIG_REQUEST, unpackedBufLen)) - result = unpack_ul_config_request(&pReadPackedMessage, end, pMessageHeader, config); - else - return -1; - break; - case NFAPI_TX_REQUEST: - if (check_unpack_length(NFAPI_TX_REQUEST, unpackedBufLen)) - result = unpack_tx_request(&pReadPackedMessage, end, pMessageHeader, config); - else - return -1; - break; - case NFAPI_HI_DCI0_REQUEST: - if (check_unpack_length(NFAPI_HI_DCI0_REQUEST, unpackedBufLen)) - result = unpack_hi_dci0_request(&pReadPackedMessage, end, pMessageHeader, config); - else - return -1; - break; - - case NFAPI_UE_RELEASE_REQUEST: - if (check_unpack_length(NFAPI_UE_RELEASE_REQUEST, unpackedBufLen)) - result = unpack_ue_release_request(&pReadPackedMessage, end, pMessageHeader, config); - else - return -1; - break; - - case NFAPI_HARQ_INDICATION: - if (check_unpack_length(NFAPI_HARQ_INDICATION, unpackedBufLen)) - result = unpack_harq_indication(&pReadPackedMessage, end, pMessageHeader, config); - else - return -1; - break; - - case NFAPI_CRC_INDICATION: - if (check_unpack_length(NFAPI_CRC_INDICATION, unpackedBufLen)) - result = unpack_crc_indication(&pReadPackedMessage,end , pMessageHeader, config); - else - return -1; - break; - - case NFAPI_RX_ULSCH_INDICATION: - if (check_unpack_length(NFAPI_RX_ULSCH_INDICATION, unpackedBufLen)) - result = unpack_rx_indication(&pReadPackedMessage, end, pMessageHeader, config); - else - return -1; - break; - - case NFAPI_RACH_INDICATION: - if (check_unpack_length(NFAPI_RACH_INDICATION, unpackedBufLen)) - result = unpack_rach_indication(&pReadPackedMessage, end, pMessageHeader, config); - else - return -1; - break; - - case NFAPI_SRS_INDICATION: - if (check_unpack_length(NFAPI_SRS_INDICATION, unpackedBufLen)) - result = unpack_srs_indication(&pReadPackedMessage, end, pMessageHeader, config); - else - return -1; - break; - - case NFAPI_RX_SR_INDICATION: - if (check_unpack_length(NFAPI_RX_SR_INDICATION, unpackedBufLen)) - result = unpack_sr_indication(&pReadPackedMessage, end, pMessageHeader, config); - else - return -1; - break; - - case NFAPI_RX_CQI_INDICATION: - if (check_unpack_length(NFAPI_RX_CQI_INDICATION, unpackedBufLen)) - result = unpack_cqi_indication(&pReadPackedMessage, end, pMessageHeader, config); - else - return -1; - break; - - case NFAPI_LBT_DL_CONFIG_REQUEST: - if (check_unpack_length(NFAPI_LBT_DL_CONFIG_REQUEST, unpackedBufLen)) - result = unpack_lbt_dl_config_request(&pReadPackedMessage, end, pMessageHeader, config); - else - return -1; - break; - - case NFAPI_LBT_DL_INDICATION: - if (check_unpack_length(NFAPI_LBT_DL_INDICATION, unpackedBufLen)) - result = unpack_lbt_dl_indication(&pReadPackedMessage, end, pMessageHeader, config); - else - return -1; - break; - - case NFAPI_NB_HARQ_INDICATION: - if (check_unpack_length(NFAPI_NB_HARQ_INDICATION, unpackedBufLen)) - result = unpack_nb_harq_indication(&pReadPackedMessage, end, pMessageHeader, config); - else - return -1; - break; - - case NFAPI_NRACH_INDICATION: - if (check_unpack_length(NFAPI_NRACH_INDICATION, unpackedBufLen)) - result = unpack_nrach_indication(&pReadPackedMessage, end, pMessageHeader, config); - else - return -1; - break; - - case NFAPI_DL_NODE_SYNC: - if (check_unpack_length(NFAPI_DL_NODE_SYNC, unpackedBufLen)) - result = unpack_dl_node_sync(&pReadPackedMessage, end, pMessageHeader, config); - else - return -1; - break; - - case NFAPI_UL_NODE_SYNC: - if (check_unpack_length(NFAPI_UL_NODE_SYNC, unpackedBufLen)) - result = unpack_ul_node_sync(&pReadPackedMessage, end , pMessageHeader, config); - else - return -1; - break; - - case NFAPI_TIMING_INFO: - if (check_unpack_length(NFAPI_TIMING_INFO, unpackedBufLen)) - result = unpack_timing_info(&pReadPackedMessage, end, pMessageHeader, config); - else - return -1; - break; - - case NFAPI_UE_RELEASE_RESPONSE: - if (check_unpack_length(NFAPI_UE_RELEASE_RESPONSE, unpackedBufLen)) - result = unpack_ue_release_resp(&pReadPackedMessage, end, pMessageHeader, config); - else - return -1; - break; - - default: - - if(pMessageHeader->message_id >= NFAPI_VENDOR_EXT_MSG_MIN && - pMessageHeader->message_id <= NFAPI_VENDOR_EXT_MSG_MAX) - { - if(config && config->unpack_p7_vendor_extension) - { - result = (config->unpack_p7_vendor_extension)(pMessageHeader, &pReadPackedMessage, end, config); - } - else - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s VE NFAPI message ID %d. No ve decoder provided\n", __FUNCTION__, pMessageHeader->message_id); - } - } - else - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s NFAPI Unknown message ID %d\n", __FUNCTION__, pMessageHeader->message_id); - } - break; - } - - if(result == 0) - return -1; - else - return 0; -} - -int nfapi_nr_p7_message_unpack(void *pMessageBuf, uint32_t messageBufLen, void *pUnpackedBuf, uint32_t unpackedBufLen, nfapi_p7_codec_config_t* config) -{ - int result = 0; - nfapi_p7_message_header_t *pMessageHeader = (nfapi_p7_message_header_t*)pUnpackedBuf; - uint8_t *pReadPackedMessage = pMessageBuf; - uint8_t *end = pMessageBuf + messageBufLen; - - if (pMessageBuf == NULL || pUnpackedBuf == NULL) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "P7 unpack supplied pointers are null\n"); - return -1; - } - - if (messageBufLen < NFAPI_P7_HEADER_LENGTH || unpackedBufLen < sizeof(nfapi_p7_message_header_t)) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "P7 unpack supplied message buffer is too small %d, %d\n", messageBufLen, unpackedBufLen); - return -1; - } - /* - uint8_t *ptr = pMessageBuf; - printf("\n Read P7 message unpack: "); - while(ptr < end){ - printf(" %d ", *ptr); - ptr++; - } - printf("\n"); -*/ - // clean the supplied buffer for - tag value blanking - (void)memset(pUnpackedBuf, 0, unpackedBufLen); - - // process the header - if(!(pull16(&pReadPackedMessage, &pMessageHeader->phy_id, end) && - pull16(&pReadPackedMessage, &pMessageHeader->message_id, end) && - pull16(&pReadPackedMessage, &pMessageHeader->message_length, end) && - pull16(&pReadPackedMessage, &pMessageHeader->m_segment_sequence, end) && - pull32(&pReadPackedMessage, &pMessageHeader->checksum, end) && - pull32(&pReadPackedMessage, &pMessageHeader->transmit_timestamp, end))) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "P7 unpack header failed\n"); - return -1; - } - - 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; - } - - /* - if(check_unpack_length(pMessageHeader->message_id, unpackedBufLen) == 0) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "P7 unpack unpack buffer is not large enough \n"); - return -1; - } - */ - - // look for the specific message - switch (pMessageHeader->message_id) - { - case NFAPI_NR_PHY_MSG_TYPE_DL_TTI_REQUEST: - if (check_nr_unpack_length(NFAPI_NR_PHY_MSG_TYPE_DL_TTI_REQUEST, unpackedBufLen)) - result = unpack_dl_tti_request(&pReadPackedMessage, end, pMessageHeader, config); - else - return -1; - break; - - case NFAPI_NR_PHY_MSG_TYPE_UL_TTI_REQUEST: - if (check_nr_unpack_length(NFAPI_NR_PHY_MSG_TYPE_UL_TTI_REQUEST, unpackedBufLen)) - result = unpack_ul_tti_request(&pReadPackedMessage, end, pMessageHeader, config); - else - return -1; - break; - case NFAPI_NR_PHY_MSG_TYPE_TX_DATA_REQUEST: - if (check_nr_unpack_length(NFAPI_NR_PHY_MSG_TYPE_TX_DATA_REQUEST, unpackedBufLen)) - result = unpack_tx_data_request(&pReadPackedMessage, end, pMessageHeader, config); - else - return -1; - break; - case NFAPI_NR_PHY_MSG_TYPE_UL_DCI_REQUEST: - if (check_nr_unpack_length(NFAPI_NR_PHY_MSG_TYPE_UL_DCI_REQUEST, unpackedBufLen)) - result = unpack_ul_dci_request(&pReadPackedMessage, end, pMessageHeader, config); - else - return -1; - break; - - case NFAPI_UE_RELEASE_REQUEST: - if (check_nr_unpack_length(NFAPI_UE_RELEASE_REQUEST, unpackedBufLen)) - result = unpack_ue_release_request(&pReadPackedMessage, end, pMessageHeader, config); - else - return -1; - break; - - case NFAPI_HARQ_INDICATION: - if (check_nr_unpack_length(NFAPI_HARQ_INDICATION, unpackedBufLen)) - result = unpack_harq_indication(&pReadPackedMessage, end, pMessageHeader, config); - else - return -1; - break; - - case NFAPI_CRC_INDICATION: - if (check_nr_unpack_length(NFAPI_CRC_INDICATION, unpackedBufLen)) - result = unpack_crc_indication(&pReadPackedMessage,end , pMessageHeader, config); - else - return -1; - break; - - case NFAPI_RX_ULSCH_INDICATION: - if (check_nr_unpack_length(NFAPI_RX_ULSCH_INDICATION, unpackedBufLen)) - result = unpack_rx_indication(&pReadPackedMessage, end, pMessageHeader, config); - else - return -1; - break; - - case NFAPI_RACH_INDICATION: - if (check_nr_unpack_length(NFAPI_RACH_INDICATION, unpackedBufLen)) - result = unpack_rach_indication(&pReadPackedMessage, end, pMessageHeader, config); - else - return -1; - break; - - case NFAPI_SRS_INDICATION: - if (check_nr_unpack_length(NFAPI_SRS_INDICATION, unpackedBufLen)) - result = unpack_srs_indication(&pReadPackedMessage, end, pMessageHeader, config); - else - return -1; - break; - - case NFAPI_RX_SR_INDICATION: - if (check_nr_unpack_length(NFAPI_RX_SR_INDICATION, unpackedBufLen)) - result = unpack_sr_indication(&pReadPackedMessage, end, pMessageHeader, config); - else - return -1; - break; - - case NFAPI_RX_CQI_INDICATION: - if (check_nr_unpack_length(NFAPI_RX_CQI_INDICATION, unpackedBufLen)) - result = unpack_cqi_indication(&pReadPackedMessage, end, pMessageHeader, config); - else - return -1; - break; - - case NFAPI_LBT_DL_CONFIG_REQUEST: - if (check_nr_unpack_length(NFAPI_LBT_DL_CONFIG_REQUEST, unpackedBufLen)) - result = unpack_lbt_dl_config_request(&pReadPackedMessage, end, pMessageHeader, config); - else - return -1; - break; - - case NFAPI_LBT_DL_INDICATION: - if (check_nr_unpack_length(NFAPI_LBT_DL_INDICATION, unpackedBufLen)) - result = unpack_lbt_dl_indication(&pReadPackedMessage, end, pMessageHeader, config); - else - return -1; - break; - - case NFAPI_NB_HARQ_INDICATION: - if (check_nr_unpack_length(NFAPI_NB_HARQ_INDICATION, unpackedBufLen)) - result = unpack_nb_harq_indication(&pReadPackedMessage, end, pMessageHeader, config); - else - return -1; - break; - - case NFAPI_NRACH_INDICATION: - if (check_nr_unpack_length(NFAPI_NRACH_INDICATION, unpackedBufLen)) - result = unpack_nrach_indication(&pReadPackedMessage, end, pMessageHeader, config); - else - return -1; - break; - - case NFAPI_NR_PHY_MSG_TYPE_DL_NODE_SYNC: - if (check_nr_unpack_length(NFAPI_NR_PHY_MSG_TYPE_DL_NODE_SYNC, unpackedBufLen)) - result = unpack_nr_dl_node_sync(&pReadPackedMessage, end, pMessageHeader, config); - else - return -1; - break; - - case NFAPI_NR_PHY_MSG_TYPE_UL_NODE_SYNC: - if (check_nr_unpack_length(NFAPI_NR_PHY_MSG_TYPE_UL_NODE_SYNC, unpackedBufLen)) - result = unpack_nr_ul_node_sync(&pReadPackedMessage, end , pMessageHeader, config); - else - return -1; - break; - - case NFAPI_TIMING_INFO: - if (check_nr_unpack_length(NFAPI_TIMING_INFO, unpackedBufLen)) - result = unpack_nr_timing_info(&pReadPackedMessage, end, pMessageHeader, config); - else - return -1; - break; - - case NFAPI_UE_RELEASE_RESPONSE: - if (check_nr_unpack_length(NFAPI_UE_RELEASE_RESPONSE, unpackedBufLen)) - result = unpack_ue_release_resp(&pReadPackedMessage, end, pMessageHeader, config); - else - return -1; - break; - - default: - - if(pMessageHeader->message_id >= NFAPI_VENDOR_EXT_MSG_MIN && - pMessageHeader->message_id <= NFAPI_VENDOR_EXT_MSG_MAX) - { - if(config && config->unpack_p7_vendor_extension) - { - result = (config->unpack_p7_vendor_extension)(pMessageHeader, &pReadPackedMessage, end, config); - } - else - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s VE NFAPI message ID %d. No ve decoder provided\n", __FUNCTION__, pMessageHeader->message_id); - } - } - else - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s NFAPI Unknown message ID %d\n", __FUNCTION__, pMessageHeader->message_id); - } - break; - } - - if(result == 0) - return -1; - else - return 0; -} - - +/* + * 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. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include "nfapi_nr_interface_scf.h" + +extern int nfapi_unpack_p7_vendor_extension(nfapi_p7_message_header_t* header, uint8_t **ppReadPackedMsg, void* user_data); +extern int nfapi_pack_p7_vendor_extension(nfapi_p7_message_header_t* header, uint8_t **ppWritePackedMsg, void* user_data); + +uint32_t nfapi_calculate_checksum(uint8_t* buffer, uint16_t len) +{ + uint32_t chksum = 0; + // calcaulte upto the checksum + chksum = crc32(chksum, buffer, 8); + + // skip the checksum + uint8_t zeros[4] = {0, 0, 0, 0}; + chksum = crc32(chksum, zeros, 4); + + // continu with the rest of the mesage + chksum = crc32(chksum, &buffer[NFAPI_P7_HEADER_LENGTH], len - NFAPI_P7_HEADER_LENGTH); + + // return the inverse + return ~(chksum); +} + +int nfapi_p7_update_checksum(uint8_t* buffer, uint32_t len) +{ + uint32_t checksum = nfapi_calculate_checksum(buffer, len); + + uint8_t* p_write = &buffer[8]; + return (push32(checksum, &p_write, buffer + len) > 0 ? 0 : -1); +} + +int nfapi_p7_update_transmit_timestamp(uint8_t* buffer, uint32_t timestamp) +{ + uint8_t* p_write = &buffer[12]; + return (push32(timestamp, &p_write, buffer + 16) > 0 ? 0 : -1); +} + +uint32_t nfapi_p7_calculate_checksum(uint8_t* buffer, uint32_t len) +{ + return nfapi_calculate_checksum(buffer, len); +} + +void* nfapi_p7_allocate(size_t size, nfapi_p7_codec_config_t* config) +{ + if(size == 0) + return 0; + + void* buffer_p = NULL; + if(config && config->allocate) + { + buffer_p = (config->allocate)(size); + if(buffer_p != NULL){ + memset(buffer_p,0,size); + } + return buffer_p; + } + else + { + buffer_p = calloc(1, size); + return buffer_p; + } +} + +void nfapi_p7_deallocate(void* ptr, nfapi_p7_codec_config_t* config) +{ + if(ptr == NULL) + return; + + if(config && config->deallocate) + { + return (config->deallocate)(ptr); + } + else + { + return free(ptr); + } +} +// Pack routines + + +static uint8_t pack_dl_config_dci_dl_pdu_rel8_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_dl_config_dci_dl_pdu_rel8_t* value = (nfapi_dl_config_dci_dl_pdu_rel8_t*)tlv; + + //NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s() dci_format:%u\n", __FUNCTION__, value->dci_format); + + return ( push8(value->dci_format, ppWritePackedMsg, end) && + push8(value->cce_idx, ppWritePackedMsg, end) && + push8(value->aggregation_level, ppWritePackedMsg, end) && + push16(value->rnti, ppWritePackedMsg, end) && + push8(value->resource_allocation_type, ppWritePackedMsg, end) && + push8(value->virtual_resource_block_assignment_flag, ppWritePackedMsg, end) && + push32(value->resource_block_coding, ppWritePackedMsg, end) && + push8(value->mcs_1, ppWritePackedMsg, end) && + push8(value->redundancy_version_1, ppWritePackedMsg, end) && + push8(value->new_data_indicator_1, ppWritePackedMsg, end) && + push8(value->transport_block_to_codeword_swap_flag, ppWritePackedMsg, end) && + push8(value->mcs_2, ppWritePackedMsg, end) && + push8(value->redundancy_version_2, ppWritePackedMsg, end) && + push8(value->new_data_indicator_2, ppWritePackedMsg, end) && + push8(value->harq_process, ppWritePackedMsg, end) && + push8(value->tpmi, ppWritePackedMsg, end) && + push8(value->pmi, ppWritePackedMsg, end) && + push8(value->precoding_information, ppWritePackedMsg, end) && + push8(value->tpc, ppWritePackedMsg, end) && + push8(value->downlink_assignment_index, ppWritePackedMsg, end) && + push8(value->ngap, ppWritePackedMsg, end) && + push8(value->transport_block_size_index, ppWritePackedMsg, end) && + push8(value->downlink_power_offset, ppWritePackedMsg, end) && + push8(value->allocate_prach_flag, ppWritePackedMsg, end) && + push8(value->preamble_index, ppWritePackedMsg, end) && + push8(value->prach_mask_index, ppWritePackedMsg, end) && + push8(value->rnti_type, ppWritePackedMsg, end) && + push16(value->transmission_power, ppWritePackedMsg, end)); +} + +static uint8_t pack_dl_config_dci_dl_pdu_rel9_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_dl_config_dci_dl_pdu_rel9_t* value = (nfapi_dl_config_dci_dl_pdu_rel9_t*)tlv; + + return( push8(value->mcch_flag, ppWritePackedMsg, end) && + push8(value->mcch_change_notification, ppWritePackedMsg, end) && + push8(value->scrambling_identity, ppWritePackedMsg, end)); +} + +static uint8_t pack_dl_config_dci_dl_pdu_rel10_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_dl_config_dci_dl_pdu_rel10_t* value = (nfapi_dl_config_dci_dl_pdu_rel10_t*)tlv; + + return ( push8(value->cross_carrier_scheduling_flag, ppWritePackedMsg, end) && + push8(value->carrier_indicator, ppWritePackedMsg, end) && + push8(value->srs_flag, ppWritePackedMsg, end) && + push8(value->srs_request, ppWritePackedMsg, end) && + push8(value->antenna_ports_scrambling_and_layers, ppWritePackedMsg, end) && + push8(value->total_dci_length_including_padding, ppWritePackedMsg, end) && + push8(value->n_dl_rb, ppWritePackedMsg, end)); +} + +static uint8_t pack_dl_config_dci_dl_pdu_rel11_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_dl_config_dci_dl_pdu_rel11_t* value = (nfapi_dl_config_dci_dl_pdu_rel11_t*)tlv; + + return ( push8(value->harq_ack_resource_offset, ppWritePackedMsg, end) && + push8(value->pdsch_re_mapping_quasi_co_location_indicator, ppWritePackedMsg, end)); +} + +static uint8_t pack_dl_config_dci_dl_pdu_rel12_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_dl_config_dci_dl_pdu_rel12_t* value = (nfapi_dl_config_dci_dl_pdu_rel12_t*)tlv; + + return ( push8(value->primary_cell_type, ppWritePackedMsg, end) && + push8(value->ul_dl_configuration_flag, ppWritePackedMsg, end) && + push8(value->number_ul_dl_configurations, ppWritePackedMsg, end) && + pusharray8(value->ul_dl_configuration_indication, NFAPI_MAX_UL_DL_CONFIGURATIONS, value->number_ul_dl_configurations, ppWritePackedMsg, end)); +} + +static uint8_t pack_tpm_value(nfapi_dl_config_dci_dl_tpm_t* value, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + if (!( push8(value->num_prb_per_subband, ppWritePackedMsg, end) && + push8(value->number_of_subbands, ppWritePackedMsg, end) && + push8(value->num_antennas, ppWritePackedMsg, end))) + return 0; + + uint8_t idx = 0; + for(idx = 0; idx < value->number_of_subbands; ++idx) + { + nfapi_dl_config_dci_dl_tpm_subband_info_t* subband_info = &(value->subband_info[idx]); + + if(!(push8(subband_info->subband_index, ppWritePackedMsg, end) && + push8(subband_info->scheduled_ues, ppWritePackedMsg, end))) + return 0; + + + uint8_t antenna_idx = 0; + uint8_t scheduled_ue_idx = 0; + + for(antenna_idx = 0; antenna_idx < value->num_antennas; ++antenna_idx) + { + for(scheduled_ue_idx = 0; scheduled_ue_idx < subband_info->scheduled_ues; ++scheduled_ue_idx) + { + if(!push16(subband_info->precoding_value[antenna_idx][scheduled_ue_idx], ppWritePackedMsg, end)) + return 0; + } + } + + } + + + return 1; + +} + + +static uint8_t pack_dl_tti_csi_rs_pdu_rel15_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_nr_dl_tti_csi_rs_pdu_rel15_t* value = (nfapi_nr_dl_tti_csi_rs_pdu_rel15_t*)tlv; + + return( + push16(value->bwp_size, ppWritePackedMsg, end) && + push16(value->bwp_start, ppWritePackedMsg, end) && + + push8(value->subcarrier_spacing, ppWritePackedMsg, end) && + push8(value->cyclic_prefix, ppWritePackedMsg, end) && + + push16(value->start_rb, ppWritePackedMsg, end) && + push16(value->nr_of_rbs, ppWritePackedMsg, end) && + + push8(value->csi_type, ppWritePackedMsg, end) && + push8(value->row, ppWritePackedMsg, end) && + + push16(value->freq_domain, ppWritePackedMsg, end) && + push8(value->symb_l0, ppWritePackedMsg, end) && + + push8(value->symb_l1, ppWritePackedMsg, end) && + push8(value->cdm_type, ppWritePackedMsg, end) && + + push8(value->freq_density, ppWritePackedMsg, end) && + push16(value->scramb_id, ppWritePackedMsg, end) && + + push8(value->power_control_offset, ppWritePackedMsg, end) && + push8(value->power_control_offset_ss, ppWritePackedMsg, end) + ); + +} + + +static uint8_t pack_dl_tti_pdcch_pdu_rel15_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_nr_dl_tti_pdcch_pdu_rel15_t* value = (nfapi_nr_dl_tti_pdcch_pdu_rel15_t*)tlv; + + for(uint8_t i = 0; i < MAX_DCI_CORESET; ++i) + { + if(!(push16(value->dci_pdu[i].RNTI, ppWritePackedMsg, end) && + push16(value->dci_pdu[i].ScramblingId, ppWritePackedMsg, end) && + + push16(value->dci_pdu[i].ScramblingRNTI, ppWritePackedMsg, end) && + push8(value->dci_pdu[i].CceIndex, ppWritePackedMsg, end) && + push8(value->dci_pdu[i].AggregationLevel, ppWritePackedMsg, end) && + push8(value->dci_pdu[i].beta_PDCCH_1_0, ppWritePackedMsg, end) && + + push8(value->dci_pdu[i].powerControlOffsetSS, ppWritePackedMsg, end) && + push16(value->dci_pdu[i].PayloadSizeBits, ppWritePackedMsg, end) && + pusharray8(value->dci_pdu[i].Payload, value->dci_pdu[i].PayloadSizeBits, value->dci_pdu[i].PayloadSizeBits, ppWritePackedMsg, end))) + return 0; + + } + + // TODO: resolve the packaging of array (currently sending a single element) + return( + push16(value->BWPSize, ppWritePackedMsg, end) && + push16(value->BWPStart, ppWritePackedMsg, end) && + push8(value->SubcarrierSpacing, ppWritePackedMsg, end) && + push8(value->CyclicPrefix, ppWritePackedMsg, end) && + + push8(value->StartSymbolIndex, ppWritePackedMsg, end) && + push8(value->DurationSymbols, ppWritePackedMsg, end) && + pusharray8(value->FreqDomainResource, 6, 6, ppWritePackedMsg, end) && + push8(value->CceRegMappingType, ppWritePackedMsg, end) && + + push8(value->RegBundleSize, ppWritePackedMsg, end) && + push8(value->InterleaverSize, ppWritePackedMsg, end) && + push8(value->CoreSetType, ppWritePackedMsg, end) && + push16(value->ShiftIndex, ppWritePackedMsg, end) && + + push8(value->precoderGranularity, ppWritePackedMsg, end) && + push16(value->numDlDci, ppWritePackedMsg, end)); + +} + + +static uint8_t pack_dl_tti_pdsch_pdu_rel15_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + printf("packing pdsch pdu. \n"); + nfapi_nr_dl_tti_pdsch_pdu_rel15_t* value = (nfapi_nr_dl_tti_pdsch_pdu_rel15_t*)tlv; + + // TODO: resolve the packaging of array (currently sending a single element) + return( + push16(value->pduBitmap, ppWritePackedMsg, end) && + push16(value->rnti, ppWritePackedMsg, end) && + push16(value->pduIndex, ppWritePackedMsg, end) && + push16(value->BWPSize, ppWritePackedMsg, end) && + + push16(value->BWPStart, ppWritePackedMsg, end) && + push8(value->SubcarrierSpacing, ppWritePackedMsg, end) && + push8(value->CyclicPrefix, ppWritePackedMsg, end) && + push8(value->NrOfCodewords, ppWritePackedMsg, end) && + + pusharray16(value->targetCodeRate, 2, 1, ppWritePackedMsg, end) && + pusharray8(value->qamModOrder, 2, 1, ppWritePackedMsg, end) && + pusharray8(value->mcsIndex, 2, 1, ppWritePackedMsg, end) && + pusharray8(value->mcsTable, 2, 1, ppWritePackedMsg, end) && + + pusharray8(value->rvIndex, 2, 1, ppWritePackedMsg, end) && + pusharray32(value->TBSize, 2, 1, ppWritePackedMsg, end) && + push16(value->dataScramblingId, ppWritePackedMsg, end) && + push8(value->nrOfLayers, ppWritePackedMsg, end) && + + push8(value->transmissionScheme, ppWritePackedMsg, end) && + push8(value->refPoint, ppWritePackedMsg, end) && + push16(value->dlDmrsSymbPos, ppWritePackedMsg, end) && + push8(value->dmrsConfigType, ppWritePackedMsg, end) && + + push16(value->dlDmrsScramblingId, ppWritePackedMsg, end) && + push8(value->SCID, ppWritePackedMsg, end) && + push8(value->numDmrsCdmGrpsNoData, ppWritePackedMsg, end) && + push16(value->dmrsPorts, ppWritePackedMsg, end) && + + push8(value->resourceAlloc, ppWritePackedMsg, end) && + push16(value->rbStart, ppWritePackedMsg, end) && + push16(value->rbSize, ppWritePackedMsg, end) && + + push8(value->VRBtoPRBMapping, ppWritePackedMsg, end) && + push8(value->StartSymbolIndex, ppWritePackedMsg, end) && + push8(value->NrOfSymbols, ppWritePackedMsg, end) && + push8(value->PTRSPortIndex, ppWritePackedMsg, end) && + + push8(value->PTRSTimeDensity, ppWritePackedMsg, end) && + push8(value->PTRSFreqDensity, ppWritePackedMsg, end) && + push8(value->PTRSReOffset, ppWritePackedMsg, end) + ); + +} + + +static uint8_t pack_dl_tti_ssb_pdu_rel15_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + printf("Packing ssb. \n"); + nfapi_nr_dl_tti_ssb_pdu_rel15_t* value = (nfapi_nr_dl_tti_ssb_pdu_rel15_t*)tlv; + + return( + push16(value->PhysCellId, ppWritePackedMsg, end) && + push8(value->BetaPss, ppWritePackedMsg, end) && + push8(value->SsbBlockIndex, ppWritePackedMsg, end) && + push8(value->SsbSubcarrierOffset, ppWritePackedMsg, end) && + push16(value->ssbOffsetPointA, ppWritePackedMsg, end) && + push8(value->bchPayloadFlag, ppWritePackedMsg, end) && + push32(value->bchPayload, ppWritePackedMsg, end) + // TODO: pack precoding_and_beamforming too + ); + +} + + +static uint8_t pack_dl_config_dci_dl_pdu_rel13_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_dl_config_dci_dl_pdu_rel13_t* value = (nfapi_dl_config_dci_dl_pdu_rel13_t*)tlv; + + return( push8(value->laa_end_partial_sf_flag, ppWritePackedMsg, end) && + push8(value->laa_end_partial_sf_configuration, ppWritePackedMsg, end) && + push8(value->initial_lbt_sf, ppWritePackedMsg, end) && + push8(value->codebook_size_determination, ppWritePackedMsg, end) && + push8(value->drms_table_flag, ppWritePackedMsg, end) && + push8(value->tpm_struct_flag, ppWritePackedMsg, end) && + (value->tpm_struct_flag == 1 ? pack_tpm_value(&(value->tpm), ppWritePackedMsg, end) : 1)); +} + +static uint8_t pack_dl_config_bch_pdu_rel8_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_dl_config_bch_pdu_rel8_t* value = (nfapi_dl_config_bch_pdu_rel8_t*)tlv; + + //NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s()\n", __FUNCTION__); + + return( push16(value->length, ppWritePackedMsg, end) && + push16(value->pdu_index, ppWritePackedMsg, end) && + push16(value->transmission_power, ppWritePackedMsg, end)); +} +static uint8_t pack_dl_config_mch_pdu_rel8_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_dl_config_mch_pdu_rel8_t* value = (nfapi_dl_config_mch_pdu_rel8_t*)tlv; + + return ( push16(value->length, ppWritePackedMsg, end) && + push16(value->pdu_index, ppWritePackedMsg, end) && + push16(value->rnti, ppWritePackedMsg, end) && + push8(value->resource_allocation_type, ppWritePackedMsg, end) && + push32(value->resource_block_coding, ppWritePackedMsg, end) && + push8(value->modulation, ppWritePackedMsg, end) && + push16(value->transmission_power, ppWritePackedMsg, end) && + push16(value->mbsfn_area_id, ppWritePackedMsg, end)); +} + +static uint8_t pack_bf_vector_info(void* elem, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_bf_vector_t* bf = (nfapi_bf_vector_t*)elem; + + return ( push8(bf->subband_index, ppWritePackedMsg, end) && + push8(bf->num_antennas, ppWritePackedMsg, end) && + pusharray16(bf->bf_value, NFAPI_MAX_NUM_ANTENNAS, bf->num_antennas, ppWritePackedMsg, end)); + + +} +static uint8_t pack_dl_config_dlsch_pdu_rel8_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_dl_config_dlsch_pdu_rel8_t* value = (nfapi_dl_config_dlsch_pdu_rel8_t*)tlv; + + return ( push16(value->length, ppWritePackedMsg, end) && + push16(value->pdu_index, ppWritePackedMsg, end) && + push16(value->rnti, ppWritePackedMsg, end) && + push8(value->resource_allocation_type, ppWritePackedMsg, end) && + push8(value->virtual_resource_block_assignment_flag, ppWritePackedMsg, end) && + push32(value->resource_block_coding, ppWritePackedMsg, end) && + push8(value->modulation, ppWritePackedMsg, end) && + push8(value->redundancy_version, ppWritePackedMsg, end) && + push8(value->transport_blocks, ppWritePackedMsg, end) && + push8(value->transport_block_to_codeword_swap_flag, ppWritePackedMsg, end) && + push8(value->transmission_scheme, ppWritePackedMsg, end) && + push8(value->number_of_layers, ppWritePackedMsg, end) && + push8(value->number_of_subbands, ppWritePackedMsg, end) && + pusharray8(value->codebook_index, NFAPI_MAX_NUM_SUBBANDS, value->number_of_subbands, ppWritePackedMsg, end) && + push8(value->ue_category_capacity, ppWritePackedMsg, end) && + push8(value->pa, ppWritePackedMsg, end) && + push8(value->delta_power_offset_index, ppWritePackedMsg, end) && + push8(value->ngap, ppWritePackedMsg, end) && + push8(value->nprb, ppWritePackedMsg, end) && + push8(value->transmission_mode, ppWritePackedMsg, end) && + push8(value->num_bf_prb_per_subband, ppWritePackedMsg, end) && + push8(value->num_bf_vector, ppWritePackedMsg, end) && + packarray(value->bf_vector, sizeof(nfapi_bf_vector_t), NFAPI_MAX_BF_VECTORS, value->num_bf_vector, ppWritePackedMsg, end, &pack_bf_vector_info)); + +} +static uint8_t pack_dl_config_dlsch_pdu_rel9_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_dl_config_dlsch_pdu_rel9_t* value = (nfapi_dl_config_dlsch_pdu_rel9_t*)tlv; + return ( push8(value->nscid, ppWritePackedMsg, end) ); +} +static uint8_t pack_dl_config_dlsch_pdu_rel10_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_dl_config_dlsch_pdu_rel10_t* value = (nfapi_dl_config_dlsch_pdu_rel10_t*)tlv; + + return ( push8(value->csi_rs_flag, ppWritePackedMsg, end) && + push8(value->csi_rs_resource_config_r10, ppWritePackedMsg, end) && + push16(value->csi_rs_zero_tx_power_resource_config_bitmap_r10, ppWritePackedMsg, end) && + push8(value->csi_rs_number_nzp_configuration, ppWritePackedMsg, end) && + pusharray8(value->csi_rs_resource_config, NFAPI_MAX_CSI_RS_RESOURCE_CONFIG, value->csi_rs_number_nzp_configuration, ppWritePackedMsg, end) && + push8(value->pdsch_start, ppWritePackedMsg, end)); +} +static uint8_t pack_dl_config_dlsch_pdu_rel11_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_dl_config_dlsch_pdu_rel11_t* value = (nfapi_dl_config_dlsch_pdu_rel11_t*)tlv; + + return( push8(value->drms_config_flag, ppWritePackedMsg, end) && + push16(value->drms_scrambling, ppWritePackedMsg, end) && + push8(value->csi_config_flag, ppWritePackedMsg, end) && + push16(value->csi_scrambling, ppWritePackedMsg, end) && + push8(value->pdsch_re_mapping_flag, ppWritePackedMsg, end) && + push8(value->pdsch_re_mapping_atenna_ports, ppWritePackedMsg, end) && + push8(value->pdsch_re_mapping_freq_shift, ppWritePackedMsg, end)); +} +static uint8_t pack_dl_config_dlsch_pdu_rel12_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_dl_config_dlsch_pdu_rel12_t* value = (nfapi_dl_config_dlsch_pdu_rel12_t*)tlv; + + return( push8(value->altcqi_table_r12, ppWritePackedMsg, end) && + push8(value->maxlayers, ppWritePackedMsg, end) && + push8(value->n_dl_harq, ppWritePackedMsg, end)); +} +static uint8_t pack_dl_config_dlsch_pdu_rel13_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_dl_config_dlsch_pdu_rel13_t* value = (nfapi_dl_config_dlsch_pdu_rel13_t*)tlv; + + return( push8(value->dwpts_symbols, ppWritePackedMsg, end) && + push8(value->initial_lbt_sf, ppWritePackedMsg, end) && + push8(value->ue_type, ppWritePackedMsg, end) && + push8(value->pdsch_payload_type, ppWritePackedMsg, end) && + push16(value->initial_transmission_sf_io, ppWritePackedMsg, end) && + push8(value->drms_table_flag, ppWritePackedMsg, end)); +} +static uint8_t pack_dl_config_pch_pdu_rel8_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_dl_config_pch_pdu_rel8_t* value = (nfapi_dl_config_pch_pdu_rel8_t*)tlv; + + return( push16(value->length, ppWritePackedMsg, end) && + push16(value->pdu_index, ppWritePackedMsg, end) && + push16(value->p_rnti, ppWritePackedMsg, end) && + push8(value->resource_allocation_type, ppWritePackedMsg, end) && + push8(value->virtual_resource_block_assignment_flag, ppWritePackedMsg, end) && + push32(value->resource_block_coding, ppWritePackedMsg, end) && + push8(value->mcs, ppWritePackedMsg, end) && + push8(value->redundancy_version, ppWritePackedMsg, end) && + push8(value->number_of_transport_blocks, ppWritePackedMsg, end) && + push8(value->transport_block_to_codeword_swap_flag, ppWritePackedMsg, end) && + push8(value->transmission_scheme, ppWritePackedMsg, end) && + push8(value->number_of_layers, ppWritePackedMsg, end) && + push8(value->codebook_index, ppWritePackedMsg, end) && + push8(value->ue_category_capacity, ppWritePackedMsg, end) && + push8(value->pa, ppWritePackedMsg, end) && + push16(value->transmission_power, ppWritePackedMsg, end) && + push8(value->nprb, ppWritePackedMsg, end) && + push8(value->ngap, ppWritePackedMsg, end)); +} +static uint8_t pack_dl_config_pch_pdu_rel13_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_dl_config_pch_pdu_rel13_t* value = (nfapi_dl_config_pch_pdu_rel13_t*)tlv; + + return ( push8(value->ue_mode, ppWritePackedMsg, end) && + push16(value->initial_transmission_sf_io, ppWritePackedMsg, end)); +} +static uint8_t pack_dl_config_prs_pdu_rel9_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_dl_config_prs_pdu_rel9_t* value = (nfapi_dl_config_prs_pdu_rel9_t*)tlv; + + return( push16(value->transmission_power, ppWritePackedMsg, end) && + push8(value->prs_bandwidth, ppWritePackedMsg, end) && + push8(value->prs_cyclic_prefix_type, ppWritePackedMsg, end) && + push8(value->prs_muting, ppWritePackedMsg, end)); +} +static uint8_t pack_dl_config_csi_rs_pdu_rel10_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_dl_config_csi_rs_pdu_rel10_t* value = (nfapi_dl_config_csi_rs_pdu_rel10_t*)tlv; + + return( push8(value->csi_rs_antenna_port_count_r10, ppWritePackedMsg, end) && + push8(value->csi_rs_resource_config_r10, ppWritePackedMsg, end) && + push16(value->transmission_power, ppWritePackedMsg, end) && + push16(value->csi_rs_zero_tx_power_resource_config_bitmap_r10, ppWritePackedMsg, end) && + push8(value->csi_rs_number_of_nzp_configuration, ppWritePackedMsg, end) && + pusharray8(value->csi_rs_resource_config, NFAPI_MAX_CSI_RS_RESOURCE_CONFIG, value->csi_rs_number_of_nzp_configuration, ppWritePackedMsg, end)); +} +static uint8_t pack_dl_config_csi_rs_pdu_rel13_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_dl_config_csi_rs_pdu_rel13_t* value = (nfapi_dl_config_csi_rs_pdu_rel13_t*)tlv; + + if(!(push8(value->csi_rs_class, ppWritePackedMsg, end) && + push8(value->cdm_type, ppWritePackedMsg, end) && + push8(value->num_bf_vector, ppWritePackedMsg, end))) + { + return 0; + } + + uint16_t i; + for(i = 0; i < value->num_bf_vector; ++i) + { + if(!(push8(value->bf_vector[i].csi_rs_resource_index, ppWritePackedMsg, end) && + pusharray16(value->bf_vector[i].bf_value, NFAPI_MAX_ANTENNA_PORT_COUNT, NFAPI_MAX_ANTENNA_PORT_COUNT, ppWritePackedMsg, end))) + return 0; + } + + return 1; +} +static uint8_t pack_bf_vector(nfapi_bf_vector_t* vector, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + return ( push8(vector->subband_index, ppWritePackedMsg, end) && + push8(vector->num_antennas, ppWritePackedMsg, end) && + pusharray16(vector->bf_value, NFAPI_MAX_NUM_ANTENNAS, vector->num_antennas, ppWritePackedMsg, end)); +} + +static uint8_t pack_dl_config_epdcch_parameters_rel11_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_dl_config_epdcch_parameters_rel11_t* value = (nfapi_dl_config_epdcch_parameters_rel11_t*)tlv; + + return ( push8(value->epdcch_resource_assignment_flag, ppWritePackedMsg, end) && + push16(value->epdcch_id, ppWritePackedMsg, end) && + push8(value->epdcch_start_symbol, ppWritePackedMsg, end) && + push8(value->epdcch_num_prb, ppWritePackedMsg, end) && + pusharray8(value->epdcch_prb_index, NFAPI_MAX_EPDCCH_PRB, value->epdcch_num_prb, ppWritePackedMsg, end) && + pack_bf_vector(&value->bf_vector, ppWritePackedMsg, end)); +} +static uint8_t pack_dl_config_epdcch_parameters_rel13_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_dl_config_epdcch_parameters_rel13_t* value = (nfapi_dl_config_epdcch_parameters_rel13_t*)tlv; + + return (push8(value->dwpts_symbols, ppWritePackedMsg, end) && + push8(value->initial_lbt_sf, ppWritePackedMsg, end)); +} +static uint8_t pack_dl_config_mpdcch_pdu_rel13_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_dl_config_mpdcch_pdu_rel13_t* value = (nfapi_dl_config_mpdcch_pdu_rel13_t*)tlv; + + return ( push8(value->mpdcch_narrow_band, ppWritePackedMsg, end) && + push8(value->number_of_prb_pairs, ppWritePackedMsg, end) && + push8(value->resource_block_assignment, ppWritePackedMsg, end) && + push8(value->mpdcch_tansmission_type, ppWritePackedMsg, end) && + push8(value->start_symbol, ppWritePackedMsg, end) && + push8(value->ecce_index, ppWritePackedMsg, end) && + push8(value->aggregation_level, ppWritePackedMsg, end) && + push8(value->rnti_type, ppWritePackedMsg, end) && + push16(value->rnti, ppWritePackedMsg, end) && + push8(value->ce_mode, ppWritePackedMsg, end) && + push16(value->drms_scrambling_init, ppWritePackedMsg, end) && + push16(value->initial_transmission_sf_io, ppWritePackedMsg, end) && + push16(value->transmission_power, ppWritePackedMsg, end) && + push8(value->dci_format, ppWritePackedMsg, end) && + push16(value->resource_block_coding, ppWritePackedMsg, end) && + push8(value->mcs, ppWritePackedMsg, end) && + push8(value->pdsch_reptition_levels, ppWritePackedMsg, end) && + push8(value->redundancy_version, ppWritePackedMsg, end) && + push8(value->new_data_indicator, ppWritePackedMsg, end) && + push8(value->harq_process, ppWritePackedMsg, end) && + push8(value->tpmi_length, ppWritePackedMsg, end) && + push8(value->tpmi, ppWritePackedMsg, end) && + push8(value->pmi_flag, ppWritePackedMsg, end) && + push8(value->pmi, ppWritePackedMsg, end) && + push8(value->harq_resource_offset, ppWritePackedMsg, end) && + push8(value->dci_subframe_repetition_number, ppWritePackedMsg, end) && + push8(value->tpc, ppWritePackedMsg, end) && + push8(value->downlink_assignment_index_length, ppWritePackedMsg, end) && + push8(value->downlink_assignment_index, ppWritePackedMsg, end) && + push8(value->allocate_prach_flag, ppWritePackedMsg, end) && + push8(value->preamble_index, ppWritePackedMsg, end) && + push8(value->prach_mask_index, ppWritePackedMsg, end) && + push8(value->starting_ce_level, ppWritePackedMsg, end) && + push8(value->srs_request, ppWritePackedMsg, end) && + push8(value->antenna_ports_and_scrambling_identity_flag, ppWritePackedMsg, end) && + push8(value->antenna_ports_and_scrambling_identity, ppWritePackedMsg, end) && + push8(value->frequency_hopping_enabled_flag, ppWritePackedMsg, end) && + push8(value->paging_direct_indication_differentiation_flag, ppWritePackedMsg, end) && + push8(value->direct_indication, ppWritePackedMsg, end) && + push8(value->total_dci_length_including_padding, ppWritePackedMsg, end) && + push8(value->number_of_tx_antenna_ports, ppWritePackedMsg, end) && + pusharray16(value->precoding_value, NFAPI_MAX_TX_PHYSICAL_ANTENNA_PORTS, value->number_of_tx_antenna_ports, ppWritePackedMsg, end)); +} + + +static uint8_t pack_dl_config_nbch_pdu_rel13_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_dl_config_nbch_pdu_rel13_t* value = (nfapi_dl_config_nbch_pdu_rel13_t*)tlv; + + return (push16(value->length, ppWritePackedMsg, end) && + push16(value->pdu_index, ppWritePackedMsg, end) && + push16(value->transmission_power, ppWritePackedMsg, end) && + push16(value->hyper_sfn_2_lsbs, ppWritePackedMsg, end)); +} + + +static uint8_t pack_dl_config_npdcch_pdu_rel13_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_dl_config_npdcch_pdu_rel13_t* value = (nfapi_dl_config_npdcch_pdu_rel13_t*)tlv; + + return (push16(value->length, ppWritePackedMsg, end) && + push16(value->pdu_index, ppWritePackedMsg, end) && + push8(value->ncce_index, ppWritePackedMsg, end) && + push8(value->aggregation_level, ppWritePackedMsg, end) && + push8(value->start_symbol, ppWritePackedMsg, end) && + push8(value->rnti_type, ppWritePackedMsg, end) && + push16(value->rnti, ppWritePackedMsg, end) && + push8(value->scrambling_reinitialization_batch_index, ppWritePackedMsg, end) && + push8(value->nrs_antenna_ports_assumed_by_the_ue, ppWritePackedMsg, end) && + push8(value->dci_format, ppWritePackedMsg, end) && + push8(value->scheduling_delay, ppWritePackedMsg, end) && + push8(value->resource_assignment, ppWritePackedMsg, end) && + push8(value->repetition_number, ppWritePackedMsg, end) && + push8(value->mcs, ppWritePackedMsg, end) && + push8(value->new_data_indicator, ppWritePackedMsg, end) && + push8(value->harq_ack_resource, ppWritePackedMsg, end) && + push8(value->npdcch_order_indication, ppWritePackedMsg, end) && + push8(value->starting_number_of_nprach_repetitions, ppWritePackedMsg, end) && + push8(value->subcarrier_indication_of_nprach, ppWritePackedMsg, end) && + push8(value->paging_direct_indication_differentation_flag, ppWritePackedMsg, end) && + push8(value->direct_indication, ppWritePackedMsg, end) && + push8(value->dci_subframe_repetition_number, ppWritePackedMsg, end) && + push8(value->total_dci_length_including_padding, ppWritePackedMsg, end)); +} + +static uint8_t pack_dl_config_ndlsch_pdu_rel13_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_dl_config_ndlsch_pdu_rel13_t* value = (nfapi_dl_config_ndlsch_pdu_rel13_t*)tlv; + + return (push16(value->length, ppWritePackedMsg, end) && + push16(value->pdu_index, ppWritePackedMsg, end) && + push8(value->start_symbol, ppWritePackedMsg, end) && + push8(value->rnti_type, ppWritePackedMsg, end) && + push16(value->rnti, ppWritePackedMsg, end) && + push16(value->resource_assignment, ppWritePackedMsg, end) && + push16(value->repetition_number, ppWritePackedMsg, end) && + push8(value->modulation, ppWritePackedMsg, end) && + push8(value->number_of_subframes_for_resource_assignment, ppWritePackedMsg, end) && + push8(value->scrambling_sequence_initialization_cinit, ppWritePackedMsg, end) && + push16(value->sf_idx, ppWritePackedMsg, end) && + push8(value->nrs_antenna_ports_assumed_by_the_ue, ppWritePackedMsg, end)); +} + + +static uint8_t pack_dl_tti_request_body_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_nr_dl_tti_request_pdu_t* value = (nfapi_nr_dl_tti_request_pdu_t*)tlv; + + if(!(push16(value->PDUSize, ppWritePackedMsg, end) && + push16(value->PDUType, ppWritePackedMsg, end) )) + return 0; + + + // first match the pdu type, then call the respective function + switch(value->PDUType) + { + case NFAPI_NR_DL_TTI_CSI_RS_PDU_TYPE: + { + if(!(pack_dl_tti_csi_rs_pdu_rel15_value(&value->csi_rs_pdu.csi_rs_pdu_rel15,ppWritePackedMsg,end))) + return 0; + } + break; + + case NFAPI_NR_DL_TTI_PDCCH_PDU_TYPE: + { + if(!(pack_dl_tti_pdcch_pdu_rel15_value(&value->pdcch_pdu.pdcch_pdu_rel15,ppWritePackedMsg,end))) + return 0; + } + break; + case NFAPI_NR_DL_TTI_PDSCH_PDU_TYPE: + { + if(!(pack_dl_tti_pdsch_pdu_rel15_value(&value->pdsch_pdu.pdsch_pdu_rel15,ppWritePackedMsg,end))) + return 0; + } + break; + case NFAPI_NR_DL_TTI_SSB_PDU_TYPE: + { + if(!(pack_dl_tti_ssb_pdu_rel15_value(&value->ssb_pdu.ssb_pdu_rel15,ppWritePackedMsg,end))) + return 0; + } + break; + + default: + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "FIXME : Invalid DL_TTI pdu type %d \n", value->PDUType ); + } + break; + } + + return 1; +} + +static uint8_t pack_dl_config_request_body_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_dl_config_request_body_t* value = (nfapi_dl_config_request_body_t*)tlv; + + //NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s() dci:%u pdu:%u pdsch:%u rnti:%u pcfich:%u\n", __FUNCTION__, value->number_dci, value->number_pdu, value->number_pdsch_rnti, value->transmission_power_pcfich); + + if(!(push8(value->number_pdcch_ofdm_symbols, ppWritePackedMsg, end) && + push8(value->number_dci, ppWritePackedMsg, end) && + push16(value->number_pdu, ppWritePackedMsg, end) && + push8(value->number_pdsch_rnti, ppWritePackedMsg, end) && + push16(value->transmission_power_pcfich, ppWritePackedMsg, end))) + { + return 0; + } + + uint16_t i = 0; + uint16_t total_number_of_pdus = value->number_pdu; + for(; i < total_number_of_pdus; ++i) + { + nfapi_dl_config_request_pdu_t* pdu = &(value->dl_config_pdu_list[i]); + + if(push8(pdu->pdu_type, ppWritePackedMsg, end) == 0) + return 0; + + // Put a 0 size in and then determine the size after the pdu + // has been writen and write the calculated size + uint8_t* pWritePackedMsgPduSize = *ppWritePackedMsg; + pdu->pdu_size = 0; + if(push8(pdu->pdu_size, ppWritePackedMsg, end) == 0) + return 0; + + switch(pdu->pdu_type) + { + case NFAPI_DL_CONFIG_DCI_DL_PDU_TYPE: + { + //NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s() NFAPI_DL_CONFIG_DCI_DL_PDU_TYPE\n", __FUNCTION__); + + if(!(pack_tlv(NFAPI_DL_CONFIG_REQUEST_DCI_DL_PDU_REL8_TAG, &pdu->dci_dl_pdu.dci_dl_pdu_rel8, ppWritePackedMsg, end, &pack_dl_config_dci_dl_pdu_rel8_value) && + pack_tlv(NFAPI_DL_CONFIG_REQUEST_DCI_DL_PDU_REL9_TAG, &pdu->dci_dl_pdu.dci_dl_pdu_rel9, ppWritePackedMsg, end, &pack_dl_config_dci_dl_pdu_rel9_value) && + pack_tlv(NFAPI_DL_CONFIG_REQUEST_DCI_DL_PDU_REL10_TAG, &pdu->dci_dl_pdu.dci_dl_pdu_rel10, ppWritePackedMsg, end, &pack_dl_config_dci_dl_pdu_rel10_value) && + pack_tlv(NFAPI_DL_CONFIG_REQUEST_DCI_DL_PDU_REL11_TAG, &pdu->dci_dl_pdu.dci_dl_pdu_rel11, ppWritePackedMsg, end, &pack_dl_config_dci_dl_pdu_rel11_value) && + pack_tlv(NFAPI_DL_CONFIG_REQUEST_DCI_DL_PDU_REL12_TAG, &pdu->dci_dl_pdu.dci_dl_pdu_rel12, ppWritePackedMsg, end, &pack_dl_config_dci_dl_pdu_rel12_value) && + pack_tlv(NFAPI_DL_CONFIG_REQUEST_DCI_DL_PDU_REL13_TAG, &pdu->dci_dl_pdu.dci_dl_pdu_rel13, ppWritePackedMsg, end, &pack_dl_config_dci_dl_pdu_rel13_value))) + { + return 0; + } + } + break; + case NFAPI_DL_CONFIG_BCH_PDU_TYPE: + { + //NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s() NFAPI_DL_CONFIG_BCH_PDU_TYPE\n", __FUNCTION__); + + if(!(pack_tlv(NFAPI_DL_CONFIG_REQUEST_BCH_PDU_REL8_TAG, &pdu->bch_pdu.bch_pdu_rel8, ppWritePackedMsg, end, &pack_dl_config_bch_pdu_rel8_value))) + return 0; + } + break; + case NFAPI_DL_CONFIG_MCH_PDU_TYPE: + { + if(!(pack_tlv(NFAPI_DL_CONFIG_REQUEST_MCH_PDU_REL8_TAG, &pdu->mch_pdu.mch_pdu_rel8, ppWritePackedMsg, end, &pack_dl_config_mch_pdu_rel8_value))) + return 0; + } + break; + case NFAPI_DL_CONFIG_DLSCH_PDU_TYPE: + { + if(!(pack_tlv(NFAPI_DL_CONFIG_REQUEST_DLSCH_PDU_REL8_TAG, &pdu->dlsch_pdu.dlsch_pdu_rel8, ppWritePackedMsg, end, &pack_dl_config_dlsch_pdu_rel8_value) && + pack_tlv(NFAPI_DL_CONFIG_REQUEST_DLSCH_PDU_REL9_TAG, &pdu->dlsch_pdu.dlsch_pdu_rel9, ppWritePackedMsg, end, &pack_dl_config_dlsch_pdu_rel9_value) && + pack_tlv(NFAPI_DL_CONFIG_REQUEST_DLSCH_PDU_REL10_TAG, &pdu->dlsch_pdu.dlsch_pdu_rel10, ppWritePackedMsg, end, &pack_dl_config_dlsch_pdu_rel10_value) && + pack_tlv(NFAPI_DL_CONFIG_REQUEST_DLSCH_PDU_REL11_TAG, &pdu->dlsch_pdu.dlsch_pdu_rel11, ppWritePackedMsg, end, &pack_dl_config_dlsch_pdu_rel11_value) && + pack_tlv(NFAPI_DL_CONFIG_REQUEST_DLSCH_PDU_REL12_TAG, &pdu->dlsch_pdu.dlsch_pdu_rel12, ppWritePackedMsg, end, &pack_dl_config_dlsch_pdu_rel12_value) && + pack_tlv(NFAPI_DL_CONFIG_REQUEST_DLSCH_PDU_REL13_TAG, &pdu->dlsch_pdu.dlsch_pdu_rel13, ppWritePackedMsg, end, &pack_dl_config_dlsch_pdu_rel13_value))) + return 0; + } + break; + case NFAPI_DL_CONFIG_PCH_PDU_TYPE: + { + if(!(pack_tlv(NFAPI_DL_CONFIG_REQUEST_PCH_PDU_REL8_TAG, &pdu->pch_pdu.pch_pdu_rel8, ppWritePackedMsg, end, &pack_dl_config_pch_pdu_rel8_value) && + pack_tlv(NFAPI_DL_CONFIG_REQUEST_PCH_PDU_REL13_TAG, &pdu->pch_pdu.pch_pdu_rel13, ppWritePackedMsg, end, &pack_dl_config_pch_pdu_rel13_value))) + return 0; + } + break; + case NFAPI_DL_CONFIG_PRS_PDU_TYPE: + { + if(!(pack_tlv(NFAPI_DL_CONFIG_REQUEST_PRS_PDU_REL9_TAG, &pdu->prs_pdu.prs_pdu_rel9, ppWritePackedMsg, end, &pack_dl_config_prs_pdu_rel9_value))) + return 0; + } + break; + case NFAPI_DL_CONFIG_CSI_RS_PDU_TYPE: + { + if(!(pack_tlv(NFAPI_DL_CONFIG_REQUEST_CSI_RS_PDU_REL10_TAG, &pdu->csi_rs_pdu.csi_rs_pdu_rel10, ppWritePackedMsg, end, &pack_dl_config_csi_rs_pdu_rel10_value) && + pack_tlv(NFAPI_DL_CONFIG_REQUEST_CSI_RS_PDU_REL13_TAG, &pdu->csi_rs_pdu.csi_rs_pdu_rel13, ppWritePackedMsg, end, &pack_dl_config_csi_rs_pdu_rel13_value))) + return 0; + } + break; + case NFAPI_DL_CONFIG_EPDCCH_DL_PDU_TYPE: + { + if(!(pack_tlv(NFAPI_DL_CONFIG_REQUEST_EPDCCH_PDU_REL8_TAG, &pdu->epdcch_pdu.epdcch_pdu_rel8, ppWritePackedMsg, end, &pack_dl_config_dci_dl_pdu_rel8_value) && + pack_tlv(NFAPI_DL_CONFIG_REQUEST_EPDCCH_PDU_REL9_TAG, &pdu->epdcch_pdu.epdcch_pdu_rel9, ppWritePackedMsg, end, &pack_dl_config_dci_dl_pdu_rel9_value) && + pack_tlv(NFAPI_DL_CONFIG_REQUEST_EPDCCH_PDU_REL10_TAG, &pdu->epdcch_pdu.epdcch_pdu_rel10, ppWritePackedMsg, end, &pack_dl_config_dci_dl_pdu_rel10_value) && + pack_tlv(NFAPI_DL_CONFIG_REQUEST_EPDCCH_PDU_REL11_TAG, &pdu->epdcch_pdu.epdcch_pdu_rel11, ppWritePackedMsg, end, &pack_dl_config_dci_dl_pdu_rel11_value) && + pack_tlv(NFAPI_DL_CONFIG_REQUEST_EPDCCH_PDU_REL12_TAG, &pdu->epdcch_pdu.epdcch_pdu_rel12, ppWritePackedMsg, end, &pack_dl_config_dci_dl_pdu_rel12_value) && + pack_tlv(NFAPI_DL_CONFIG_REQUEST_EPDCCH_PDU_REL13_TAG, &pdu->epdcch_pdu.epdcch_pdu_rel13, ppWritePackedMsg, end, &pack_dl_config_dci_dl_pdu_rel13_value) && + pack_tlv(NFAPI_DL_CONFIG_REQUEST_EPDCCH_PARAM_REL11_TAG, &pdu->epdcch_pdu.epdcch_params_rel11, ppWritePackedMsg, end, &pack_dl_config_epdcch_parameters_rel11_value) & + pack_tlv(NFAPI_DL_CONFIG_REQUEST_EPDCCH_PARAM_REL13_TAG, &pdu->epdcch_pdu.epdcch_params_rel13, ppWritePackedMsg, end, &pack_dl_config_epdcch_parameters_rel13_value))) + return 0; + } + break; + case NFAPI_DL_CONFIG_MPDCCH_PDU_TYPE: + { + if(!(pack_tlv(NFAPI_DL_CONFIG_REQUEST_MPDCCH_PDU_REL13_TAG, &pdu->mpdcch_pdu.mpdcch_pdu_rel13, ppWritePackedMsg, end, &pack_dl_config_mpdcch_pdu_rel13_value))) + return 0; + } + break; + case NFAPI_DL_CONFIG_NBCH_PDU_TYPE: + { + if(!(pack_tlv(NFAPI_DL_CONFIG_REQUEST_NBCH_PDU_REL13_TAG, &pdu->nbch_pdu.nbch_pdu_rel13, ppWritePackedMsg, end, &pack_dl_config_nbch_pdu_rel13_value))) + return 0; + } + break; + case NFAPI_DL_CONFIG_NPDCCH_PDU_TYPE: + { + if(!(pack_tlv(NFAPI_DL_CONFIG_REQUEST_NPDCCH_PDU_REL13_TAG, &pdu->npdcch_pdu.npdcch_pdu_rel13, ppWritePackedMsg, end, &pack_dl_config_npdcch_pdu_rel13_value))) + return 0; + } + break; + case NFAPI_DL_CONFIG_NDLSCH_PDU_TYPE: + { + if(!(pack_tlv(NFAPI_DL_CONFIG_REQUEST_NDLSCH_PDU_REL13_TAG, &pdu->ndlsch_pdu.ndlsch_pdu_rel13, ppWritePackedMsg, end, &pack_dl_config_ndlsch_pdu_rel13_value))) + return 0; + } + break; + default: + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "FIXME : Invalid pdu type %d \n", pdu->pdu_type ); + } + break; + }; + + // add 1 for the pdu_type. The delta will include the pdu_size + pdu->pdu_size = 1 + (*ppWritePackedMsg - pWritePackedMsgPduSize); + push8(pdu->pdu_size, &pWritePackedMsgPduSize, end); + } + + return 1; +} + + +static uint8_t pack_dl_tti_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) +{ + nfapi_nr_dl_tti_request_t *pNfapiMsg = (nfapi_nr_dl_tti_request_t*)msg; + + if (!(push16(pNfapiMsg->SFN , ppWritePackedMsg, end) && + push16(pNfapiMsg->Slot , ppWritePackedMsg, end) && + push8(pNfapiMsg->dl_tti_request_body.nGroup , ppWritePackedMsg, end) && + push8(pNfapiMsg->dl_tti_request_body.nPDUs , ppWritePackedMsg, end) && + pusharray8(pNfapiMsg->dl_tti_request_body.nUe ,256,pNfapiMsg->dl_tti_request_body.nGroup, ppWritePackedMsg, end) + //pusharray8(pNfapiMsg->PduIdx[0] ,256,256, ppWritePackedMsg, end) + )) + return 0; + + int arr[12]; + for(int i=0;idl_tti_request_body.nGroup;i++) + { + for(int j=0;jdl_tti_request_body.nUe[i];j++) + { + arr[j] = pNfapiMsg->dl_tti_request_body.PduIdx[i][j]; + } + if(!(pusharrays32(arr,12,pNfapiMsg->dl_tti_request_body.nUe[i],ppWritePackedMsg, end))) + return 0; + } + + for(int i=0;idl_tti_request_body.nPDUs;i++) + { + if(!pack_dl_tti_request_body_value(&pNfapiMsg->dl_tti_request_body.dl_tti_pdu_list[i],ppWritePackedMsg,end)) + return 0; + } + +return 1; +} + + +static uint8_t pack_dl_config_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) +{ + nfapi_dl_config_request_t *pNfapiMsg = (nfapi_dl_config_request_t*)msg; + + //return ( push16(pNfapiMsg->sfn_sf, ppWritePackedMsg, end) && + //pack_tlv(NFAPI_DL_CONFIG_REQUEST_BODY_TAG, &pNfapiMsg->dl_config_request_body, ppWritePackedMsg, end, &pack_dl_config_request_body_value) && + //pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); + { + uint8_t x = push16(pNfapiMsg->sfn_sf, ppWritePackedMsg, end); + uint8_t y = pack_tlv(NFAPI_DL_CONFIG_REQUEST_BODY_TAG, &pNfapiMsg->dl_config_request_body, ppWritePackedMsg, end, &pack_dl_config_request_body_value); + uint8_t z = pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config); + + if (!x || !y || !z) + { + NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() NFAPI_DL_CONFIG_REQUEST x:%u y:%u z:%u \n", __FUNCTION__,x,y,z); + } + + return x && y && z; + } +} + + + + +static uint8_t pack_ul_config_request_ulsch_rel8_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t * end) +{ + nfapi_ul_config_ulsch_pdu_rel8_t* ulsch_pdu_rel8 = (nfapi_ul_config_ulsch_pdu_rel8_t*)tlv; + + return( push32(ulsch_pdu_rel8->handle, ppWritePackedMsg, end) && + push16(ulsch_pdu_rel8->size, ppWritePackedMsg, end) && + push16(ulsch_pdu_rel8->rnti, ppWritePackedMsg, end) && + push8(ulsch_pdu_rel8->resource_block_start, ppWritePackedMsg, end) && + push8(ulsch_pdu_rel8->number_of_resource_blocks, ppWritePackedMsg, end) && + push8(ulsch_pdu_rel8->modulation_type, ppWritePackedMsg, end) && + push8(ulsch_pdu_rel8->cyclic_shift_2_for_drms, ppWritePackedMsg, end) && + push8(ulsch_pdu_rel8->frequency_hopping_enabled_flag, ppWritePackedMsg, end) && + push8(ulsch_pdu_rel8->frequency_hopping_bits, ppWritePackedMsg, end) && + push8(ulsch_pdu_rel8->new_data_indication, ppWritePackedMsg, end) && + push8(ulsch_pdu_rel8->redundancy_version, ppWritePackedMsg, end) && + push8(ulsch_pdu_rel8->harq_process_number, ppWritePackedMsg, end) && + push8(ulsch_pdu_rel8->ul_tx_mode, ppWritePackedMsg, end) && + push8(ulsch_pdu_rel8->current_tx_nb, ppWritePackedMsg, end) && + push8(ulsch_pdu_rel8->n_srs, ppWritePackedMsg, end)); +} +static uint8_t pack_ul_config_request_ulsch_rel10_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_ul_config_ulsch_pdu_rel10_t* ulsch_pdu_rel10 = (nfapi_ul_config_ulsch_pdu_rel10_t*)tlv; + + return (push8(ulsch_pdu_rel10->resource_allocation_type, ppWritePackedMsg, end) && + push32(ulsch_pdu_rel10->resource_block_coding, ppWritePackedMsg, end) && + push8(ulsch_pdu_rel10->transport_blocks, ppWritePackedMsg, end) && + push8(ulsch_pdu_rel10->transmission_scheme, ppWritePackedMsg, end) && + push8(ulsch_pdu_rel10->number_of_layers, ppWritePackedMsg, end) && + push8(ulsch_pdu_rel10->codebook_index, ppWritePackedMsg, end) && + push8(ulsch_pdu_rel10->disable_sequence_hopping_flag, ppWritePackedMsg, end)); +} + +static uint8_t pack_ul_config_request_ulsch_rel11_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_ul_config_ulsch_pdu_rel11_t* ulsch_pdu_rel11 = (nfapi_ul_config_ulsch_pdu_rel11_t*)tlv; + + return (push8(ulsch_pdu_rel11->virtual_cell_id_enabled_flag, ppWritePackedMsg, end) && + push16(ulsch_pdu_rel11->npusch_identity, ppWritePackedMsg, end) && + push8(ulsch_pdu_rel11->dmrs_config_flag, ppWritePackedMsg, end) && + push16(ulsch_pdu_rel11->ndmrs_csh_identity, ppWritePackedMsg, end)); +} + +static uint8_t pack_ul_config_request_ulsch_rel13_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_ul_config_ulsch_pdu_rel13_t* ulsch_pdu_rel13 = (nfapi_ul_config_ulsch_pdu_rel13_t*)tlv; + + return (push8(ulsch_pdu_rel13->ue_type, ppWritePackedMsg, end) && + push16(ulsch_pdu_rel13->total_number_of_repetitions, ppWritePackedMsg, end) && + push16(ulsch_pdu_rel13->repetition_number, ppWritePackedMsg, end) && + push16(ulsch_pdu_rel13->initial_transmission_sf_io, ppWritePackedMsg, end) && + push8(ulsch_pdu_rel13->empty_symbols_due_to_re_tunning, ppWritePackedMsg, end)); +} + +//Pack fns for ul_tti PDUS + + +static uint8_t pack_ul_tti_request_prach_pdu(nfapi_nr_prach_pdu_t* prach_pdu, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + return( + push16(prach_pdu->phys_cell_id, ppWritePackedMsg, end) && + push8(prach_pdu->num_prach_ocas, ppWritePackedMsg, end) && + push8(prach_pdu->prach_format, ppWritePackedMsg, end) && + push8(prach_pdu->num_ra, ppWritePackedMsg, end) && + push8(prach_pdu->prach_start_symbol, ppWritePackedMsg, end) && + push16(prach_pdu->num_cs, ppWritePackedMsg, end) + // TODO: ignoring beamforming tlv for now + ); + +} + +static uint8_t pack_ul_tti_request_pucch_pdu(nfapi_nr_pucch_pdu_t* pucch_pdu, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + return( + push16(pucch_pdu->rnti, ppWritePackedMsg, end) && + push32(pucch_pdu->handle, ppWritePackedMsg, end) && + push16(pucch_pdu->bwp_size, ppWritePackedMsg, end) && + push16(pucch_pdu->bwp_start, ppWritePackedMsg, end) && + push8(pucch_pdu->subcarrier_spacing, ppWritePackedMsg, end) && + push8(pucch_pdu->cyclic_prefix, ppWritePackedMsg, end) && + push8(pucch_pdu->format_type, ppWritePackedMsg, end) && + push8(pucch_pdu->multi_slot_tx_indicator, ppWritePackedMsg, end) && + push16(pucch_pdu->prb_start, ppWritePackedMsg, end) && + push16(pucch_pdu->prb_size, ppWritePackedMsg, end) && + push8(pucch_pdu->start_symbol_index, ppWritePackedMsg, end) && + push8(pucch_pdu->nr_of_symbols, ppWritePackedMsg, end) && + push8(pucch_pdu->freq_hop_flag, ppWritePackedMsg, end) && + push16(pucch_pdu->second_hop_prb, ppWritePackedMsg, end) && + push8(pucch_pdu->group_hop_flag, ppWritePackedMsg, end) && + push8(pucch_pdu->sequence_hop_flag, ppWritePackedMsg, end) && + push16(pucch_pdu->hopping_id, ppWritePackedMsg, end) && + push16(pucch_pdu->initial_cyclic_shift, ppWritePackedMsg, end) && + push16(pucch_pdu->data_scrambling_id, ppWritePackedMsg, end) && + push8(pucch_pdu->time_domain_occ_idx, ppWritePackedMsg, end) && + push8(pucch_pdu->pre_dft_occ_idx, ppWritePackedMsg, end) && + push8(pucch_pdu->pre_dft_occ_len, ppWritePackedMsg, end) && + push8(pucch_pdu->add_dmrs_flag, ppWritePackedMsg, end) && + push16(pucch_pdu->dmrs_scrambling_id, ppWritePackedMsg, end) && + push8(pucch_pdu->dmrs_cyclic_shift, ppWritePackedMsg, end) && + push8(pucch_pdu->sr_flag, ppWritePackedMsg, end) && + push8(pucch_pdu->bit_len_harq, ppWritePackedMsg, end) && + push16(pucch_pdu->bit_len_csi_part1, ppWritePackedMsg, end) && + push16(pucch_pdu->bit_len_csi_part2, ppWritePackedMsg, end) + // TODO: ignoring beamforming tlv for now + ); + +} + + +static uint8_t pack_ul_tti_request_pusch_pdu(nfapi_nr_pusch_pdu_t* pusch_pdu, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + + if (!( + push16(pusch_pdu->pdu_bit_map, ppWritePackedMsg, end) && + push16(pusch_pdu->rnti, ppWritePackedMsg, end) && + push32(pusch_pdu->handle, ppWritePackedMsg, end) && + push16(pusch_pdu->bwp_size, ppWritePackedMsg, end) && + push16(pusch_pdu->bwp_start, ppWritePackedMsg, end) && + push8(pusch_pdu->subcarrier_spacing, ppWritePackedMsg, end) && + push8(pusch_pdu->cyclic_prefix, ppWritePackedMsg, end) && + push16(pusch_pdu->target_code_rate, ppWritePackedMsg, end) && + push8(pusch_pdu->qam_mod_order, ppWritePackedMsg, end) && + push8(pusch_pdu->mcs_index, ppWritePackedMsg, end) && + push8(pusch_pdu->mcs_table, ppWritePackedMsg, end) && + push8(pusch_pdu->transform_precoding, ppWritePackedMsg, end) && + push16(pusch_pdu->data_scrambling_id, ppWritePackedMsg, end) && + push8(pusch_pdu->nrOfLayers, ppWritePackedMsg, end) && + push16(pusch_pdu->ul_dmrs_symb_pos, ppWritePackedMsg, end) && + push8(pusch_pdu->dmrs_config_type, ppWritePackedMsg, end) && + push16(pusch_pdu->ul_dmrs_scrambling_id, ppWritePackedMsg, end) && + push8(pusch_pdu->scid, ppWritePackedMsg, end) && + push8(pusch_pdu->num_dmrs_cdm_grps_no_data, ppWritePackedMsg, end) && + push16(pusch_pdu->dmrs_ports, ppWritePackedMsg, end) && + push8(pusch_pdu->resource_alloc, ppWritePackedMsg, end) && + push8(pusch_pdu->resource_alloc,ppWritePackedMsg, end) && + push16(pusch_pdu->dmrs_ports, ppWritePackedMsg, end) && + push16(pusch_pdu->rb_start, ppWritePackedMsg, end) && + push16(pusch_pdu->rb_size, ppWritePackedMsg, end) && + push8(pusch_pdu->vrb_to_prb_mapping, ppWritePackedMsg, end) && + push8(pusch_pdu->frequency_hopping, ppWritePackedMsg, end) && + push16(pusch_pdu->tx_direct_current_location, ppWritePackedMsg, end) && + push8(pusch_pdu->uplink_frequency_shift_7p5khz, ppWritePackedMsg, end) && + push8(pusch_pdu->start_symbol_index, ppWritePackedMsg, end) && + push8(pusch_pdu->nr_of_symbols, ppWritePackedMsg, end) + // TODO: ignoring beamforming tlv for now + )) + return 0; + + + //Pack Optional Data only included if indicated in pduBitmap + switch(pusch_pdu->pdu_bit_map){ + case PUSCH_PDU_BITMAP_PUSCH_DATA: + { + // pack optional TLVs + return( + push8(pusch_pdu->pusch_data.rv_index, ppWritePackedMsg, end) && + push8(pusch_pdu->pusch_data.harq_process_id, ppWritePackedMsg, end) && + push32(pusch_pdu->pusch_data.tb_size, ppWritePackedMsg, end) && + push16(pusch_pdu->pusch_data.num_cb, ppWritePackedMsg, end) && + pusharray8(pusch_pdu->pusch_data.cb_present_and_position,1,1,ppWritePackedMsg, end) + ); + } + break; + + case PUSCH_PDU_BITMAP_PUSCH_UCI: + { + return( + push16(pusch_pdu->pusch_uci.harq_ack_bit_length, ppWritePackedMsg, end) && + push16(pusch_pdu->pusch_uci.csi_part1_bit_length, ppWritePackedMsg, end) && + push16(pusch_pdu->pusch_uci.csi_part2_bit_length, ppWritePackedMsg, end) && + push8(pusch_pdu->pusch_uci.alpha_scaling, ppWritePackedMsg, end) && + push8(pusch_pdu->pusch_uci.beta_offset_harq_ack, ppWritePackedMsg, end) && + push8(pusch_pdu->pusch_uci.beta_offset_csi1, ppWritePackedMsg, end) && + push8(pusch_pdu->pusch_uci.beta_offset_csi2, ppWritePackedMsg, end) + ); + } + break; + + case PUSCH_PDU_BITMAP_PUSCH_PTRS: + { + return( + push8(pusch_pdu->pusch_ptrs.num_ptrs_ports, ppWritePackedMsg, end) && + push8(pusch_pdu->pusch_ptrs.ptrs_ports_list->ptrs_dmrs_port, ppWritePackedMsg, end) && + push16(pusch_pdu->pusch_ptrs.ptrs_ports_list->ptrs_port_index, ppWritePackedMsg, end) && + push8(pusch_pdu->pusch_ptrs.ptrs_ports_list->ptrs_re_offset, ppWritePackedMsg, end) && + push8(pusch_pdu->pusch_ptrs.ptrs_time_density, ppWritePackedMsg, end) && + push8(pusch_pdu->pusch_ptrs.ptrs_freq_density, ppWritePackedMsg, end) && + push8(pusch_pdu->pusch_ptrs.ul_ptrs_power, ppWritePackedMsg, end) + ); + } + break; + + case PUSCH_PDU_BITMAP_DFTS_OFDM: + { + return( + push8(pusch_pdu->dfts_ofdm.low_papr_group_number, ppWritePackedMsg, end) && + push16(pusch_pdu->dfts_ofdm.low_papr_sequence_number, ppWritePackedMsg, end) && + push8(pusch_pdu->dfts_ofdm.ul_ptrs_sample_density, ppWritePackedMsg, end) && + push8(pusch_pdu->dfts_ofdm.ul_ptrs_time_density_transform_precoding, ppWritePackedMsg, end) + ); + } + break; + + default: + { + NFAPI_TRACE(NFAPI_TRACE_INFO, "Invalid pdu bitmap %d \n", pusch_pdu->pdu_bit_map ); + } + } + + return 1; +} + +static uint8_t pack_ul_tti_request_srs_pdu(nfapi_nr_srs_pdu_t* srs_pdu, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + return( + push16(srs_pdu->rnti, ppWritePackedMsg, end) && + push32(srs_pdu->handle, ppWritePackedMsg, end) && + push16(srs_pdu->bwp_size, ppWritePackedMsg, end) && + push16(srs_pdu->bwp_start, ppWritePackedMsg, end) && + push8(srs_pdu->subcarrier_spacing, ppWritePackedMsg, end) && + push8(srs_pdu->cyclic_prefix, ppWritePackedMsg, end) && + push8(srs_pdu->num_ant_ports, ppWritePackedMsg, end) && + push8(srs_pdu->num_symbols, ppWritePackedMsg, end) && + push8(srs_pdu->num_repetitions, ppWritePackedMsg, end) && + push8(srs_pdu->time_start_position, ppWritePackedMsg, end) && + push8(srs_pdu->config_index, ppWritePackedMsg, end) && + push16(srs_pdu->sequence_id, ppWritePackedMsg, end) && + push8(srs_pdu->bandwidth_index, ppWritePackedMsg, end) && + push8(srs_pdu->comb_size, ppWritePackedMsg, end) && + push8(srs_pdu->comb_offset, ppWritePackedMsg, end) && + push8(srs_pdu->cyclic_shift, ppWritePackedMsg, end) && + push8(srs_pdu->frequency_position, ppWritePackedMsg, end) && + push8(srs_pdu->frequency_shift, ppWritePackedMsg, end) && + push8(srs_pdu->frequency_hopping, ppWritePackedMsg, end) && + push8(srs_pdu->group_or_sequence_hopping, ppWritePackedMsg, end) && + push8(srs_pdu->resource_type, ppWritePackedMsg, end) && + push16(srs_pdu->t_srs, ppWritePackedMsg, end) && + push16(srs_pdu->t_offset, ppWritePackedMsg, end) + + // TODO: ignoring beamforming tlv for now + ); + +} + +static uint8_t pack_ul_config_request_ulsch_pdu(nfapi_ul_config_ulsch_pdu* ulsch_pdu, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + return ( pack_tlv(NFAPI_UL_CONFIG_REQUEST_ULSCH_PDU_REL8_TAG, &ulsch_pdu->ulsch_pdu_rel8, ppWritePackedMsg, end, &pack_ul_config_request_ulsch_rel8_value) && + pack_tlv(NFAPI_UL_CONFIG_REQUEST_ULSCH_PDU_REL10_TAG, &ulsch_pdu->ulsch_pdu_rel10, ppWritePackedMsg, end, &pack_ul_config_request_ulsch_rel10_value) && + pack_tlv(NFAPI_UL_CONFIG_REQUEST_ULSCH_PDU_REL11_TAG, &ulsch_pdu->ulsch_pdu_rel11, ppWritePackedMsg, end, &pack_ul_config_request_ulsch_rel11_value) && + pack_tlv(NFAPI_UL_CONFIG_REQUEST_ULSCH_PDU_REL13_TAG, &ulsch_pdu->ulsch_pdu_rel13, ppWritePackedMsg, end, &pack_ul_config_request_ulsch_rel13_value)); +} + +static uint8_t pack_ul_config_request_cqi_ri_rel8_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_ul_config_cqi_ri_information_rel8_t* cqi_ri_info_rel8 = (nfapi_ul_config_cqi_ri_information_rel8_t*)tlv; + + return ( push8(cqi_ri_info_rel8->dl_cqi_pmi_size_rank_1, ppWritePackedMsg, end) && + push8(cqi_ri_info_rel8->dl_cqi_pmi_size_rank_greater_1, ppWritePackedMsg, end) && + push8(cqi_ri_info_rel8->ri_size, ppWritePackedMsg, end) && + push8(cqi_ri_info_rel8->delta_offset_cqi, ppWritePackedMsg, end) && + push8(cqi_ri_info_rel8->delta_offset_ri, ppWritePackedMsg, end)); +} + +static uint8_t pack_ul_config_request_cqi_ri_rel9_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_ul_config_cqi_ri_information_rel9_t* cqi_ri_info_rel9 = (nfapi_ul_config_cqi_ri_information_rel9_t*)tlv; + + if(!(push8(cqi_ri_info_rel9->report_type, ppWritePackedMsg, end) && + push8(cqi_ri_info_rel9->delta_offset_cqi, ppWritePackedMsg, end) && + push8(cqi_ri_info_rel9->delta_offset_ri, ppWritePackedMsg, end))) + { + return 0; + } + + switch(cqi_ri_info_rel9->report_type) + { + case NFAPI_CSI_REPORT_TYPE_PERIODIC: + { + if(!(push8(cqi_ri_info_rel9->periodic_cqi_pmi_ri_report.dl_cqi_pmi_ri_size, ppWritePackedMsg, end) && + push8(cqi_ri_info_rel9->periodic_cqi_pmi_ri_report.control_type, ppWritePackedMsg, end))) + { + return 0; + } + } + break; + case NFAPI_CSI_REPORT_TYPE_APERIODIC: + { + if(push8(cqi_ri_info_rel9->aperiodic_cqi_pmi_ri_report.number_of_cc, ppWritePackedMsg, end) == 0) + return 0; + + uint8_t i; + for(i = 0; i < cqi_ri_info_rel9->aperiodic_cqi_pmi_ri_report.number_of_cc; ++i) + { + if(push8(cqi_ri_info_rel9->aperiodic_cqi_pmi_ri_report.cc[i].ri_size, ppWritePackedMsg, end) == 0) + return 0; + + uint8_t j; + for(j = 0; j < 8; ++j) + { + if(push8(cqi_ri_info_rel9->aperiodic_cqi_pmi_ri_report.cc[i].dl_cqi_pmi_size[j], ppWritePackedMsg, end) == 0) + return 0; + } + } + } + break; + default: + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "FIXME : Invalid report type %d \n", cqi_ri_info_rel9->report_type ); + } + break; + }; + + return 1; +} + +static uint8_t pack_ul_config_request_cqi_ri_rel13_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_ul_config_cqi_ri_information_rel13_t* cqi_ri_info_rel13 = (nfapi_ul_config_cqi_ri_information_rel13_t*)tlv; + + switch(cqi_ri_info_rel13->report_type) + { + case NFAPI_CSI_REPORT_TYPE_PERIODIC: + { + if(push16(cqi_ri_info_rel13->periodic_cqi_pmi_ri_report.dl_cqi_pmi_ri_size_2, ppWritePackedMsg, end) == 0) + return 0; + } + break; + case NFAPI_CSI_REPORT_TYPE_APERIODIC: + { + // No parameters + } + break; + default: + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "FIXME : Invalid report type %d \n", cqi_ri_info_rel13->report_type ); + } + break; + }; + + return 1; +} + +static uint8_t pack_ul_config_request_cqi_ri_information(nfapi_ul_config_cqi_ri_information* cqi_ri_info, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + return (pack_tlv(NFAPI_UL_CONFIG_REQUEST_CQI_RI_INFORMATION_REL8_TAG, &cqi_ri_info->cqi_ri_information_rel8, ppWritePackedMsg, end, &pack_ul_config_request_cqi_ri_rel8_value) && + pack_tlv(NFAPI_UL_CONFIG_REQUEST_CQI_RI_INFORMATION_REL9_TAG, &cqi_ri_info->cqi_ri_information_rel9, ppWritePackedMsg, end, &pack_ul_config_request_cqi_ri_rel9_value) && + pack_tlv(NFAPI_UL_CONFIG_REQUEST_CQI_RI_INFORMATION_REL13_TAG, &cqi_ri_info->cqi_ri_information_rel13, ppWritePackedMsg, end, &pack_ul_config_request_cqi_ri_rel13_value)); + +} + +static uint8_t pack_ul_config_request_init_tx_params_rel8_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_ul_config_initial_transmission_parameters_rel8_t* init_tx_params_rel8 = (nfapi_ul_config_initial_transmission_parameters_rel8_t*)tlv; + + return (push8(init_tx_params_rel8->n_srs_initial, ppWritePackedMsg, end) && + push8(init_tx_params_rel8->initial_number_of_resource_blocks, ppWritePackedMsg, end)); +} + +static uint8_t pack_ul_config_request_initial_transmission_parameters(nfapi_ul_config_initial_transmission_parameters* init_tx_params, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + return pack_tlv(NFAPI_UL_CONFIG_REQUEST_INITIAL_TRANSMISSION_PARAMETERS_REL8_TAG, &init_tx_params->initial_transmission_parameters_rel8, ppWritePackedMsg, end, &pack_ul_config_request_init_tx_params_rel8_value); +} + +static uint8_t pack_ul_config_request_ulsch_harq_info_rel10_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_ul_config_ulsch_harq_information_rel10_t* harq_info_rel10 = (nfapi_ul_config_ulsch_harq_information_rel10_t*)tlv; + + return (push8(harq_info_rel10->harq_size, ppWritePackedMsg, end) && + push8(harq_info_rel10->delta_offset_harq, ppWritePackedMsg, end) && + push8(harq_info_rel10->ack_nack_mode, ppWritePackedMsg, end)); +} +static uint8_t pack_ul_config_request_ulsch_harq_info_rel13_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_ul_config_ulsch_harq_information_rel13_t* harq_info_rel13 = (nfapi_ul_config_ulsch_harq_information_rel13_t*)tlv; + + return (push16(harq_info_rel13->harq_size_2, ppWritePackedMsg, end) && + push8(harq_info_rel13->delta_offset_harq_2, ppWritePackedMsg, end)); +} + +static uint8_t pack_ul_config_request_ulsch_harq_information(nfapi_ul_config_ulsch_harq_information* harq_info, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + return ( pack_tlv(NFAPI_UL_CONFIG_REQUEST_ULSCH_HARQ_INFORMATION_REL10_TAG, &harq_info->harq_information_rel10, ppWritePackedMsg, end, &pack_ul_config_request_ulsch_harq_info_rel10_value) && + pack_tlv(NFAPI_UL_CONFIG_REQUEST_ULSCH_HARQ_INFORMATION_REL13_TAG, &harq_info->harq_information_rel13, ppWritePackedMsg, end, &pack_ul_config_request_ulsch_harq_info_rel13_value)); +} + +static uint8_t pack_ul_config_request_ue_info_rel8_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_ul_config_ue_information_rel8_t* ue_info_rel8 = (nfapi_ul_config_ue_information_rel8_t*)tlv; + + return ( push32(ue_info_rel8->handle, ppWritePackedMsg, end) && + push16(ue_info_rel8->rnti, ppWritePackedMsg, end)); +} +static uint8_t pack_ul_config_request_ue_info_rel11_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_ul_config_ue_information_rel11_t* ue_info_rel11 = (nfapi_ul_config_ue_information_rel11_t*)tlv; + + return ( push8(ue_info_rel11->virtual_cell_id_enabled_flag, ppWritePackedMsg, end) && + push16(ue_info_rel11->npusch_identity, ppWritePackedMsg, end)); +} +static uint8_t pack_ul_config_request_ue_info_rel13_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_ul_config_ue_information_rel13_t* ue_info_rel13 = (nfapi_ul_config_ue_information_rel13_t*)tlv; + + return ( push8(ue_info_rel13->ue_type, ppWritePackedMsg, end) && + push8(ue_info_rel13->empty_symbols, ppWritePackedMsg, end) && + push16(ue_info_rel13->total_number_of_repetitions, ppWritePackedMsg, end) && + push16(ue_info_rel13->repetition_number, ppWritePackedMsg, end)); +} + +static uint8_t pack_ul_config_request_ue_information(nfapi_ul_config_ue_information* ue_info, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + return ( pack_tlv(NFAPI_UL_CONFIG_REQUEST_UE_INFORMATION_REL8_TAG, &ue_info->ue_information_rel8, ppWritePackedMsg, end, &pack_ul_config_request_ue_info_rel8_value) && + pack_tlv(NFAPI_UL_CONFIG_REQUEST_UE_INFORMATION_REL11_TAG, &ue_info->ue_information_rel11, ppWritePackedMsg, end, &pack_ul_config_request_ue_info_rel11_value) && + pack_tlv(NFAPI_UL_CONFIG_REQUEST_UE_INFORMATION_REL13_TAG, &ue_info->ue_information_rel13, ppWritePackedMsg, end, &pack_ul_config_request_ue_info_rel13_value)); +} + +static uint8_t pack_ul_config_request_harq_info_rel10_tdd_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_ul_config_harq_information_rel10_tdd_t* harq_info_rel10_tdd = (nfapi_ul_config_harq_information_rel10_tdd_t*)tlv; + + return ( push8(harq_info_rel10_tdd->harq_size, ppWritePackedMsg, end) && + push8(harq_info_rel10_tdd->ack_nack_mode, ppWritePackedMsg, end) && + push8(harq_info_rel10_tdd->number_of_pucch_resources, ppWritePackedMsg, end) && + push16(harq_info_rel10_tdd->n_pucch_1_0, ppWritePackedMsg, end) && + push16(harq_info_rel10_tdd->n_pucch_1_1, ppWritePackedMsg, end) && + push16(harq_info_rel10_tdd->n_pucch_1_2, ppWritePackedMsg, end) && + push16(harq_info_rel10_tdd->n_pucch_1_3, ppWritePackedMsg, end)); +} +static uint8_t pack_ul_config_request_harq_info_rel8_fdd_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_ul_config_harq_information_rel8_fdd_t* harq_info_rel8_fdd = (nfapi_ul_config_harq_information_rel8_fdd_t*)tlv; + + return ( push16(harq_info_rel8_fdd->n_pucch_1_0, ppWritePackedMsg, end) && + push8(harq_info_rel8_fdd->harq_size, ppWritePackedMsg, end)); +} +static uint8_t pack_ul_config_request_harq_info_rel9_fdd_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_ul_config_harq_information_rel9_fdd_t* harq_info_rel9_fdd = (nfapi_ul_config_harq_information_rel9_fdd_t*)tlv; + + return ( push8(harq_info_rel9_fdd->harq_size, ppWritePackedMsg, end) && + push8(harq_info_rel9_fdd->ack_nack_mode, ppWritePackedMsg, end) && + push8(harq_info_rel9_fdd->number_of_pucch_resources, ppWritePackedMsg, end) && + push16(harq_info_rel9_fdd->n_pucch_1_0, ppWritePackedMsg, end) && + push16(harq_info_rel9_fdd->n_pucch_1_1, ppWritePackedMsg, end) && + push16(harq_info_rel9_fdd->n_pucch_1_2, ppWritePackedMsg, end) && + push16(harq_info_rel9_fdd->n_pucch_1_3, ppWritePackedMsg, end)); +} +static uint8_t pack_ul_config_request_harq_info_rel11_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_ul_config_harq_information_rel11_t* harq_info_rel11 = (nfapi_ul_config_harq_information_rel11_t*)tlv; + + return ( push8(harq_info_rel11->num_ant_ports, ppWritePackedMsg, end) && + push16(harq_info_rel11->n_pucch_2_0, ppWritePackedMsg, end) && + push16(harq_info_rel11->n_pucch_2_1, ppWritePackedMsg, end) && + push16(harq_info_rel11->n_pucch_2_2, ppWritePackedMsg, end) && + push16(harq_info_rel11->n_pucch_2_3, ppWritePackedMsg, end)); +} +static uint8_t pack_ul_config_request_harq_info_rel13_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_ul_config_harq_information_rel13_t* harq_info_rel13 = (nfapi_ul_config_harq_information_rel13_t*)tlv; + + return ( push16(harq_info_rel13->harq_size_2, ppWritePackedMsg, end) && + push8(harq_info_rel13->starting_prb, ppWritePackedMsg, end) && + push8(harq_info_rel13->n_prb, ppWritePackedMsg, end) && + push8(harq_info_rel13->cdm_index, ppWritePackedMsg, end) && + push8(harq_info_rel13->n_srs, ppWritePackedMsg, end)); +} + +static uint8_t pack_ul_config_request_harq_information(nfapi_ul_config_harq_information* harq_info, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + return ( pack_tlv(NFAPI_UL_CONFIG_REQUEST_HARQ_INFORMATION_REL10_TDD_TAG, &harq_info->harq_information_rel10_tdd, ppWritePackedMsg, end, &pack_ul_config_request_harq_info_rel10_tdd_value) && + pack_tlv(NFAPI_UL_CONFIG_REQUEST_HARQ_INFORMATION_REL8_FDD_TAG, &harq_info->harq_information_rel8_fdd, ppWritePackedMsg, end, &pack_ul_config_request_harq_info_rel8_fdd_value) && + pack_tlv(NFAPI_UL_CONFIG_REQUEST_HARQ_INFORMATION_REL9_FDD_TAG, &harq_info->harq_information_rel9_fdd, ppWritePackedMsg, end, &pack_ul_config_request_harq_info_rel9_fdd_value) && + pack_tlv(NFAPI_UL_CONFIG_REQUEST_HARQ_INFORMATION_REL11_TAG, &harq_info->harq_information_rel11, ppWritePackedMsg, end, &pack_ul_config_request_harq_info_rel11_value) && + pack_tlv(NFAPI_UL_CONFIG_REQUEST_HARQ_INFORMATION_REL13_TAG, &harq_info->harq_information_rel13, ppWritePackedMsg, end, &pack_ul_config_request_harq_info_rel13_value)); + +} + +static uint8_t pack_ul_config_request_cqi_info_rel8_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_ul_config_cqi_information_rel8_t* cqi_info_rel8 = (nfapi_ul_config_cqi_information_rel8_t*)tlv; + + return ( push16(cqi_info_rel8->pucch_index, ppWritePackedMsg, end) && + push8(cqi_info_rel8->dl_cqi_pmi_size, ppWritePackedMsg, end)); +} +static uint8_t pack_ul_config_request_cqi_info_rel10_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_ul_config_cqi_information_rel10_t* cqi_info_rel10 = (nfapi_ul_config_cqi_information_rel10_t*)tlv; + + return ( push8(cqi_info_rel10->number_of_pucch_resource, ppWritePackedMsg, end) && + push16(cqi_info_rel10->pucch_index_p1, ppWritePackedMsg, end)); +} +static uint8_t pack_ul_config_request_cqi_info_rel13_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_ul_config_cqi_information_rel13_t* cqi_info_rel13 = (nfapi_ul_config_cqi_information_rel13_t*)tlv; + + return ( push8(cqi_info_rel13->csi_mode, ppWritePackedMsg, end) && + push16(cqi_info_rel13->dl_cqi_pmi_size_2, ppWritePackedMsg, end) && + push8(cqi_info_rel13->starting_prb, ppWritePackedMsg, end) && + push8(cqi_info_rel13->n_prb, ppWritePackedMsg, end) && + push8(cqi_info_rel13->cdm_index, ppWritePackedMsg, end) && + push8(cqi_info_rel13->n_srs, ppWritePackedMsg, end)); +} + +static uint8_t pack_ul_config_request_cqi_information(nfapi_ul_config_cqi_information* cqi_info, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + return ( pack_tlv(NFAPI_UL_CONFIG_REQUEST_CQI_INFORMATION_REL8_TAG, &cqi_info->cqi_information_rel8, ppWritePackedMsg, end, &pack_ul_config_request_cqi_info_rel8_value) && + pack_tlv(NFAPI_UL_CONFIG_REQUEST_CQI_INFORMATION_REL10_TAG, &cqi_info->cqi_information_rel10, ppWritePackedMsg, end, &pack_ul_config_request_cqi_info_rel10_value) && + pack_tlv(NFAPI_UL_CONFIG_REQUEST_CQI_INFORMATION_REL13_TAG, &cqi_info->cqi_information_rel13, ppWritePackedMsg, end, &pack_ul_config_request_cqi_info_rel13_value)); + +} + +static uint8_t pack_ul_config_request_sr_info_rel8_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_ul_config_sr_information_rel8_t* sr_info_rel8 = (nfapi_ul_config_sr_information_rel8_t*)tlv; + return push16(sr_info_rel8->pucch_index, ppWritePackedMsg, end); +} +static uint8_t pack_ul_config_request_sr_info_rel10_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_ul_config_sr_information_rel10_t* sr_info_rel10 = (nfapi_ul_config_sr_information_rel10_t*)tlv; + + return ( push8(sr_info_rel10->number_of_pucch_resources, ppWritePackedMsg, end) && + push16(sr_info_rel10->pucch_index_p1, ppWritePackedMsg, end)); +} + +static uint8_t pack_ul_config_request_sr_information(nfapi_ul_config_sr_information* sr_info, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + return ( pack_tlv(NFAPI_UL_CONFIG_REQUEST_SR_INFORMATION_REL8_TAG, &sr_info->sr_information_rel8, ppWritePackedMsg, end, &pack_ul_config_request_sr_info_rel8_value) && + pack_tlv(NFAPI_UL_CONFIG_REQUEST_SR_INFORMATION_REL10_TAG, &sr_info->sr_information_rel10, ppWritePackedMsg, end, &pack_ul_config_request_sr_info_rel10_value)); +} + +static uint8_t pack_ul_config_request_srs_pdu_rel8_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_ul_config_srs_pdu_rel8_t* srs_pdu_rel8 = (nfapi_ul_config_srs_pdu_rel8_t*)tlv; + + return (push32(srs_pdu_rel8->handle, ppWritePackedMsg, end) && + push16(srs_pdu_rel8->size, ppWritePackedMsg, end) && + push16(srs_pdu_rel8->rnti, ppWritePackedMsg, end) && + push8(srs_pdu_rel8->srs_bandwidth, ppWritePackedMsg, end) && + push8(srs_pdu_rel8->frequency_domain_position, ppWritePackedMsg, end) && + push8(srs_pdu_rel8->srs_hopping_bandwidth, ppWritePackedMsg, end) && + push8(srs_pdu_rel8->transmission_comb, ppWritePackedMsg, end) && + push16(srs_pdu_rel8->i_srs, ppWritePackedMsg, end) && + push8(srs_pdu_rel8->sounding_reference_cyclic_shift, ppWritePackedMsg, end)); +} + +static uint8_t pack_ul_config_request_srs_pdu_rel10_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_ul_config_srs_pdu_rel10_t* srs_pdu_rel10 = (nfapi_ul_config_srs_pdu_rel10_t*)tlv; + return push8(srs_pdu_rel10->antenna_port, ppWritePackedMsg, end); +} + +static uint8_t pack_ul_config_request_srs_pdu_rel13_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_ul_config_srs_pdu_rel13_t* srs_pdu_rel13 = (nfapi_ul_config_srs_pdu_rel13_t*)tlv; + + return ( push8(srs_pdu_rel13->number_of_combs, ppWritePackedMsg, end)); +} + +static uint8_t pack_ul_config_request_nb_harq_rel13_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_ul_config_nb_harq_information_rel13_fdd_t* nb_harq_pdu_rel13 = (nfapi_ul_config_nb_harq_information_rel13_fdd_t*)tlv; + + return ( push8(nb_harq_pdu_rel13->harq_ack_resource, ppWritePackedMsg, end)); +} + +static uint8_t pack_ul_config_request_nulsch_pdu_rel13_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_ul_config_nulsch_pdu_rel13_t* nulsch_pdu_rel13 = (nfapi_ul_config_nulsch_pdu_rel13_t*)tlv; + + return (push8(nulsch_pdu_rel13->nulsch_format, ppWritePackedMsg, end) && + push32(nulsch_pdu_rel13->handle, ppWritePackedMsg, end) && + push16(nulsch_pdu_rel13->size, ppWritePackedMsg, end) && + push16(nulsch_pdu_rel13->rnti, ppWritePackedMsg, end) && + push8(nulsch_pdu_rel13->subcarrier_indication, ppWritePackedMsg, end) && + push8(nulsch_pdu_rel13->resource_assignment, ppWritePackedMsg, end) && + push8(nulsch_pdu_rel13->mcs, ppWritePackedMsg, end) && + push8(nulsch_pdu_rel13->redudancy_version, ppWritePackedMsg, end) && + push8(nulsch_pdu_rel13->repetition_number, ppWritePackedMsg, end) && + push8(nulsch_pdu_rel13->new_data_indication, ppWritePackedMsg, end) && + push8(nulsch_pdu_rel13->n_srs, ppWritePackedMsg, end) && + push16(nulsch_pdu_rel13->scrambling_sequence_initialization_cinit, ppWritePackedMsg, end) && + push16(nulsch_pdu_rel13->sf_idx, ppWritePackedMsg, end) && + pack_ul_config_request_ue_information(&(nulsch_pdu_rel13->ue_information), ppWritePackedMsg, end) && + pack_tlv(NFAPI_UL_CONFIG_REQUEST_NB_HARQ_INFORMATION_REL13_FDD_TAG, &nulsch_pdu_rel13->nb_harq_information.nb_harq_information_rel13_fdd, ppWritePackedMsg, end, &pack_ul_config_request_nb_harq_rel13_value)); +} +static uint8_t pack_ul_config_request_nrach_pdu_rel13_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_ul_config_nrach_pdu_rel13_t* nrach_pdu_rel13 = (nfapi_ul_config_nrach_pdu_rel13_t*)tlv; + + return ( push8(nrach_pdu_rel13->nprach_config_0, ppWritePackedMsg, end) && + push8(nrach_pdu_rel13->nprach_config_1, ppWritePackedMsg, end) && + push8(nrach_pdu_rel13->nprach_config_2, ppWritePackedMsg, end)); + +} + + + +static uint8_t pack_ul_tti_pdu_list_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_nr_ul_tti_request_number_of_pdus_t* value = (nfapi_nr_ul_tti_request_number_of_pdus_t*)tlv; + + if(!(push16(value->pdu_size, ppWritePackedMsg, end) && + push16(value->pdu_type, ppWritePackedMsg, end) )) + return 0; + + + // first match the pdu type, then call the respective function + switch(value->pdu_type) + { + case NFAPI_NR_UL_CONFIG_PRACH_PDU_TYPE: + { + if(!pack_ul_tti_request_prach_pdu(&value->prach_pdu, ppWritePackedMsg, end)) + return 0; + } + break; + + case NFAPI_NR_UL_CONFIG_PUCCH_PDU_TYPE: + { + if(!pack_ul_tti_request_pucch_pdu(&value->pucch_pdu, ppWritePackedMsg, end)) + return 0; + } + break; + case NFAPI_NR_UL_CONFIG_PUSCH_PDU_TYPE: + { + if(!pack_ul_tti_request_pusch_pdu(&value->pusch_pdu, ppWritePackedMsg, end)) + return 0; + } + break; + case NFAPI_NR_UL_CONFIG_SRS_PDU_TYPE: + { + if(!pack_ul_tti_request_srs_pdu(&value->srs_pdu, ppWritePackedMsg, end)) + return 0; + } + break; + + default: + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "FIXME : Invalid UL_TTI pdu type %d \n", value->pdu_type ); + } + break; + } + + return 1; +} + +static uint8_t pack_ul_tti_groups_list_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_nr_ul_tti_request_number_of_groups_t* value = (nfapi_nr_ul_tti_request_number_of_groups_t*)tlv; + + if(!push8(value->n_ue, ppWritePackedMsg, end)) + return 0; + for(int i=0; in_ue;i++) + { + if(!push8(value->ue_list[i].pdu_idx, ppWritePackedMsg, end)) + return 0; + } + return 1; +} + +static uint8_t pack_ul_config_request_body_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_ul_config_request_body_t* value = (nfapi_ul_config_request_body_t*)tlv; + + if(!(push8(value->number_of_pdus, ppWritePackedMsg, end) && + push8(value->rach_prach_frequency_resources, ppWritePackedMsg, end) && + push8(value->srs_present, ppWritePackedMsg, end))) + return 0; + + uint16_t i = 0; + for(i = 0; i < value->number_of_pdus; ++i) + { + nfapi_ul_config_request_pdu_t* pdu = &(value->ul_config_pdu_list[i]); + + if(push8(pdu->pdu_type, ppWritePackedMsg, end) == 0) + return 0; + + // Put a 0 size in and then determine the size after the pdu + // has been writen and write the calculated size + uint8_t* pWritePackedMsgPduSize = *ppWritePackedMsg; + pdu->pdu_size = 0; + if(push8(pdu->pdu_size, ppWritePackedMsg, end) == 0) + return 0; + + switch(pdu->pdu_type) + { + case NFAPI_UL_CONFIG_ULSCH_PDU_TYPE: + { + if(!pack_ul_config_request_ulsch_pdu(&(pdu->ulsch_pdu), ppWritePackedMsg, end)) + return 0; + } + break; + case NFAPI_UL_CONFIG_ULSCH_CQI_RI_PDU_TYPE: + { + if(!(pack_ul_config_request_ulsch_pdu(&(pdu->ulsch_cqi_ri_pdu.ulsch_pdu), ppWritePackedMsg, end) && + pack_ul_config_request_cqi_ri_information(&(pdu->ulsch_cqi_ri_pdu.cqi_ri_information), ppWritePackedMsg, end) && + pack_ul_config_request_initial_transmission_parameters(&(pdu->ulsch_cqi_ri_pdu.initial_transmission_parameters), ppWritePackedMsg, end))) + return 0; + } + break; + case NFAPI_UL_CONFIG_ULSCH_HARQ_PDU_TYPE: + { + if(!(pack_ul_config_request_ulsch_pdu(&(pdu->ulsch_harq_pdu.ulsch_pdu), ppWritePackedMsg, end) && + pack_ul_config_request_ulsch_harq_information(&(pdu->ulsch_harq_pdu.harq_information), ppWritePackedMsg, end) && + pack_ul_config_request_initial_transmission_parameters(&(pdu->ulsch_harq_pdu.initial_transmission_parameters), ppWritePackedMsg, end))) + return 0; + } + break; + case NFAPI_UL_CONFIG_ULSCH_CQI_HARQ_RI_PDU_TYPE: + { + if(!(pack_ul_config_request_ulsch_pdu(&(pdu->ulsch_cqi_harq_ri_pdu.ulsch_pdu), ppWritePackedMsg, end) && + pack_ul_config_request_cqi_ri_information(&(pdu->ulsch_cqi_harq_ri_pdu.cqi_ri_information), ppWritePackedMsg, end) && + pack_ul_config_request_ulsch_harq_information(&(pdu->ulsch_cqi_harq_ri_pdu.harq_information), ppWritePackedMsg, end) && + pack_ul_config_request_initial_transmission_parameters(&(pdu->ulsch_cqi_harq_ri_pdu.initial_transmission_parameters), ppWritePackedMsg, end))) + return 0; + } + break; + case NFAPI_UL_CONFIG_UCI_CQI_PDU_TYPE: + { + if(!(pack_ul_config_request_ue_information(&(pdu->uci_cqi_pdu.ue_information), ppWritePackedMsg, end) && + pack_ul_config_request_cqi_information(&(pdu->uci_cqi_pdu.cqi_information), ppWritePackedMsg, end))) + return 0; + } + break; + case NFAPI_UL_CONFIG_UCI_SR_PDU_TYPE: + { + if(!(pack_ul_config_request_ue_information(&(pdu->uci_sr_pdu.ue_information), ppWritePackedMsg, end) && + pack_ul_config_request_sr_information(&(pdu->uci_sr_pdu.sr_information), ppWritePackedMsg, end))) + return 0; + } + break; + case NFAPI_UL_CONFIG_UCI_HARQ_PDU_TYPE: + { + if(!(pack_ul_config_request_ue_information(&(pdu->uci_harq_pdu.ue_information), ppWritePackedMsg, end) && + pack_ul_config_request_harq_information(&(pdu->uci_harq_pdu.harq_information), ppWritePackedMsg, end))) + return 0; + } + break; + case NFAPI_UL_CONFIG_UCI_SR_HARQ_PDU_TYPE: + { + if(!(pack_ul_config_request_ue_information(&(pdu->uci_sr_harq_pdu.ue_information), ppWritePackedMsg, end) && + pack_ul_config_request_sr_information(&(pdu->uci_sr_harq_pdu.sr_information), ppWritePackedMsg, end) && + pack_ul_config_request_harq_information(&(pdu->uci_sr_harq_pdu.harq_information), ppWritePackedMsg, end))) + return 0; + } + break; + case NFAPI_UL_CONFIG_UCI_CQI_HARQ_PDU_TYPE: + { + if(!(pack_ul_config_request_ue_information(&(pdu->uci_cqi_harq_pdu.ue_information), ppWritePackedMsg, end) && + pack_ul_config_request_cqi_information(&(pdu->uci_cqi_harq_pdu.cqi_information), ppWritePackedMsg, end) && + pack_ul_config_request_harq_information(&(pdu->uci_cqi_harq_pdu.harq_information), ppWritePackedMsg, end))) + return 0; + } + break; + case NFAPI_UL_CONFIG_UCI_CQI_SR_PDU_TYPE: + { + if(!(pack_ul_config_request_ue_information(&(pdu->uci_cqi_sr_pdu.ue_information), ppWritePackedMsg, end) && + pack_ul_config_request_cqi_information(&(pdu->uci_cqi_sr_pdu.cqi_information), ppWritePackedMsg, end) && + pack_ul_config_request_sr_information(&(pdu->uci_cqi_sr_pdu.sr_information), ppWritePackedMsg, end))) + return 0; + } + break; + case NFAPI_UL_CONFIG_UCI_CQI_SR_HARQ_PDU_TYPE: + { + if(!(pack_ul_config_request_ue_information(&(pdu->uci_cqi_sr_harq_pdu.ue_information), ppWritePackedMsg, end) && + pack_ul_config_request_cqi_information(&(pdu->uci_cqi_sr_harq_pdu.cqi_information), ppWritePackedMsg, end) && + pack_ul_config_request_sr_information(&(pdu->uci_cqi_sr_harq_pdu.sr_information), ppWritePackedMsg, end) && + pack_ul_config_request_harq_information(&(pdu->uci_cqi_sr_harq_pdu.harq_information), ppWritePackedMsg, end))) + return 0; + } + break; + case NFAPI_UL_CONFIG_SRS_PDU_TYPE: + { + if(!(pack_tlv(NFAPI_UL_CONFIG_REQUEST_SRS_PDU_REL8_TAG, &pdu->srs_pdu.srs_pdu_rel8, ppWritePackedMsg, end, &pack_ul_config_request_srs_pdu_rel8_value) && + pack_tlv(NFAPI_UL_CONFIG_REQUEST_SRS_PDU_REL10_TAG, &pdu->srs_pdu.srs_pdu_rel10, ppWritePackedMsg, end, &pack_ul_config_request_srs_pdu_rel10_value) && + pack_tlv(NFAPI_UL_CONFIG_REQUEST_SRS_PDU_REL13_TAG, &pdu->srs_pdu.srs_pdu_rel13, ppWritePackedMsg, end, &pack_ul_config_request_srs_pdu_rel13_value))) + return 0; + } + break; + case NFAPI_UL_CONFIG_HARQ_BUFFER_PDU_TYPE: + { + if(!(pack_ul_config_request_ue_information(&(pdu->harq_buffer_pdu.ue_information), ppWritePackedMsg, end))) + return 0; + } + break; + case NFAPI_UL_CONFIG_ULSCH_UCI_CSI_PDU_TYPE: + { + if(!(pack_ul_config_request_ulsch_pdu(&(pdu->ulsch_uci_csi_pdu.ulsch_pdu), ppWritePackedMsg, end) && + pack_ul_config_request_cqi_information(&(pdu->ulsch_uci_csi_pdu.csi_information), ppWritePackedMsg, end))) + return 0; + } + break; + case NFAPI_UL_CONFIG_ULSCH_UCI_HARQ_PDU_TYPE: + { + if(!(pack_ul_config_request_ulsch_pdu(&(pdu->ulsch_uci_harq_pdu.ulsch_pdu), ppWritePackedMsg, end) && + pack_ul_config_request_harq_information(&(pdu->ulsch_uci_harq_pdu.harq_information), ppWritePackedMsg, end))) + return 0; + } + break; + case NFAPI_UL_CONFIG_ULSCH_CSI_UCI_HARQ_PDU_TYPE: + { + if(!(pack_ul_config_request_ulsch_pdu(&(pdu->ulsch_csi_uci_harq_pdu.ulsch_pdu), ppWritePackedMsg, end) && + pack_ul_config_request_cqi_information(&(pdu->ulsch_csi_uci_harq_pdu.csi_information), ppWritePackedMsg, end) && + pack_ul_config_request_harq_information(&(pdu->ulsch_csi_uci_harq_pdu.harq_information), ppWritePackedMsg, end))) + return 0; + } + break; + case NFAPI_UL_CONFIG_NULSCH_PDU_TYPE: + { + if(!(pack_tlv(NFAPI_UL_CONFIG_REQUEST_NULSCH_PDU_REL13_TAG, &pdu->nulsch_pdu.nulsch_pdu_rel13, ppWritePackedMsg, end, &pack_ul_config_request_nulsch_pdu_rel13_value))) + return 0; + } + break; + case NFAPI_UL_CONFIG_NRACH_PDU_TYPE: + { + if(!(pack_tlv(NFAPI_UL_CONFIG_REQUEST_NRACH_PDU_REL13_TAG, &pdu->nrach_pdu.nrach_pdu_rel13, ppWritePackedMsg, end, &pack_ul_config_request_nrach_pdu_rel13_value))) + return 0; + } + break; + default: + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "FIXME : Invalid pdu type %d \n", pdu->pdu_type ); + } + break; + }; + + // add 1 for the pdu_type. The delta will include the pdu_size + pdu->pdu_size = 1 + (*ppWritePackedMsg - pWritePackedMsgPduSize); + push8(pdu->pdu_size, &pWritePackedMsgPduSize, end); + + } + return 1; +} + + +static uint8_t pack_ul_tti_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) +{ + nfapi_nr_ul_tti_request_t *pNfapiMsg = (nfapi_nr_ul_tti_request_t*)msg; + + if (!(push16(pNfapiMsg->SFN , ppWritePackedMsg, end) && + push16(pNfapiMsg->Slot , ppWritePackedMsg, end) && + push8(pNfapiMsg->n_pdus , ppWritePackedMsg, end) && + push8(pNfapiMsg->rach_present, ppWritePackedMsg, end) && + push8(pNfapiMsg->n_ulsch, ppWritePackedMsg, end) && + push8(pNfapiMsg->n_ulcch, ppWritePackedMsg, end) && + push8(pNfapiMsg->n_group, ppWritePackedMsg, end) )) + return 0; + + for(int i=0; in_pdus; i++) + { + if(!pack_ul_tti_pdu_list_value(&pNfapiMsg->pdus_list[i], ppWritePackedMsg, end)) + return 0; + } + + for(int i=0; in_group; i++) + { + if(!pack_ul_tti_groups_list_value(&pNfapiMsg->groups_list[i], ppWritePackedMsg, end)) + return 0; + + } + + return 1; +} + + +static uint8_t pack_ul_config_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) +{ + nfapi_ul_config_request_t *pNfapiMsg = (nfapi_ul_config_request_t*)msg; + + return ( push16(pNfapiMsg->sfn_sf, ppWritePackedMsg, end) && + pack_tlv(NFAPI_UL_CONFIG_REQUEST_BODY_TAG, &pNfapiMsg->ul_config_request_body, ppWritePackedMsg, end, &pack_ul_config_request_body_value) && + pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)) ; +} + +static uint8_t pack_hi_dci0_hi_rel8_pdu_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_hi_dci0_hi_pdu_rel8_t* hi_pdu_rel8 = (nfapi_hi_dci0_hi_pdu_rel8_t*)tlv; + + return ( push8(hi_pdu_rel8->resource_block_start, ppWritePackedMsg, end) && + push8(hi_pdu_rel8->cyclic_shift_2_for_drms, ppWritePackedMsg, end) && + push8(hi_pdu_rel8->hi_value, ppWritePackedMsg, end) && + push8(hi_pdu_rel8->i_phich, ppWritePackedMsg, end) && + push16(hi_pdu_rel8->transmission_power, ppWritePackedMsg, end)); +} + +static uint8_t pack_hi_dci0_hi_rel10_pdu_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_hi_dci0_hi_pdu_rel10_t* hi_pdu_rel10 = (nfapi_hi_dci0_hi_pdu_rel10_t*)tlv; + + return ( push8(hi_pdu_rel10->flag_tb2, ppWritePackedMsg, end) && + push8(hi_pdu_rel10->hi_value_2, ppWritePackedMsg, end)); +} + +static uint8_t pack_hi_dci0_dci_rel8_pdu_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_hi_dci0_dci_pdu_rel8_t* dci_pdu_rel8 = (nfapi_hi_dci0_dci_pdu_rel8_t*)tlv; + + return ( push8(dci_pdu_rel8->dci_format, ppWritePackedMsg, end) && + push8(dci_pdu_rel8->cce_index, ppWritePackedMsg, end) && + push8(dci_pdu_rel8->aggregation_level, ppWritePackedMsg, end) && + push16(dci_pdu_rel8->rnti, ppWritePackedMsg, end) && + push8(dci_pdu_rel8->resource_block_start, ppWritePackedMsg, end) && + push8(dci_pdu_rel8->number_of_resource_block, ppWritePackedMsg, end) && + push8(dci_pdu_rel8->mcs_1, ppWritePackedMsg, end) && + push8(dci_pdu_rel8->cyclic_shift_2_for_drms, ppWritePackedMsg, end) && + push8(dci_pdu_rel8->frequency_hopping_enabled_flag, ppWritePackedMsg, end) && + push8(dci_pdu_rel8->frequency_hopping_bits, ppWritePackedMsg, end) && + push8(dci_pdu_rel8->new_data_indication_1, ppWritePackedMsg, end) && + push8(dci_pdu_rel8->ue_tx_antenna_seleciton, ppWritePackedMsg, end) && + push8(dci_pdu_rel8->tpc, ppWritePackedMsg, end) && + push8(dci_pdu_rel8->cqi_csi_request, ppWritePackedMsg, end) && + push8(dci_pdu_rel8->ul_index, ppWritePackedMsg, end) && + push8(dci_pdu_rel8->dl_assignment_index, ppWritePackedMsg, end) && + push32(dci_pdu_rel8->tpc_bitmap, ppWritePackedMsg, end) && + push16(dci_pdu_rel8->transmission_power, ppWritePackedMsg, end)); +} + +static uint8_t pack_hi_dci0_dci_rel10_pdu_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_hi_dci0_dci_pdu_rel10_t* dci_pdu_rel10 = (nfapi_hi_dci0_dci_pdu_rel10_t*)tlv; + + return ( push8(dci_pdu_rel10->cross_carrier_scheduling_flag, ppWritePackedMsg, end) && + push8(dci_pdu_rel10->carrier_indicator, ppWritePackedMsg, end) && + push8(dci_pdu_rel10->size_of_cqi_csi_feild, ppWritePackedMsg, end) && + push8(dci_pdu_rel10->srs_flag, ppWritePackedMsg, end) && + push8(dci_pdu_rel10->srs_request, ppWritePackedMsg, end) && + push8(dci_pdu_rel10->resource_allocation_flag, ppWritePackedMsg, end) && + push8(dci_pdu_rel10->resource_allocation_type, ppWritePackedMsg, end) && + push32(dci_pdu_rel10->resource_block_coding, ppWritePackedMsg, end) && + push8(dci_pdu_rel10->mcs_2, ppWritePackedMsg, end) && + push8(dci_pdu_rel10->new_data_indication_2, ppWritePackedMsg, end) && + push8(dci_pdu_rel10->number_of_antenna_ports, ppWritePackedMsg, end) && + push8(dci_pdu_rel10->tpmi, ppWritePackedMsg, end) && + push8(dci_pdu_rel10->total_dci_length_including_padding, ppWritePackedMsg, end) && + push8(dci_pdu_rel10->n_ul_rb, ppWritePackedMsg, end)); +} + +static uint8_t pack_hi_dci0_dci_rel12_pdu_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_hi_dci0_dci_pdu_rel12_t* dci_pdu_rel12 = (nfapi_hi_dci0_dci_pdu_rel12_t*)tlv; + + return ( push8(dci_pdu_rel12->pscch_resource, ppWritePackedMsg, end) && + push8(dci_pdu_rel12->time_resource_pattern, ppWritePackedMsg, end)); +} + +static uint8_t pack_hi_dci0_mpdcch_dci_rel13_pdu_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_hi_dci0_mpdcch_dci_pdu_rel13_t* mpdcch_dci_pdu_rel13 = (nfapi_hi_dci0_mpdcch_dci_pdu_rel13_t*)tlv; + + return ( push8(mpdcch_dci_pdu_rel13->mpdcch_narrowband, ppWritePackedMsg, end) && + push8(mpdcch_dci_pdu_rel13->number_of_prb_pairs, ppWritePackedMsg, end) && + push8(mpdcch_dci_pdu_rel13->resource_block_assignment, ppWritePackedMsg, end) && + push8(mpdcch_dci_pdu_rel13->mpdcch_transmission_type, ppWritePackedMsg, end) && + push8(mpdcch_dci_pdu_rel13->start_symbol, ppWritePackedMsg, end) && + push8(mpdcch_dci_pdu_rel13->ecce_index, ppWritePackedMsg, end) && + push8(mpdcch_dci_pdu_rel13->aggreagation_level, ppWritePackedMsg, end) && + push8(mpdcch_dci_pdu_rel13->rnti_type, ppWritePackedMsg, end) && + push16(mpdcch_dci_pdu_rel13->rnti, ppWritePackedMsg, end) && + push8(mpdcch_dci_pdu_rel13->ce_mode, ppWritePackedMsg, end) && + push16(mpdcch_dci_pdu_rel13->drms_scrambling_init, ppWritePackedMsg, end) && + push16(mpdcch_dci_pdu_rel13->initial_transmission_sf_io, ppWritePackedMsg, end) && + push16(mpdcch_dci_pdu_rel13->transmission_power, ppWritePackedMsg, end) && + push8(mpdcch_dci_pdu_rel13->dci_format, ppWritePackedMsg, end) && + push8(mpdcch_dci_pdu_rel13->resource_block_start, ppWritePackedMsg, end) && + push8(mpdcch_dci_pdu_rel13->number_of_resource_blocks, ppWritePackedMsg, end) && + push8(mpdcch_dci_pdu_rel13->mcs, ppWritePackedMsg, end) && + push8(mpdcch_dci_pdu_rel13->pusch_repetition_levels, ppWritePackedMsg, end) && + push8(mpdcch_dci_pdu_rel13->frequency_hopping_flag, ppWritePackedMsg, end) && + push8(mpdcch_dci_pdu_rel13->new_data_indication, ppWritePackedMsg, end) && + push8(mpdcch_dci_pdu_rel13->harq_process, ppWritePackedMsg, end) && + push8(mpdcch_dci_pdu_rel13->redudency_version, ppWritePackedMsg, end) && + push8(mpdcch_dci_pdu_rel13->tpc, ppWritePackedMsg, end) && + push8(mpdcch_dci_pdu_rel13->csi_request, ppWritePackedMsg, end) && + push8(mpdcch_dci_pdu_rel13->ul_inex, ppWritePackedMsg, end) && + push8(mpdcch_dci_pdu_rel13->dai_presence_flag, ppWritePackedMsg, end) && + push8(mpdcch_dci_pdu_rel13->dl_assignment_index, ppWritePackedMsg, end) && + push8(mpdcch_dci_pdu_rel13->srs_request, ppWritePackedMsg, end) && + push8(mpdcch_dci_pdu_rel13->dci_subframe_repetition_number, ppWritePackedMsg, end) && + push32(mpdcch_dci_pdu_rel13->tcp_bitmap, ppWritePackedMsg, end) && + push8(mpdcch_dci_pdu_rel13->total_dci_length_include_padding, ppWritePackedMsg, end) && + push8(mpdcch_dci_pdu_rel13->number_of_tx_antenna_ports, ppWritePackedMsg, end) && + pusharray16(mpdcch_dci_pdu_rel13->precoding_value, NFAPI_MAX_TX_PHYSICAL_ANTENNA_PORTS, mpdcch_dci_pdu_rel13->number_of_tx_antenna_ports, ppWritePackedMsg, end)); + +} + +static uint8_t pack_hi_dci0_npdcch_dci_rel13_pdu_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_hi_dci0_npdcch_dci_pdu_rel13_t* npdcch_dci_pdu_rel13 = (nfapi_hi_dci0_npdcch_dci_pdu_rel13_t*)tlv; + + return ( push8(npdcch_dci_pdu_rel13->ncce_index, ppWritePackedMsg, end) && + push8(npdcch_dci_pdu_rel13->aggregation_level, ppWritePackedMsg, end) && + push8(npdcch_dci_pdu_rel13->start_symbol, ppWritePackedMsg, end) && + push16(npdcch_dci_pdu_rel13->rnti, ppWritePackedMsg, end) && + push8(npdcch_dci_pdu_rel13->scrambling_reinitialization_batch_index, ppWritePackedMsg, end) && + push8(npdcch_dci_pdu_rel13->nrs_antenna_ports_assumed_by_the_ue, ppWritePackedMsg, end) && + push8(npdcch_dci_pdu_rel13->subcarrier_indication, ppWritePackedMsg, end) && + push8(npdcch_dci_pdu_rel13->resource_assignment, ppWritePackedMsg, end) && + push8(npdcch_dci_pdu_rel13->scheduling_delay, ppWritePackedMsg, end) && + push8(npdcch_dci_pdu_rel13->mcs, ppWritePackedMsg, end) && + push8(npdcch_dci_pdu_rel13->redudancy_version, ppWritePackedMsg, end) && + push8(npdcch_dci_pdu_rel13->repetition_number, ppWritePackedMsg, end) && + push8(npdcch_dci_pdu_rel13->new_data_indicator, ppWritePackedMsg, end) && + push8(npdcch_dci_pdu_rel13->dci_subframe_repetition_number, ppWritePackedMsg, end)); +} + + +static uint8_t pack_hi_dci0_request_body_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_hi_dci0_request_body_t* value = (nfapi_hi_dci0_request_body_t*)tlv; + + if(!(push16(value->sfnsf, ppWritePackedMsg, end) && + push8(value->number_of_dci, ppWritePackedMsg, end) && + push8(value->number_of_hi, ppWritePackedMsg, end))) + return 0; + + uint16_t i = 0; + uint16_t total_number_of_pdus = value->number_of_dci + value->number_of_hi; + for(i = 0; i < total_number_of_pdus; ++i) + { + nfapi_hi_dci0_request_pdu_t* pdu = &(value->hi_dci0_pdu_list[i]); + + if(push8(pdu->pdu_type, ppWritePackedMsg, end) == 0) + return 0; + + // Put a 0 size in and then determine the size after the pdu + // has been writen and write the calculated size + uint8_t* pWritePackedMsgPduSize = *ppWritePackedMsg; + pdu->pdu_size = 0; + if(push8(pdu->pdu_size, ppWritePackedMsg, end) == 0) + return 0; + + switch(pdu->pdu_type) + { + case NFAPI_HI_DCI0_HI_PDU_TYPE: + { + if(!(pack_tlv(NFAPI_HI_DCI0_REQUEST_HI_PDU_REL8_TAG, &pdu->hi_pdu.hi_pdu_rel8, ppWritePackedMsg, end, pack_hi_dci0_hi_rel8_pdu_value) && + pack_tlv(NFAPI_HI_DCI0_REQUEST_HI_PDU_REL10_TAG, &pdu->hi_pdu.hi_pdu_rel10, ppWritePackedMsg, end, pack_hi_dci0_hi_rel10_pdu_value))) + return 0; + } + break; + case NFAPI_HI_DCI0_DCI_PDU_TYPE: + { + if(!(pack_tlv(NFAPI_HI_DCI0_REQUEST_DCI_PDU_REL8_TAG, &pdu->dci_pdu.dci_pdu_rel8, ppWritePackedMsg, end, pack_hi_dci0_dci_rel8_pdu_value) && + pack_tlv(NFAPI_HI_DCI0_REQUEST_DCI_PDU_REL10_TAG, &pdu->dci_pdu.dci_pdu_rel10, ppWritePackedMsg, end, pack_hi_dci0_dci_rel10_pdu_value) && + pack_tlv(NFAPI_HI_DCI0_REQUEST_DCI_PDU_REL12_TAG, &pdu->dci_pdu.dci_pdu_rel12, ppWritePackedMsg, end, pack_hi_dci0_dci_rel12_pdu_value))) + return 0; + } + break; + case NFAPI_HI_DCI0_EPDCCH_DCI_PDU_TYPE: + { + if(!(pack_tlv(NFAPI_HI_DCI0_REQUEST_EPDCCH_DCI_PDU_REL8_TAG, &pdu->epdcch_dci_pdu.epdcch_dci_pdu_rel8, ppWritePackedMsg, end, pack_hi_dci0_dci_rel8_pdu_value) && + pack_tlv(NFAPI_HI_DCI0_REQUEST_EPDCCH_DCI_PDU_REL10_TAG, &pdu->epdcch_dci_pdu.epdcch_dci_pdu_rel10, ppWritePackedMsg, end, pack_hi_dci0_dci_rel10_pdu_value) && + pack_tlv(NFAPI_HI_DCI0_REQUEST_EPDCCH_PARAMETERS_REL11_TAG, &pdu->epdcch_dci_pdu.epdcch_parameters_rel11, ppWritePackedMsg, end, pack_dl_config_epdcch_parameters_rel11_value))) + return 0; + } + break; + case NFAPI_HI_DCI0_MPDCCH_DCI_PDU_TYPE: + { + if(!(pack_tlv(NFAPI_HI_DCI0_REQUEST_MPDCCH_DCI_PDU_REL13_TAG, &pdu->mpdcch_dci_pdu.mpdcch_dci_pdu_rel13, ppWritePackedMsg, end, pack_hi_dci0_mpdcch_dci_rel13_pdu_value))) + return 0; + } + break; + case NFAPI_HI_DCI0_NPDCCH_DCI_PDU_TYPE: + { + if(!(pack_tlv(NFAPI_HI_DCI0_REQUEST_NPDCCH_DCI_PDU_REL13_TAG, &pdu->npdcch_dci_pdu.npdcch_dci_pdu_rel13, ppWritePackedMsg, end, pack_hi_dci0_npdcch_dci_rel13_pdu_value))) + return 0; + } + break; + default: + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "FIXME : Invalid pdu type %d \n", pdu->pdu_type ); + } + break; + }; + + // add 1 for the pdu_type. The delta will include the pdu_size + pdu->pdu_size = 1 + (*ppWritePackedMsg - pWritePackedMsgPduSize); + push8(pdu->pdu_size, &pWritePackedMsgPduSize, end); + + } + + return 1; +} + +static uint8_t pack_ul_dci_pdu_list_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_nr_ul_dci_request_pdus_t* value = (nfapi_nr_ul_dci_request_pdus_t*)tlv; + + for(uint8_t i = 0; i < MAX_DCI_CORESET; ++i) + { + if(!(push16(value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].RNTI, ppWritePackedMsg, end) && + push16(value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].ScramblingId, ppWritePackedMsg, end) && + + push16(value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].ScramblingRNTI, ppWritePackedMsg, end) && + push8(value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].CceIndex, ppWritePackedMsg, end) && + push8(value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].AggregationLevel, ppWritePackedMsg, end) && + push8(value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].beta_PDCCH_1_0, ppWritePackedMsg, end) && + + push8(value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].powerControlOffsetSS, ppWritePackedMsg, end) && + push16(value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].PayloadSizeBits, ppWritePackedMsg, end) && + + pusharray8(value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].Payload, value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].PayloadSizeBits, value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].PayloadSizeBits, ppWritePackedMsg, end))) + + return 0; + } + + return (push16(value->PDUType, ppWritePackedMsg, end) && + push16(value->PDUSize, ppWritePackedMsg, end) && + push16(value->pdcch_pdu.pdcch_pdu_rel15.BWPSize, ppWritePackedMsg, end) && + push16(value->pdcch_pdu.pdcch_pdu_rel15.BWPStart, ppWritePackedMsg, end) && + push8(value->pdcch_pdu.pdcch_pdu_rel15.SubcarrierSpacing, ppWritePackedMsg, end) && + push8(value->pdcch_pdu.pdcch_pdu_rel15.CyclicPrefix, ppWritePackedMsg, end) && + + push8(value->pdcch_pdu.pdcch_pdu_rel15.StartSymbolIndex, ppWritePackedMsg, end) && + push8(value->pdcch_pdu.pdcch_pdu_rel15.DurationSymbols, ppWritePackedMsg, end) && + pusharray8(value->pdcch_pdu.pdcch_pdu_rel15.FreqDomainResource, 6, 6, ppWritePackedMsg, end) && + push8(value->pdcch_pdu.pdcch_pdu_rel15.CceRegMappingType, ppWritePackedMsg, end) && + + push8(value->pdcch_pdu.pdcch_pdu_rel15.RegBundleSize, ppWritePackedMsg, end) && + push8(value->pdcch_pdu.pdcch_pdu_rel15.InterleaverSize, ppWritePackedMsg, end) && + push8(value->pdcch_pdu.pdcch_pdu_rel15.CoreSetType, ppWritePackedMsg, end) && + push16(value->pdcch_pdu.pdcch_pdu_rel15.ShiftIndex, ppWritePackedMsg, end) && + push8(value->pdcch_pdu.pdcch_pdu_rel15.precoderGranularity, ppWritePackedMsg, end) && + push16(value->pdcch_pdu.pdcch_pdu_rel15.numDlDci, ppWritePackedMsg, end)); + +} + +static uint8_t pack_ul_dci_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) +{ + nfapi_nr_ul_dci_request_t *pNfapiMsg = (nfapi_nr_ul_dci_request_t*)msg; + + if (!(push16(pNfapiMsg->SFN, ppWritePackedMsg, end) && + push16(pNfapiMsg->Slot, ppWritePackedMsg, end) && + push8(pNfapiMsg->numPdus, ppWritePackedMsg, end) + )) + return 0; + + for(int i=0; inumPdus; i++) + { + if(!pack_ul_dci_pdu_list_value(&pNfapiMsg->ul_dci_pdu_list[i], ppWritePackedMsg, end)) + return 0; + } + return 1; + + +} + + + +static uint8_t pack_hi_dci0_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) +{ + nfapi_hi_dci0_request_t *pNfapiMsg = (nfapi_hi_dci0_request_t*)msg; + + return ( push16(pNfapiMsg->sfn_sf, ppWritePackedMsg, end) && + pack_tlv(NFAPI_HI_DCI0_REQUEST_BODY_TAG, &pNfapiMsg->hi_dci0_request_body, ppWritePackedMsg, end, &pack_hi_dci0_request_body_value) && + pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); +} + +//pack_tx_data_pdu_list_value +static uint8_t pack_tx_data_pdu_list_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_nr_pdu_t* value = (nfapi_nr_pdu_t*)tlv; + + if(!(push32(value->num_TLV, ppWritePackedMsg, end) && + push16(value->PDU_index, ppWritePackedMsg, end) && + push16(value->PDU_length, ppWritePackedMsg, end) + )) + return 0; + + uint16_t i = 0; + uint16_t total_number_of_tlvs = value->num_TLV; + for(; i < total_number_of_tlvs; ++i) + { + + if (!(push16(value->TLVs[i].length, ppWritePackedMsg, end) && + push16(value->TLVs[i].tag, ppWritePackedMsg, end))) + return 0; + + switch(value->TLVs[i].tag) + { + case 0: + { + if(!pusharray32(value->TLVs[i].value.direct, 16384, value->TLVs[i].length, ppWritePackedMsg, end)) + return 0; + break; + + } + + case 1: + { + if(!pusharray32(value->TLVs[i].value.ptr, value->TLVs[i].length , value->TLVs[i].length, ppWritePackedMsg, end)) + return 0; + break; + + } + + default: + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "FIXME : Invalid tag value %d \n", value->TLVs[i].tag ); + break; + } + + } + } + return 1; +} + +static uint8_t pack_tx_request_body_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_tx_request_body_t* value = (nfapi_tx_request_body_t*)tlv; + + if(push16(value->number_of_pdus, ppWritePackedMsg, end) == 0) + return 0; + + uint16_t i = 0; + uint16_t total_number_of_pdus = value->number_of_pdus; + for(; i < total_number_of_pdus; ++i) + { + nfapi_tx_request_pdu_t* pdu = &(value->tx_pdu_list[i]); + + if(!(push16(pdu->pdu_length, ppWritePackedMsg, end) && + push16(pdu->pdu_index, ppWritePackedMsg, end))) + return 0; + + uint8_t j; + for(j = 0; j < pdu->num_segments; ++j) + { + // Use -1 as it is unbounded + // DJP - does not handle -1 + // DJP - if(pusharray8(pdu->segments[j].segment_data, (uint32_t)(-1), pdu->segments[j].segment_length, ppWritePackedMsg, end) == 0) + int push_ret = pusharray8(pdu->segments[j].segment_data, 65535, pdu->segments[j].segment_length, ppWritePackedMsg, end); + + if (pdu->segments[j].segment_length == 3) + { + NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() BCH? segment_data:%x %x %x\n", __FUNCTION__, + pdu->segments[j].segment_data[0], + pdu->segments[j].segment_data[1], + pdu->segments[j].segment_data[2] + ); + } + //NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() segment_data:%p segment_length:%u pusharray8()=%d\n", __FUNCTION__, pdu->segments[j].segment_data, pdu->segments[j].segment_length, push_ret); + + if (push_ret == 0) + { + return 0; + } + } + } + + return 1; +} + +static uint8_t pack_tx_data_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) +{ + nfapi_nr_tx_data_request_t *pNfapiMsg = (nfapi_nr_tx_data_request_t*)msg; + + if (!( + push16(pNfapiMsg->SFN, ppWritePackedMsg, end) && + push16(pNfapiMsg->Slot, ppWritePackedMsg, end) && + push16(pNfapiMsg->Number_of_PDUs, ppWritePackedMsg, end) + )) + return 0; + + for(int i=0; iNumber_of_PDUs; i++) + { + if(!pack_tx_data_pdu_list_value(&pNfapiMsg->pdu_list[i], ppWritePackedMsg, end)) + return 0; + } + + return 1; +} + +static uint8_t pack_tx_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) +{ + nfapi_tx_request_t *pNfapiMsg = (nfapi_tx_request_t*)msg; + + int x = push16(pNfapiMsg->sfn_sf, ppWritePackedMsg, end); + int y = pack_tlv(NFAPI_TX_REQUEST_BODY_TAG, &pNfapiMsg->tx_request_body, ppWritePackedMsg, end, &pack_tx_request_body_value); + int z = pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config); + + //NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() x:%d y:%d z:%d\n", __FUNCTION__, x, y, z); + + return x && y && z; +} + +static uint8_t pack_release_request_body_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_ue_release_request_body_t* value = (nfapi_ue_release_request_body_t*)tlv; + if(push16(value->number_of_TLVs, ppWritePackedMsg, end) == 0){ + return 0; + } + + uint8_t j; + uint16_t num = value->number_of_TLVs; + for(j = 0; j < num; ++j){ + if(push16(value->ue_release_request_TLVs_list[j].rnti, ppWritePackedMsg, end) == 0){ + return 0; + } + } + return 1; +} + +static uint8_t pack_ue_release_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) +{ + nfapi_ue_release_request_t *pNfapiMsg = (nfapi_ue_release_request_t*)msg; + int x = push16(pNfapiMsg->sfn_sf, ppWritePackedMsg, end); + int y = pack_tlv(NFAPI_UE_RELEASE_BODY_TAG, &pNfapiMsg->ue_release_request_body, ppWritePackedMsg, end, &pack_release_request_body_value); + int z = pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config); + return x && y && z; +} + +static uint8_t pack_ue_release_response(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) +{ + + nfapi_ue_release_response_t *pNfapiMsg = (nfapi_ue_release_response_t*)msg; + + int x = push32(pNfapiMsg->error_code, ppWritePackedMsg, end); + int z = pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config); + return x && z; +} + +static uint8_t pack_rx_ue_information_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_rx_ue_information* value = (nfapi_rx_ue_information*)tlv; + + return ( push32(value->handle, ppWritePackedMsg, end) && + push16(value->rnti, ppWritePackedMsg, end) ); +} + +static uint8_t unpack_rx_ue_information_value(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_rx_ue_information* value = (nfapi_rx_ue_information*)tlv; + + return ( pull32(ppReadPackedMsg, &value->handle, end) && + pull16(ppReadPackedMsg, &value->rnti, end)); +} + +static uint8_t pack_harq_indication_tdd_harq_data_bundling(nfapi_harq_indication_tdd_harq_data_bundling_t* data, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + return ( push8(data->value_0, ppWritePackedMsg, end) && + push8(data->value_1, ppWritePackedMsg, end)); +} + +static uint8_t pack_harq_indication_tdd_harq_data_multiplexing(nfapi_harq_indication_tdd_harq_data_multiplexing_t* data, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + return ( push8(data->value_0, ppWritePackedMsg, end) && + push8(data->value_1, ppWritePackedMsg, end) && + push8(data->value_2, ppWritePackedMsg, end) && + push8(data->value_3, ppWritePackedMsg, end)); +} + +static uint8_t pack_harq_indication_tdd_harq_data_special_bundling(nfapi_harq_indication_tdd_harq_data_special_bundling_t* data, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + return ( push8(data->value_0, ppWritePackedMsg, end) ); +} + +static uint8_t pack_harq_indication_tdd_harq_data(nfapi_harq_indication_tdd_harq_data_t* data, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + return ( push8(data->value_0, ppWritePackedMsg, end) ); +} + +static uint8_t pack_harq_indication_tdd_rel8_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_harq_indication_tdd_rel8_t* harq_indication_tdd_rel8 = (nfapi_harq_indication_tdd_rel8_t*)tlv; + + if(!(push8(harq_indication_tdd_rel8->mode, ppWritePackedMsg, end) && + push8(harq_indication_tdd_rel8->number_of_ack_nack, ppWritePackedMsg, end))) + return 0; + + uint8_t result = 0; + switch(harq_indication_tdd_rel8->mode) + { + case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_BUNDLING: + result = pack_harq_indication_tdd_harq_data_bundling(&harq_indication_tdd_rel8->harq_data.bundling, ppWritePackedMsg, end); + break; + case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_MULIPLEXING: + result = pack_harq_indication_tdd_harq_data_multiplexing(&harq_indication_tdd_rel8->harq_data.multiplex, ppWritePackedMsg, end); + break; + case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_SPECIAL_BUNDLING: + result = pack_harq_indication_tdd_harq_data_special_bundling(&harq_indication_tdd_rel8->harq_data.special_bundling, ppWritePackedMsg, end); + break; + case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_CHANNEL_SELECTION: + case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_FORMAT_3: + result = 1; + break; + default: + // err.... + break; + } + + return result; + +} + +static uint8_t pack_harq_indication_tdd_rel9_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_harq_indication_tdd_rel9_t* harq_indication_tdd_rel9 = (nfapi_harq_indication_tdd_rel9_t*)tlv; + + if(!(push8(harq_indication_tdd_rel9->mode, ppWritePackedMsg, end) && + push8(harq_indication_tdd_rel9->number_of_ack_nack, ppWritePackedMsg, end))) + return 0; + + uint8_t idx; + for(idx = 0; idx < harq_indication_tdd_rel9->number_of_ack_nack; ++idx) + { + uint8_t result = 0; + + switch(harq_indication_tdd_rel9->mode) + { + case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_BUNDLING: + result = pack_harq_indication_tdd_harq_data(&(harq_indication_tdd_rel9->harq_data[idx].bundling), ppWritePackedMsg, end); + break; + case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_MULIPLEXING: + result = pack_harq_indication_tdd_harq_data(&harq_indication_tdd_rel9->harq_data[idx].multiplex, ppWritePackedMsg, end); + break; + case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_SPECIAL_BUNDLING: + result = pack_harq_indication_tdd_harq_data_special_bundling(&harq_indication_tdd_rel9->harq_data[idx].special_bundling, ppWritePackedMsg, end); + break; + case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_CHANNEL_SELECTION: + result = pack_harq_indication_tdd_harq_data(&harq_indication_tdd_rel9->harq_data[idx].channel_selection, ppWritePackedMsg, end); + break; + case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_FORMAT_3: + result = pack_harq_indication_tdd_harq_data(&harq_indication_tdd_rel9->harq_data[idx].format_3, ppWritePackedMsg, end); + break; + default: + // err.... + break; + } + + if(result == 0) + return 0; + } + + return 1; +} + +static uint8_t pack_harq_indication_tdd_rel13_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_harq_indication_tdd_rel13_t* harq_indication_tdd_rel13 = (nfapi_harq_indication_tdd_rel13_t*)tlv; + + if(!(push8(harq_indication_tdd_rel13->mode, ppWritePackedMsg, end) && + push16(harq_indication_tdd_rel13->number_of_ack_nack, ppWritePackedMsg, end))) + return 0; + + uint8_t idx; + for(idx = 0; idx < harq_indication_tdd_rel13->number_of_ack_nack; ++idx) + { + uint8_t result = 0; + switch(harq_indication_tdd_rel13->mode) + { + case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_BUNDLING: + result = pack_harq_indication_tdd_harq_data(&harq_indication_tdd_rel13->harq_data[idx].bundling, ppWritePackedMsg, end); + break; + case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_MULIPLEXING: + result = pack_harq_indication_tdd_harq_data(&harq_indication_tdd_rel13->harq_data[idx].multiplex, ppWritePackedMsg, end); + break; + case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_SPECIAL_BUNDLING: + result = pack_harq_indication_tdd_harq_data_special_bundling(&harq_indication_tdd_rel13->harq_data[idx].special_bundling, ppWritePackedMsg, end); + break; + case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_CHANNEL_SELECTION: + result = pack_harq_indication_tdd_harq_data(&harq_indication_tdd_rel13->harq_data[idx].channel_selection, ppWritePackedMsg, end); + break; + case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_FORMAT_3: + result = pack_harq_indication_tdd_harq_data(&harq_indication_tdd_rel13->harq_data[idx].format_3, ppWritePackedMsg, end); + break; + case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_FORMAT_4: + result = pack_harq_indication_tdd_harq_data(&harq_indication_tdd_rel13->harq_data[idx].format_4, ppWritePackedMsg, end); + break; + case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_FORMAT_5: + result = pack_harq_indication_tdd_harq_data(&harq_indication_tdd_rel13->harq_data[idx].format_5, ppWritePackedMsg, end); + break; + default: + // err.... + break; + } + + if(result == 0) + return 0; + } + + return 1; +} + +static uint8_t pack_harq_indication_fdd_rel8_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_harq_indication_fdd_rel8_t* harq_indication_fdd_rel8 = (nfapi_harq_indication_fdd_rel8_t*)tlv; + + return ( push8(harq_indication_fdd_rel8->harq_tb1, ppWritePackedMsg, end) && + push8(harq_indication_fdd_rel8->harq_tb2, ppWritePackedMsg, end)); +} + +static uint8_t pack_harq_indication_fdd_rel9_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_harq_indication_fdd_rel9_t* harq_indication_fdd_rel9 = (nfapi_harq_indication_fdd_rel9_t*)tlv; + + return ( push8(harq_indication_fdd_rel9->mode, ppWritePackedMsg, end) && + push8(harq_indication_fdd_rel9->number_of_ack_nack, ppWritePackedMsg, end) && + pusharray8(harq_indication_fdd_rel9->harq_tb_n, NFAPI_HARQ_ACK_NACK_REL9_MAX, harq_indication_fdd_rel9->number_of_ack_nack, ppWritePackedMsg, end)); +} + +static uint8_t pack_harq_indication_fdd_rel13_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_harq_indication_fdd_rel13_t* harq_indication_fdd_rel13 = (nfapi_harq_indication_fdd_rel13_t*)tlv; + + return ( push8(harq_indication_fdd_rel13->mode, ppWritePackedMsg, end) && + push16(harq_indication_fdd_rel13->number_of_ack_nack, ppWritePackedMsg, end) && + pusharray8(harq_indication_fdd_rel13->harq_tb_n, NFAPI_HARQ_ACK_NACK_REL13_MAX, harq_indication_fdd_rel13->number_of_ack_nack, ppWritePackedMsg, end)); +} + +static uint8_t pack_ul_cqi_information_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_ul_cqi_information_t* value = (nfapi_ul_cqi_information_t*)tlv; + + return ( push8(value->ul_cqi, ppWritePackedMsg, end) && + push8(value->channel, ppWritePackedMsg, end)); + +} + +static uint8_t pack_harq_indication_body_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_harq_indication_body_t* value = (nfapi_harq_indication_body_t*)tlv; + + if(push16(value->number_of_harqs, ppWritePackedMsg, end) == 0) + return 0; + + uint16_t i = 0; + uint16_t total_number_of_pdus = value->number_of_harqs; + for(; i < total_number_of_pdus; ++i) + { + nfapi_harq_indication_pdu_t* pdu = &(value->harq_pdu_list[i]); + + uint8_t* instance_length_p = *ppWritePackedMsg; + if(!push16(pdu->instance_length, ppWritePackedMsg, end)) + return 0; + + if(!(pack_tlv(NFAPI_RX_UE_INFORMATION_TAG, &pdu->rx_ue_information, ppWritePackedMsg, end, pack_rx_ue_information_value) && + pack_tlv(NFAPI_HARQ_INDICATION_TDD_REL8_TAG, &pdu->harq_indication_tdd_rel8, ppWritePackedMsg, end, pack_harq_indication_tdd_rel8_value) && + pack_tlv(NFAPI_HARQ_INDICATION_TDD_REL9_TAG, &pdu->harq_indication_tdd_rel9, ppWritePackedMsg, end, pack_harq_indication_tdd_rel9_value) && + pack_tlv(NFAPI_HARQ_INDICATION_TDD_REL13_TAG, &pdu->harq_indication_tdd_rel13, ppWritePackedMsg, end, pack_harq_indication_tdd_rel13_value) && + pack_tlv(NFAPI_HARQ_INDICATION_FDD_REL8_TAG, &pdu->harq_indication_fdd_rel8, ppWritePackedMsg, end, pack_harq_indication_fdd_rel8_value) && + pack_tlv(NFAPI_HARQ_INDICATION_FDD_REL9_TAG, &pdu->harq_indication_fdd_rel9, ppWritePackedMsg, end, pack_harq_indication_fdd_rel9_value) && + pack_tlv(NFAPI_HARQ_INDICATION_FDD_REL13_TAG, &pdu->harq_indication_fdd_rel13, ppWritePackedMsg, end, pack_harq_indication_fdd_rel13_value) && + pack_tlv(NFAPI_UL_CQI_INFORMATION_TAG, &pdu->ul_cqi_information, ppWritePackedMsg, end, pack_ul_cqi_information_value))) + return 0; + + // calculate the instance length subtracting the size of the instance + // length feild + uint16_t instance_length = *ppWritePackedMsg - instance_length_p - 2; + push16(instance_length, &instance_length_p, end); + } + + return 1; +} + +static uint8_t pack_harq_indication(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) +{ + nfapi_harq_indication_t *pNfapiMsg = (nfapi_harq_indication_t*)msg; + + return ( push16(pNfapiMsg->sfn_sf, ppWritePackedMsg, end) && + pack_tlv(NFAPI_HARQ_INDICATION_BODY_TAG, &pNfapiMsg->harq_indication_body, ppWritePackedMsg, end, pack_harq_indication_body_value) && + pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); +} + +static uint8_t pack_crc_indication_rel8_body(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_crc_indication_rel8_t* crc_indication_rel8 = (nfapi_crc_indication_rel8_t*)tlv; + + return ( push8(crc_indication_rel8->crc_flag, ppWritePackedMsg, end) ); +} + +static uint8_t pack_crc_indication_body_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_crc_indication_body_t* value = (nfapi_crc_indication_body_t*)tlv; + + if(push16(value->number_of_crcs, ppWritePackedMsg, end) == 0) + return 0; + + uint16_t i = 0; + uint16_t total_number_of_pdus = value->number_of_crcs; + for(; i < total_number_of_pdus; ++i) + { + nfapi_crc_indication_pdu_t* pdu = &(value->crc_pdu_list[i]); + + uint8_t* instance_length_p = *ppWritePackedMsg; + if(!push16(pdu->instance_length, ppWritePackedMsg, end)) + return 0; + + if(!(pack_tlv(NFAPI_RX_UE_INFORMATION_TAG, &pdu->rx_ue_information, ppWritePackedMsg, end, pack_rx_ue_information_value) && + pack_tlv(NFAPI_CRC_INDICATION_REL8_TAG, &pdu->crc_indication_rel8, ppWritePackedMsg, end, pack_crc_indication_rel8_body))) + return 0; + + // calculate the instance length subtracting the size of the instance + // length feild + uint16_t instance_length = *ppWritePackedMsg - instance_length_p - 2; + push16(instance_length, &instance_length_p, end); + } + return 1; +} + +static uint8_t pack_crc_indication(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) +{ + nfapi_crc_indication_t *pNfapiMsg = (nfapi_crc_indication_t*)msg; + + return ( push16(pNfapiMsg->sfn_sf, ppWritePackedMsg, end) && + pack_tlv(NFAPI_CRC_INDICATION_BODY_TAG, &pNfapiMsg->crc_indication_body, ppWritePackedMsg, end, &pack_crc_indication_body_value) && + pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); + +} +static uint8_t pack_rx_indication_rel8_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_rx_indication_rel8_t* value = (nfapi_rx_indication_rel8_t*)tlv; + + return ( push16(value->length, ppWritePackedMsg, end) && + push16(value->offset, ppWritePackedMsg, end) && + push8(value->ul_cqi, ppWritePackedMsg, end) && + push16(value->timing_advance, ppWritePackedMsg, end)); +} +static uint8_t pack_rx_indication_rel9_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_rx_indication_rel9_t* value = (nfapi_rx_indication_rel9_t*)tlv; + + return ( push16(value->timing_advance_r9, ppWritePackedMsg, end)); +} + +static uint8_t pack_rx_ulsch_indication_body_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_rx_indication_body_t* value = (nfapi_rx_indication_body_t*)tlv; + + //printf("RX ULSCH BODY\n"); + + if( push16(value->number_of_pdus, ppWritePackedMsg, end) == 0) + return 0; + + // need to calculate the data offset's. + uint16_t i = 0; + uint16_t offset = 2; // taking into account the number_of_pdus + uint16_t total_number_of_pdus = value->number_of_pdus; + //printf("ULSCH:pdus:%d\n", total_number_of_pdus); + + for(i = 0; i < total_number_of_pdus; ++i) + { + nfapi_rx_indication_pdu_t* pdu = &(value->rx_pdu_list[i]); + if(pdu->rx_ue_information.tl.tag == NFAPI_RX_UE_INFORMATION_TAG) + { + //printf("NFAPI_RX_UE_INFORMATION_TAG\n"); + offset += 4 + 6; + } + + if(pdu->rx_indication_rel8.tl.tag == NFAPI_RX_INDICATION_REL8_TAG) + { + //printf("NFAPI_RX_INDICATION_REL8_TAG\n"); + offset += 4 + 7; + } + + if(pdu->rx_indication_rel9.tl.tag == NFAPI_RX_INDICATION_REL9_TAG) + { + //printf("NFAPI_RX_INDICATION_REL9_TAG\n"); + offset += 4 + 2; + } + } + + // Now update the structure to include the offset + for(i =0; i < total_number_of_pdus; ++i) + { + nfapi_rx_indication_pdu_t* pdu = &(value->rx_pdu_list[i]); + + if(pdu->rx_indication_rel8.tl.tag == NFAPI_RX_INDICATION_REL8_TAG) + { + if(pdu->rx_indication_rel8.offset == 1) + { + pdu->rx_indication_rel8.offset = offset; + offset += pdu->rx_indication_rel8.length; + } + } + } + + // Write out the pdu + for(i = 0; i < total_number_of_pdus; ++i) + { + nfapi_rx_indication_pdu_t* pdu = &(value->rx_pdu_list[i]); + if(!(pack_tlv(NFAPI_RX_UE_INFORMATION_TAG, &pdu->rx_ue_information, ppWritePackedMsg, end, pack_rx_ue_information_value) && + pack_tlv(NFAPI_RX_INDICATION_REL8_TAG, &pdu->rx_indication_rel8, ppWritePackedMsg, end, pack_rx_indication_rel8_value) && + pack_tlv(NFAPI_RX_INDICATION_REL9_TAG, &pdu->rx_indication_rel9, ppWritePackedMsg, end, pack_rx_indication_rel9_value))) + return 0; + } + + // Write out the pdu data + for(i = 0; i < total_number_of_pdus; ++i) + { + uint16_t length = 0; + nfapi_rx_indication_pdu_t* pdu = &(value->rx_pdu_list[i]); + + if(pdu->rx_indication_rel8.tl.tag == NFAPI_RX_INDICATION_REL8_TAG) + { + length = pdu->rx_indication_rel8.length; + } + + if( pusharray8(value->rx_pdu_list[i].data, length, length, ppWritePackedMsg, end) == 0) + return 0; + } + return 1; +} + + +static uint8_t pack_rx_ulsch_indication(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) +{ + nfapi_rx_indication_t *pNfapiMsg = (nfapi_rx_indication_t*)msg; + + return ( push16(pNfapiMsg->sfn_sf, ppWritePackedMsg, end) && + pack_tlv(NFAPI_RX_INDICATION_BODY_TAG, &pNfapiMsg->rx_indication_body, ppWritePackedMsg, end, pack_rx_ulsch_indication_body_value) && + pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); +} + +static uint8_t pack_preamble_pdu_rel8_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_preamble_pdu_rel8_t* preamble_rel8 = (nfapi_preamble_pdu_rel8_t*)tlv; + + return ( push16(preamble_rel8->rnti, ppWritePackedMsg, end) && + push8(preamble_rel8->preamble, ppWritePackedMsg, end) && + push16(preamble_rel8->timing_advance, ppWritePackedMsg, end)); +} +static uint8_t pack_preamble_pdu_rel9_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_preamble_pdu_rel9_t* preamble_rel9 = (nfapi_preamble_pdu_rel9_t*)tlv; + + return ( push16(preamble_rel9->timing_advance_r9, ppWritePackedMsg, end) ); +} +static uint8_t pack_preamble_pdu_rel13_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_preamble_pdu_rel13_t* preamble_rel13 = (nfapi_preamble_pdu_rel13_t*)tlv; + + return ( push8(preamble_rel13->rach_resource_type, ppWritePackedMsg, end) ); +} + +static uint8_t pack_rach_indication_body_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_rach_indication_body_t* value = (nfapi_rach_indication_body_t*)tlv; + + if( push16(value->number_of_preambles, ppWritePackedMsg, end) == 0) + return 0; + + uint16_t i = 0; + uint16_t total_number_of_pdus = value->number_of_preambles; + for(; i < total_number_of_pdus; ++i) + { + nfapi_preamble_pdu_t* pdu = &(value->preamble_list[i]); + + uint8_t* instance_length_p = *ppWritePackedMsg; + if(!push16(pdu->instance_length, ppWritePackedMsg, end)) + return 0; + + if(!(pack_tlv(NFAPI_PREAMBLE_REL8_TAG, &pdu->preamble_rel8, ppWritePackedMsg, end, pack_preamble_pdu_rel8_value) && + pack_tlv(NFAPI_PREAMBLE_REL9_TAG, &pdu->preamble_rel9, ppWritePackedMsg, end, pack_preamble_pdu_rel9_value) && + pack_tlv(NFAPI_PREAMBLE_REL13_TAG, &pdu->preamble_rel13, ppWritePackedMsg, end, pack_preamble_pdu_rel13_value))) + return 0; + + // calculate the instance length subtracting the size of the instance + // length feild + uint16_t instance_length = *ppWritePackedMsg - instance_length_p - 2; + push16(instance_length, &instance_length_p, end); + } + + return 1; +} + +static uint8_t pack_rach_indication(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) +{ + nfapi_rach_indication_t *pNfapiMsg = (nfapi_rach_indication_t*)msg; + + return ( push16(pNfapiMsg->sfn_sf, ppWritePackedMsg, end) && + pack_tlv(NFAPI_RACH_INDICATION_BODY_TAG, &pNfapiMsg->rach_indication_body, ppWritePackedMsg, end, pack_rach_indication_body_value) && + pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); +} + +static uint8_t pack_srs_indication_fdd_rel8_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_srs_indication_fdd_rel8_t* srs_pdu_rel8 = (nfapi_srs_indication_fdd_rel8_t*)tlv; + + return ( push16(srs_pdu_rel8->doppler_estimation, ppWritePackedMsg, end) && + push16(srs_pdu_rel8->timing_advance, ppWritePackedMsg, end) && + push8(srs_pdu_rel8->number_of_resource_blocks, ppWritePackedMsg, end) && + push8(srs_pdu_rel8->rb_start, ppWritePackedMsg, end) && + pusharray8(srs_pdu_rel8->snr, NFAPI_NUM_RB_MAX, srs_pdu_rel8->number_of_resource_blocks, ppWritePackedMsg, end)); +} + +static uint8_t pack_srs_indication_fdd_rel9_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_srs_indication_fdd_rel9_t* srs_pdu_rel9 = (nfapi_srs_indication_fdd_rel9_t*)tlv; + + return ( push16(srs_pdu_rel9->timing_advance_r9, ppWritePackedMsg, end) ); +} + +static uint8_t pack_srs_indication_tdd_rel10_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_srs_indication_ttd_rel10_t* srs_pdu_rel10 = (nfapi_srs_indication_ttd_rel10_t*)tlv; + + return ( push8(srs_pdu_rel10->uppts_symbol, ppWritePackedMsg, end) ); + +} + +static uint8_t pack_srs_indication_fdd_rel11_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_srs_indication_fdd_rel11_t* srs_pdu_rel11 = (nfapi_srs_indication_fdd_rel11_t*)tlv; + + return ( push16(srs_pdu_rel11->ul_rtoa, ppWritePackedMsg, end) ) ; +} + +static uint8_t pack_tdd_channel_measurement_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_tdd_channel_measurement_t* value = (nfapi_tdd_channel_measurement_t*)tlv; + + if(!(push8(value->num_prb_per_subband, ppWritePackedMsg, end) && + push8(value->number_of_subbands, ppWritePackedMsg, end) && + push8(value->num_atennas, ppWritePackedMsg, end))) + return 0; + + uint8_t idx = 0; + for(idx = 0; idx < value->number_of_subbands; ++idx) + { + if(!(push8(value->subands[idx].subband_index, ppWritePackedMsg, end) && + pusharray16(value->subands[idx].channel, NFAPI_MAX_NUM_PHYSICAL_ANTENNAS, value->num_atennas, ppWritePackedMsg, end))) + return 0; + } + + return 1; +} + +static uint8_t pack_srs_indication_body_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_srs_indication_body_t *value = (nfapi_srs_indication_body_t*)tlv; + + if( push8(value->number_of_ues, ppWritePackedMsg, end) == 0) + return 0; + + uint16_t i = 0; + uint16_t total_number_of_pdus = value->number_of_ues; + for(; i < total_number_of_pdus; ++i) + { + nfapi_srs_indication_pdu_t* pdu = &(value->srs_pdu_list[i]); + + uint8_t* instance_length_p = *ppWritePackedMsg; + if(!push16(pdu->instance_length, ppWritePackedMsg, end)) + return 0; + + if(!(pack_tlv(NFAPI_RX_UE_INFORMATION_TAG, &pdu->rx_ue_information, ppWritePackedMsg, end, &pack_rx_ue_information_value) && + pack_tlv(NFAPI_SRS_INDICATION_FDD_REL8_TAG, &pdu->srs_indication_fdd_rel8, ppWritePackedMsg, end, &pack_srs_indication_fdd_rel8_value) && + pack_tlv(NFAPI_SRS_INDICATION_FDD_REL9_TAG, &pdu->srs_indication_fdd_rel9, ppWritePackedMsg, end, &pack_srs_indication_fdd_rel9_value) && + pack_tlv(NFAPI_SRS_INDICATION_TDD_REL10_TAG, &pdu->srs_indication_tdd_rel10, ppWritePackedMsg, end, &pack_srs_indication_tdd_rel10_value) && + pack_tlv(NFAPI_SRS_INDICATION_FDD_REL11_TAG, &pdu->srs_indication_fdd_rel11, ppWritePackedMsg, end, &pack_srs_indication_fdd_rel11_value) && + pack_tlv(NFAPI_TDD_CHANNEL_MEASUREMENT_TAG, &pdu->tdd_channel_measurement, ppWritePackedMsg, end, &pack_tdd_channel_measurement_value))) + return 0; + + // calculate the instance length subtracting the size of the instance + // length feild + uint16_t instance_length = *ppWritePackedMsg - instance_length_p - 2; + push16(instance_length, &instance_length_p, end); + } + + return 1; +} + +static uint8_t pack_srs_indication(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) +{ + nfapi_srs_indication_t *pNfapiMsg = (nfapi_srs_indication_t*)msg; + + return ( push16(pNfapiMsg->sfn_sf, ppWritePackedMsg, end) && + pack_tlv(NFAPI_SRS_INDICATION_BODY_TAG, &pNfapiMsg->srs_indication_body, ppWritePackedMsg, end, &pack_srs_indication_body_value) && + pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); + +} + +static uint8_t pack_sr_indication_body_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_sr_indication_body_t* value = (nfapi_sr_indication_body_t*)tlv; + + if(push16(value->number_of_srs, ppWritePackedMsg, end) == 0) + return 0; + + uint16_t i = 0; + uint16_t total_number_of_pdus = value->number_of_srs; + for(; i < total_number_of_pdus; ++i) + { + nfapi_sr_indication_pdu_t* pdu = &(value->sr_pdu_list[i]); + + uint8_t* instance_length_p = *ppWritePackedMsg; + if(!push16(pdu->instance_length, ppWritePackedMsg, end)) + return 0; + + if(!(pack_tlv(NFAPI_RX_UE_INFORMATION_TAG, &pdu->rx_ue_information, ppWritePackedMsg, end, pack_rx_ue_information_value) && + pack_tlv(NFAPI_UL_CQI_INFORMATION_TAG, &pdu->ul_cqi_information, ppWritePackedMsg, end, pack_ul_cqi_information_value))) + return 0; + + // calculate the instance length subtracting the size of the instance + // length feild + uint16_t instance_length = *ppWritePackedMsg - instance_length_p - 2; + push16(instance_length, &instance_length_p, end); + } + return 1; +} + +static uint8_t pack_sr_indication(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) +{ + nfapi_sr_indication_t *pNfapiMsg = (nfapi_sr_indication_t*)msg; + + return ( push16(pNfapiMsg->sfn_sf, ppWritePackedMsg, end) && + pack_tlv(NFAPI_SR_INDICATION_BODY_TAG, &pNfapiMsg->sr_indication_body, ppWritePackedMsg, end, &pack_sr_indication_body_value) && + pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); + +} + +static uint8_t pack_cqi_indication_rel8_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_cqi_indication_rel8_t* cqi_pdu_rel8 = (nfapi_cqi_indication_rel8_t*)tlv; + + return ( push16(cqi_pdu_rel8->length, ppWritePackedMsg, end) && + push16(cqi_pdu_rel8->data_offset, ppWritePackedMsg, end) && + push8(cqi_pdu_rel8->ul_cqi, ppWritePackedMsg, end) && + push8(cqi_pdu_rel8->ri, ppWritePackedMsg, end) && + push16(cqi_pdu_rel8->timing_advance, ppWritePackedMsg, end)); +} + +static uint8_t pack_cqi_indication_rel9_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_cqi_indication_rel9_t* cqi_pdu_rel9 = (nfapi_cqi_indication_rel9_t*)tlv; + + return ( push16(cqi_pdu_rel9->length, ppWritePackedMsg, end) && + push16(cqi_pdu_rel9->data_offset, ppWritePackedMsg, end) && + push8(cqi_pdu_rel9->ul_cqi, ppWritePackedMsg, end) && + push8(cqi_pdu_rel9->number_of_cc_reported, ppWritePackedMsg, end) && + pusharray8(cqi_pdu_rel9->ri, NFAPI_CC_MAX, cqi_pdu_rel9->number_of_cc_reported, ppWritePackedMsg, end) && + push16(cqi_pdu_rel9->timing_advance, ppWritePackedMsg, end) && + push16(cqi_pdu_rel9->timing_advance_r9, ppWritePackedMsg, end)); +} + +static uint8_t pack_cqi_indication_body_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_cqi_indication_body_t* value = (nfapi_cqi_indication_body_t*)tlv; + + if( push16(value->number_of_cqis, ppWritePackedMsg, end) == 0) + return 0; + + // need to calculate the data offset's. This very bittle due the hardcoding + // of the sizes. can not use the sizeof as we have an array for the Rel9 + // info + uint16_t i = 0; + uint16_t offset = 2; // taking into account the number_of_cqis + uint16_t total_number_of_pdus = value->number_of_cqis; + for(i = 0; i < total_number_of_pdus; ++i) + { + nfapi_cqi_indication_pdu_t* pdu = &(value->cqi_pdu_list[i]); + + offset += 2; // for the instance length + + if(pdu->rx_ue_information.tl.tag == NFAPI_RX_UE_INFORMATION_TAG) + { + offset += 4 + 6; // sizeof(nfapi_rx_ue_information) - sizeof(nfapi_tl_t) + } + + if(pdu->cqi_indication_rel8.tl.tag == NFAPI_CQI_INDICATION_REL8_TAG) + { + offset += 4 + 8; + } + + if(pdu->cqi_indication_rel9.tl.tag == NFAPI_CQI_INDICATION_REL9_TAG) + { + offset += 4 + 10 + pdu->cqi_indication_rel9.number_of_cc_reported; + } + + if(pdu->ul_cqi_information.tl.tag == NFAPI_UL_CQI_INFORMATION_TAG) + { + offset += 4 + 2; + } + } + + // Now update the structure to include the offset + for(i =0; i < total_number_of_pdus; ++i) + { + nfapi_cqi_indication_pdu_t* pdu = &(value->cqi_pdu_list[i]); + + if(pdu->cqi_indication_rel8.tl.tag == NFAPI_CQI_INDICATION_REL8_TAG) + { + if(pdu->cqi_indication_rel8.data_offset == 1) + { + pdu->cqi_indication_rel8.data_offset = offset; + offset += pdu->cqi_indication_rel8.length; + } + } + + if(pdu->cqi_indication_rel9.tl.tag == NFAPI_CQI_INDICATION_REL9_TAG) + { + if(pdu->cqi_indication_rel9.data_offset == 1) + { + pdu->cqi_indication_rel9.data_offset = offset; + offset += pdu->cqi_indication_rel9.length; + } + } + + } + + // Write out the cqi information + for(i = 0; i < total_number_of_pdus; ++i) + { + nfapi_cqi_indication_pdu_t* pdu = &(value->cqi_pdu_list[i]); + + uint8_t* instance_length_p = *ppWritePackedMsg; + if(!push16(pdu->instance_length, ppWritePackedMsg, end)) + return 0; + + if(!(pack_tlv(NFAPI_RX_UE_INFORMATION_TAG, &pdu->rx_ue_information, ppWritePackedMsg, end ,pack_rx_ue_information_value) && + pack_tlv(NFAPI_CQI_INDICATION_REL8_TAG, &pdu->cqi_indication_rel8, ppWritePackedMsg, end, pack_cqi_indication_rel8_value) && + pack_tlv(NFAPI_CQI_INDICATION_REL9_TAG, &pdu->cqi_indication_rel9, ppWritePackedMsg, end, pack_cqi_indication_rel9_value) && + pack_tlv(NFAPI_UL_CQI_INFORMATION_TAG, &pdu->ul_cqi_information, ppWritePackedMsg, end, pack_ul_cqi_information_value))) + return 0; + + // calculate the instance length subtracting the size of the instance + // length feild + uint16_t instance_length = *ppWritePackedMsg - instance_length_p - 2; + push16(instance_length, &instance_length_p, end); + + } + + // Write out the cqi raw data + for(i = 0; i < total_number_of_pdus; ++i) + { + uint16_t length = 0; + nfapi_cqi_indication_pdu_t* pdu = &(value->cqi_pdu_list[i]); + + if(pdu->cqi_indication_rel8.tl.tag == NFAPI_CQI_INDICATION_REL8_TAG) + { + length = pdu->cqi_indication_rel8.length; + } + + if(pdu->cqi_indication_rel9.tl.tag == NFAPI_CQI_INDICATION_REL9_TAG) + { + length = pdu->cqi_indication_rel9.length; + } + + if( pusharray8(value->cqi_raw_pdu_list[i].pdu, NFAPI_CQI_RAW_MAX_LEN, length, ppWritePackedMsg, end) == 0) + return 0; + } + + return 1; +} + +static uint8_t pack_cqi_indication(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) +{ + nfapi_cqi_indication_t *pNfapiMsg = (nfapi_cqi_indication_t*)msg; + + return ( push16(pNfapiMsg->sfn_sf, ppWritePackedMsg, end) && + pack_tlv(NFAPI_CQI_INDICATION_BODY_TAG, &pNfapiMsg->cqi_indication_body, ppWritePackedMsg, end, pack_cqi_indication_body_value) && + pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); + +} + +static uint8_t pack_lbt_pdsch_req_pdu_rel13_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_lbt_pdsch_req_pdu_rel13_t* value = (nfapi_lbt_pdsch_req_pdu_rel13_t*)tlv; + + return ( push32(value->handle, ppWritePackedMsg, end) && + push32(value->mp_cca, ppWritePackedMsg, end) && + push32(value->n_cca, ppWritePackedMsg, end) && + push32(value->offset, ppWritePackedMsg, end) && + push32(value->lte_txop_sf, ppWritePackedMsg, end) && + push16(value->txop_sfn_sf_end, ppWritePackedMsg, end) && + push32(value->lbt_mode, ppWritePackedMsg, end)); +} + +static uint8_t pack_lbt_drs_req_pdu_rel13_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_lbt_drs_req_pdu_rel13_t* value = (nfapi_lbt_drs_req_pdu_rel13_t*)tlv; + + return ( push32(value->handle, ppWritePackedMsg, end) && + push32(value->offset, ppWritePackedMsg, end) && + push16(value->sfn_sf_end, ppWritePackedMsg, end) && + push32(value->lbt_mode, ppWritePackedMsg, end)); +} + +static uint8_t pack_lbt_dl_config_request_body_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_lbt_dl_config_request_body_t* value = (nfapi_lbt_dl_config_request_body_t*)tlv; + + if( push16(value->number_of_pdus, ppWritePackedMsg, end) == 0) + return 0; + + uint16_t i = 0; + uint16_t total_number_of_pdus = value->number_of_pdus; + for(; i < total_number_of_pdus; ++i) + { + nfapi_lbt_dl_config_request_pdu_t* pdu = &(value->lbt_dl_config_req_pdu_list[i]); + + if( push8(pdu->pdu_type, ppWritePackedMsg, end) == 0) + return 0; + + // Put a 0 size in and then determine the size after the pdu + // has been writen and write the calculated size + uint8_t* pWritePackedMsgPduSize = *ppWritePackedMsg; + pdu->pdu_size = 0; + if( push8(pdu->pdu_size, ppWritePackedMsg, end) == 0) + return 0; + + switch(pdu->pdu_type) + { + case NFAPI_LBT_DL_CONFIG_REQUEST_PDSCH_PDU_TYPE: + { + if( pack_tlv(NFAPI_LBT_PDSCH_REQ_PDU_REL13_TAG, &pdu->lbt_pdsch_req_pdu.lbt_pdsch_req_pdu_rel13, ppWritePackedMsg, end, pack_lbt_pdsch_req_pdu_rel13_value) == 0) + return 0; + } + break; + case NFAPI_LBT_DL_CONFIG_REQUEST_DRS_PDU_TYPE: + { + if(pack_tlv(NFAPI_LBT_DRS_REQ_PDU_REL13_TAG, &pdu->lbt_drs_req_pdu.lbt_drs_req_pdu_rel13, ppWritePackedMsg, end, pack_lbt_drs_req_pdu_rel13_value) == 0) + return 0; + } + break; + default: + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "LBT_DL_CONFIG.request invalid pdu type %d \n", pdu->pdu_type ); + } + break; + }; + + // add 1 for the pdu_type. The delta will include the pdu_size + pdu->pdu_size = 1 + (*ppWritePackedMsg - pWritePackedMsgPduSize); + push8(pdu->pdu_size, &pWritePackedMsgPduSize, end); + } + + return 1; +} + +static uint8_t pack_lbt_pdsch_rsp_pdu_rel13_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_lbt_pdsch_rsp_pdu_rel13_t* value = (nfapi_lbt_pdsch_rsp_pdu_rel13_t*)tlv; + + return ( push32(value->handle, ppWritePackedMsg, end) && + push32(value->result, ppWritePackedMsg, end) && + push32(value->lte_txop_symbols, ppWritePackedMsg, end) && + push32(value->initial_partial_sf, ppWritePackedMsg, end)); +} + +static uint8_t pack_lbt_drs_rsp_pdu_rel13_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_lbt_drs_rsp_pdu_rel13_t* value = (nfapi_lbt_drs_rsp_pdu_rel13_t*)tlv; + + return ( push32(value->handle, ppWritePackedMsg, end) && + push32(value->result, ppWritePackedMsg, end)); +} + +static uint8_t pack_lbt_dl_config_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) +{ + nfapi_lbt_dl_config_request_t *pNfapiMsg = (nfapi_lbt_dl_config_request_t*)msg; + + return ( push16(pNfapiMsg->sfn_sf, ppWritePackedMsg, end) && + pack_tlv(NFAPI_LBT_DL_CONFIG_REQUEST_BODY_TAG, &pNfapiMsg->lbt_dl_config_request_body, ppWritePackedMsg, end, &pack_lbt_dl_config_request_body_value) && + pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); +} + +static uint8_t pack_lbt_dl_config_indication_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_lbt_dl_indication_body_t* value = (nfapi_lbt_dl_indication_body_t*)tlv; + + if( push16(value->number_of_pdus, ppWritePackedMsg, end) == 0) + return 0; + + uint16_t i = 0; + uint16_t total_number_of_pdus = value->number_of_pdus; + for(; i < total_number_of_pdus; ++i) + { + nfapi_lbt_dl_indication_pdu_t* pdu = &(value->lbt_indication_pdu_list[i]); + + if( push8(pdu->pdu_type, ppWritePackedMsg, end) == 0) + return 0; + + // Put a 0 size in and then determine the size after the pdu + // has been writen and write the calculated size + uint8_t* pWritePackedMsgPduSize = *ppWritePackedMsg; + pdu->pdu_size = 0; + + if(push8(pdu->pdu_size, ppWritePackedMsg, end) == 0) + return 0; + + switch(pdu->pdu_type) + { + case NFAPI_LBT_DL_RSP_PDSCH_PDU_TYPE: + { + if( pack_tlv(NFAPI_LBT_PDSCH_RSP_PDU_REL13_TAG, &pdu->lbt_pdsch_rsp_pdu.lbt_pdsch_rsp_pdu_rel13, ppWritePackedMsg, end, pack_lbt_pdsch_rsp_pdu_rel13_value) == 0) + return 0; + } + break; + case NFAPI_LBT_DL_RSP_DRS_PDU_TYPE: + { + if( pack_tlv(NFAPI_LBT_DRS_RSP_PDU_REL13_TAG, &pdu->lbt_drs_rsp_pdu.lbt_drs_rsp_pdu_rel13, ppWritePackedMsg, end, pack_lbt_drs_rsp_pdu_rel13_value) == 0) + return 0; + } + break; + default: + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "LBT_DL.indication body invalid pdu type %d \n", pdu->pdu_type ); + } + break; + }; + + // add 1 for the pdu_type. The delta will include the pdu_size + pdu->pdu_size = 1 + (*ppWritePackedMsg - pWritePackedMsgPduSize); + push8(pdu->pdu_size, &pWritePackedMsgPduSize, end); + } + + return 1; +} + +static uint8_t pack_lbt_dl_indication(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) +{ + nfapi_lbt_dl_indication_t *pNfapiMsg = (nfapi_lbt_dl_indication_t*)msg; + + return ( push16(pNfapiMsg->sfn_sf, ppWritePackedMsg, end) && + pack_tlv(NFAPI_LBT_DL_INDICATION_BODY_TAG, &pNfapiMsg->lbt_dl_indication_body, ppWritePackedMsg, end, &pack_lbt_dl_config_indication_value) && + pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); +} + +static uint8_t pack_nb_harq_indication_fdd_rel13_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_nb_harq_indication_fdd_rel13_t* nb_harq_indication_fdd_rel13 = (nfapi_nb_harq_indication_fdd_rel13_t*)tlv; + + return ( push8(nb_harq_indication_fdd_rel13->harq_tb1, ppWritePackedMsg, end) ); +} + +static uint8_t pack_nb_harq_indication_body_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_nb_harq_indication_body_t* value = (nfapi_nb_harq_indication_body_t*)tlv; + + if( push16(value->number_of_harqs, ppWritePackedMsg, end) == 0) + return 0; + + uint16_t i = 0; + uint16_t total_number_of_harqs = value->number_of_harqs; + for(; i < total_number_of_harqs; ++i) + { + nfapi_nb_harq_indication_pdu_t* pdu = &(value->nb_harq_pdu_list[i]); + + uint8_t* instance_length_p = *ppWritePackedMsg; + if(!push16(pdu->instance_length, ppWritePackedMsg, end)) + return 0; + + if(!(pack_tlv(NFAPI_RX_UE_INFORMATION_TAG, &pdu->rx_ue_information, ppWritePackedMsg, end, pack_rx_ue_information_value) && + pack_tlv(NFAPI_NB_HARQ_INDICATION_FDD_REL13_TAG, &pdu->nb_harq_indication_fdd_rel13, ppWritePackedMsg, end, pack_nb_harq_indication_fdd_rel13_value) && + pack_tlv(NFAPI_UL_CQI_INFORMATION_TAG, &pdu->ul_cqi_information, ppWritePackedMsg, end, pack_ul_cqi_information_value))) + return 0; + + // calculate the instance length subtracting the size of the instance + // length feild + uint16_t instance_length = *ppWritePackedMsg - instance_length_p - 2; + push16(instance_length, &instance_length_p, end); + } + + return 1; +} + + +static uint8_t pack_nb_harq_indication(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) +{ + nfapi_nb_harq_indication_t *pNfapiMsg = (nfapi_nb_harq_indication_t*)msg; + + return ( push16(pNfapiMsg->sfn_sf, ppWritePackedMsg, end) && + pack_tlv(NFAPI_NB_HARQ_INDICATION_BODY_TAG, &pNfapiMsg->nb_harq_indication_body, ppWritePackedMsg, end, &pack_nb_harq_indication_body_value) && + pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); +} + +static uint8_t pack_nrach_indication_rel13_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_nrach_indication_pdu_rel13_t* nrach_indication_fdd_rel13 = (nfapi_nrach_indication_pdu_rel13_t*)tlv; + + return ( push16(nrach_indication_fdd_rel13->rnti, ppWritePackedMsg, end) && + push8(nrach_indication_fdd_rel13->initial_sc, ppWritePackedMsg, end) && + push16(nrach_indication_fdd_rel13->timing_advance, ppWritePackedMsg, end) && + push8(nrach_indication_fdd_rel13->nrach_ce_level, ppWritePackedMsg, end)); +} + + +static uint8_t pack_nrach_indication_body_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_nrach_indication_body_t* value = (nfapi_nrach_indication_body_t*)tlv; + + if( push8(value->number_of_initial_scs_detected, ppWritePackedMsg, end) == 0) + return 0; + + uint16_t i = 0; + uint16_t total_number_of_initial_scs_detected = value->number_of_initial_scs_detected; + for(; i < total_number_of_initial_scs_detected; ++i) + { + nfapi_nrach_indication_pdu_t* pdu = &(value->nrach_pdu_list[i]); + + //uint8_t* instance_length_p = *ppWritePackedMsg; + //if(!push16(pdu->instance_length, ppWritePackedMsg, end)) + // return 0; + + if(!(pack_tlv(NFAPI_NRACH_INDICATION_REL13_TAG, &pdu->nrach_indication_rel13, ppWritePackedMsg, end, pack_nrach_indication_rel13_value))) + return 0; + + // calculate the instance length subtracting the size of the instance + // length feild + //uint16_t instance_length = *ppWritePackedMsg - instance_length_p - 2; + //push16(instance_length, &instance_length_p, end); + } + + return 1; +} + +static uint8_t pack_nrach_indication(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) +{ + nfapi_nrach_indication_t *pNfapiMsg = (nfapi_nrach_indication_t*)msg; + + return ( push16(pNfapiMsg->sfn_sf, ppWritePackedMsg, end) && + pack_tlv(NFAPI_NRACH_INDICATION_BODY_TAG, &pNfapiMsg->nrach_indication_body, ppWritePackedMsg, end, &pack_nrach_indication_body_value) && + pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); +} + +static uint8_t pack_nr_dl_node_sync(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) +{ + nfapi_nr_dl_node_sync_t *pNfapiMsg = (nfapi_nr_dl_node_sync_t*)msg; + + return ( push32(pNfapiMsg->t1, ppWritePackedMsg, end) && + pushs32(pNfapiMsg->delta_sfn_slot, ppWritePackedMsg, end) && + pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); +} + +static uint8_t pack_dl_node_sync(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) +{ + nfapi_dl_node_sync_t *pNfapiMsg = (nfapi_dl_node_sync_t*)msg; + + return ( push32(pNfapiMsg->t1, ppWritePackedMsg, end) && + pushs32(pNfapiMsg->delta_sfn_sf, ppWritePackedMsg, end) && + pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); +} + +static uint8_t pack_nr_ul_node_sync(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) +{ + nfapi_nr_ul_node_sync_t *pNfapiMsg = (nfapi_nr_ul_node_sync_t*)msg; + + return (push32(pNfapiMsg->t1, ppWritePackedMsg, end) && + push32(pNfapiMsg->t2, ppWritePackedMsg, end) && + push32(pNfapiMsg->t3, ppWritePackedMsg, end) && + pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); +} + +static uint8_t pack_ul_node_sync(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) +{ + nfapi_ul_node_sync_t *pNfapiMsg = (nfapi_ul_node_sync_t*)msg; + + return (push32(pNfapiMsg->t1, ppWritePackedMsg, end) && + push32(pNfapiMsg->t2, ppWritePackedMsg, end) && + push32(pNfapiMsg->t3, ppWritePackedMsg, end) && + pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); +} + +static uint8_t pack_timing_info(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) +{ + nfapi_timing_info_t *pNfapiMsg = (nfapi_timing_info_t*)msg; + + return (push32(pNfapiMsg->last_sfn_sf, ppWritePackedMsg, end) && + push32(pNfapiMsg->time_since_last_timing_info, ppWritePackedMsg, end) && + push32(pNfapiMsg->dl_config_jitter, ppWritePackedMsg, end) && + push32(pNfapiMsg->tx_request_jitter, ppWritePackedMsg, end) && + push32(pNfapiMsg->ul_config_jitter, ppWritePackedMsg, end) && + push32(pNfapiMsg->hi_dci0_jitter, ppWritePackedMsg, end) && + pushs32(pNfapiMsg->dl_config_latest_delay, ppWritePackedMsg, end) && + pushs32(pNfapiMsg->tx_request_latest_delay, ppWritePackedMsg, end) && + pushs32(pNfapiMsg->ul_config_latest_delay, ppWritePackedMsg, end) && + pushs32(pNfapiMsg->hi_dci0_latest_delay, ppWritePackedMsg, end) && + pushs32(pNfapiMsg->dl_config_earliest_arrival, ppWritePackedMsg, end) && + pushs32(pNfapiMsg->tx_request_earliest_arrival, ppWritePackedMsg, end) && + pushs32(pNfapiMsg->ul_config_earliest_arrival, ppWritePackedMsg, end) && + pushs32(pNfapiMsg->hi_dci0_earliest_arrival, ppWritePackedMsg, end) && + pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); +} + +static uint8_t pack_nr_timing_info(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) +{ + nfapi_nr_timing_info_t *pNfapiMsg = (nfapi_nr_timing_info_t*)msg; + + return (push32(pNfapiMsg->last_sfn, ppWritePackedMsg, end) && + push32(pNfapiMsg->last_slot, ppWritePackedMsg, end) && + push32(pNfapiMsg->time_since_last_timing_info, ppWritePackedMsg, end) && + push32(pNfapiMsg->dl_tti_jitter, ppWritePackedMsg, end) && + push32(pNfapiMsg->tx_data_request_jitter, ppWritePackedMsg, end) && + push32(pNfapiMsg->ul_tti_jitter, ppWritePackedMsg, end) && + push32(pNfapiMsg->ul_dci_jitter, ppWritePackedMsg, end) && + pushs32(pNfapiMsg->dl_tti_latest_delay, ppWritePackedMsg, end) && + pushs32(pNfapiMsg->tx_data_request_latest_delay, ppWritePackedMsg, end) && + pushs32(pNfapiMsg->ul_tti_latest_delay, ppWritePackedMsg, end) && + pushs32(pNfapiMsg->ul_dci_latest_delay, ppWritePackedMsg, end) && + pushs32(pNfapiMsg->dl_tti_earliest_arrival, ppWritePackedMsg, end) && + pushs32(pNfapiMsg->tx_data_request_earliest_arrival, ppWritePackedMsg, end) && + pushs32(pNfapiMsg->ul_tti_earliest_arrival, ppWritePackedMsg, end) && + pushs32(pNfapiMsg->ul_dci_earliest_arrival, ppWritePackedMsg, end) && + pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); +} + + +//NR UPLINK indication function packing + +//RX DATA INDICATION + +static uint8_t pack_nr_rx_data_indication_body(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_nr_rx_data_pdu_t* value = (nfapi_nr_rx_data_pdu_t*)tlv; + + if(!(push32(value->handle, ppWritePackedMsg, end) && + push16(value->rnti, ppWritePackedMsg, end) && + push8(value->harq_id, ppWritePackedMsg, end) && + push16(value->pdu_length, ppWritePackedMsg, end) && + push8(value->ul_cqi, ppWritePackedMsg, end) && + push16(value->timing_advance, ppWritePackedMsg, end) && + push16(value->rssi, ppWritePackedMsg, end) + )) + return 0; + + return 1; +} + + +static uint8_t pack_nr_rx_data_indication(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) +{ + nfapi_nr_rx_data_indication_t *pNfapiMsg = (nfapi_nr_rx_data_indication_t*)msg; + + if (!(push16(pNfapiMsg->sfn , ppWritePackedMsg, end) && + push16(pNfapiMsg->slot , ppWritePackedMsg, end) && + push16(pNfapiMsg->number_of_pdus, ppWritePackedMsg, end) + )) + return 0; + + for(int i=0; inumber_of_pdus;i++) + { + if(!pack_nr_rx_data_indication_body(pNfapiMsg->pdu_list,ppWritePackedMsg,end)) + return 0; + } + +return 1; +} + +//NR CRC INDICATION + +static uint8_t pack_nr_crc_indication_body(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_nr_crc_t* value = (nfapi_nr_crc_t*)tlv; + + if(!(push32(value->handle, ppWritePackedMsg, end) && + push16(value->rnti, ppWritePackedMsg, end) && + push8(value->harq_id, ppWritePackedMsg, end) && + push8(value->tb_crc_status, ppWritePackedMsg, end) && + push16(value->num_cb, ppWritePackedMsg, end) && + //pusharray8(value->cb_crc_status, (int)(value->num_cb / 8) + 1, (int)(value->num_cb / 8) + 1, ppWritePackedMsg, end) && //length is ceil(NumCb/8) + push8(value->ul_cqi, ppWritePackedMsg, end) && + push16(value->timing_advance, ppWritePackedMsg, end) && + push16(value->rssi, ppWritePackedMsg, end) + )) + return 0; + + return 1; +} + +static uint8_t pack_nr_crc_indication(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) +{ + nfapi_nr_crc_indication_t *pNfapiMsg = (nfapi_nr_crc_indication_t*)msg; + + if (!(push16(pNfapiMsg->sfn , ppWritePackedMsg, end) && + push16(pNfapiMsg->slot , ppWritePackedMsg, end) && + push16(pNfapiMsg->number_crcs, ppWritePackedMsg, end) + )) + return 0; + + for(int i=0; inumber_crcs;i++) + { + if(!pack_nr_crc_indication_body(pNfapiMsg->crc_list,ppWritePackedMsg,end)) + return 0; + } + +return 1; +} + +//SRS INDICATION + +static uint8_t pack_nr_srs_indication_body(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_nr_srs_indication_pdu_t* value = (nfapi_nr_srs_indication_pdu_t*)tlv; + + if(!(push32(value->handle, ppWritePackedMsg, end) && + push16(value->rnti, ppWritePackedMsg, end) && + push16(value->timing_advance, ppWritePackedMsg, end) && + push8(value->num_symbols, ppWritePackedMsg, end) && + push8(value->wide_band_snr, ppWritePackedMsg, end) && + push8(value->num_reported_symbols, ppWritePackedMsg, end) && + push8(value->reported_symbol_list->num_rbs, ppWritePackedMsg, end) + )) + return 0; + for(int i = 0; i < value->reported_symbol_list->num_rbs; i++) + { + if(!(push8(value->reported_symbol_list->rb_list->rb_snr, ppWritePackedMsg, end) + )) + return 0; + } + return 1; +} + +static uint8_t pack_nr_srs_indication(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) +{ + nfapi_nr_srs_indication_t *pNfapiMsg = (nfapi_nr_srs_indication_t*)msg; + + if (!(push16(pNfapiMsg->sfn , ppWritePackedMsg, end) && + push16(pNfapiMsg->slot , ppWritePackedMsg, end) && + push16(pNfapiMsg->number_of_pdus, ppWritePackedMsg, end) + )) + return 0; + + for(int i=0; inumber_of_pdus;i++) + { + if(!pack_nr_srs_indication_body(&(pNfapiMsg->pdu_list[i]),ppWritePackedMsg,end)) + return 0; + } + +return 1; +} + +//RACH INDICATION + +static uint8_t pack_nr_rach_indication_body(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_nr_prach_indication_pdu_t* value = (nfapi_nr_prach_indication_pdu_t*)tlv; + + if(!(push16(value->phy_cell_id, ppWritePackedMsg, end) && + push8(value->symbol_index, ppWritePackedMsg, end) && + push8(value->slot_index, ppWritePackedMsg, end) && + push8(value->freq_index, ppWritePackedMsg, end) && + push8(value->avg_rssi, ppWritePackedMsg, end) && + push8(value->avg_snr, ppWritePackedMsg, end) && + push8(value->num_preamble, ppWritePackedMsg, end) + )) + return 0; + for(int i = 0; i < value->num_preamble; i++) + { + if(!(push8(value->preamble_list->preamble_index, ppWritePackedMsg, end) && + push16(value->preamble_list->timing_advance, ppWritePackedMsg, end) && + push32(value->preamble_list->preamble_pwr, ppWritePackedMsg, end) + )) + return 0; + } + return 1; +} + +static uint8_t pack_nr_rach_indication(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) +{ + nfapi_nr_rach_indication_t *pNfapiMsg = (nfapi_nr_rach_indication_t*)msg; + + if (!(push16(pNfapiMsg->sfn , ppWritePackedMsg, end) && + push16(pNfapiMsg->slot , ppWritePackedMsg, end) && + push16(pNfapiMsg->number_of_pdus, ppWritePackedMsg, end) + )) + return 0; + + for(int i=0; inumber_of_pdus;i++) + { + if(!pack_nr_rach_indication_body(&(pNfapiMsg->pdu_list[i]),ppWritePackedMsg,end)) + return 0; + } + +return 1; +} + + +//UCI INDICATION + +static uint8_t pack_nr_uci_pucch_0_1(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_nr_uci_pucch_pdu_format_0_1_t* value = (nfapi_nr_uci_pucch_pdu_format_0_1_t*)tlv; + + if(!(push8(value->pduBitmap, ppWritePackedMsg, end) && + push32(value->handle, ppWritePackedMsg, end) && + push16(value->rnti, ppWritePackedMsg, end) && + push8(value->pucch_format, ppWritePackedMsg, end) && + push8(value->ul_cqi, ppWritePackedMsg, end) && + push16(value->timing_advance, ppWritePackedMsg, end) && + push16(value->rssi, ppWritePackedMsg, end) + )) + return 0; + if (value->pduBitmap & 0x01) { //SR + if(!(push8(value->sr->sr_indication, ppWritePackedMsg, end) && + push8(value->sr->sr_confidence_level, ppWritePackedMsg, end) + )) + return 0; + } + + if (((value->pduBitmap >> 1) & 0x01)) { //HARQ + if(!(push8(value->harq->num_harq, ppWritePackedMsg, end) && + push8(value->harq->harq_confidence_level, ppWritePackedMsg, end) + )) + return 0; + + for(int i=0; iharq->num_harq;i++) + { + if(!(push8(value->harq->harq_list[i].harq_value, ppWritePackedMsg, end) + )) + return 0; + } + } + + return 1; +} + +static uint8_t pack_nr_uci_pucch_2_3_4(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_nr_uci_pucch_pdu_format_2_3_4_t* value = (nfapi_nr_uci_pucch_pdu_format_2_3_4_t*) tlv; + + if(!(push8(value->pduBitmap, ppWritePackedMsg, end) && + push32(value->handle, ppWritePackedMsg, end) && + push16(value->rnti, ppWritePackedMsg, end) && + push8(value->pucch_format, ppWritePackedMsg, end) && + push8(value->ul_cqi, ppWritePackedMsg, end) && + push16(value->timing_advance, ppWritePackedMsg, end) && + push16(value->rssi, ppWritePackedMsg, end) + )) + return 0; + + if (value->pduBitmap & 0x01) { //SR + if(!(push8(value->sr.sr_bit_len, ppWritePackedMsg, end) && + pusharray8(value->sr.sr_payload, (int)(value->sr.sr_bit_len / 8) + 1, (int)(value->sr.sr_bit_len / 8) + 1, ppWritePackedMsg, end) + )) + return 0; + } + + if (((value->pduBitmap >> 1) & 0x01)) { //HARQ + if(!(push8(value->harq.harq_crc, ppWritePackedMsg, end) && + push8(value->harq.harq_bit_len, ppWritePackedMsg, end) && + pusharray8(value->harq.harq_payload, (int)(value->harq.harq_bit_len / 8) + 1, (int)(value->harq.harq_bit_len / 8) + 1, ppWritePackedMsg, end) + )) + return 0; + } + + if (((value->pduBitmap >> 2) & 0x01)) { //CSI-1 + if(!(push8(value->csi_part1.csi_part1_crc, ppWritePackedMsg, end) && + push8(value->csi_part1.csi_part1_bit_len, ppWritePackedMsg, end) && + pusharray8(value->csi_part1.csi_part1_payload, (int)(value->csi_part1.csi_part1_bit_len / 8) + 1, (int)(value->csi_part1.csi_part1_bit_len / 8) + 1, ppWritePackedMsg, end) + )) + return 0; + } + + if (((value->pduBitmap >> 3) & 0x01)) { //CSI-2 + if(!(push8(value->csi_part2.csi_part2_crc, ppWritePackedMsg, end) && + push8(value->csi_part2.csi_part2_bit_len, ppWritePackedMsg, end) && + pusharray8(value->csi_part2.csi_part2_payload, (int)(value->csi_part2.csi_part2_bit_len / 8) + 1, (int)(value->csi_part2.csi_part2_bit_len / 8) + 1, ppWritePackedMsg, end) + )) + return 0; + } + + return 1; +} + +static uint8_t pack_nr_uci_indication_body(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_nr_uci_t* value = (nfapi_nr_uci_t*)tlv; + + if(!(push16(value->pdu_type, ppWritePackedMsg, end) && + push16(value->pdu_size, ppWritePackedMsg, end) + )) + return 0; + + switch (value->pdu_type) { + case NFAPI_NR_UCI_PUSCH_PDU_TYPE: + printf("Unhandled NFAPI_NR_UCI_PUSCH_PDU_TYPE \n"); + break; + + case NFAPI_NR_UCI_FORMAT_0_1_PDU_TYPE: { + nfapi_nr_uci_pucch_pdu_format_0_1_t *uci_pdu = &value->pucch_pdu_format_0_1; + pack_nr_uci_pucch_0_1(uci_pdu, ppWritePackedMsg, end); + break; + } + case NFAPI_NR_UCI_FORMAT_2_3_4_PDU_TYPE: { + nfapi_nr_uci_pucch_pdu_format_2_3_4_t *uci_pdu = &value->pucch_pdu_format_2_3_4; + pack_nr_uci_pucch_2_3_4(uci_pdu, ppWritePackedMsg, end); + break; + } + } + + return 1; +} + +static uint8_t pack_nr_uci_indication(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) +{ + nfapi_nr_uci_indication_t *pNfapiMsg = (nfapi_nr_uci_indication_t*)msg; + + if (!(push16(pNfapiMsg->sfn , ppWritePackedMsg, end) && + push16(pNfapiMsg->slot , ppWritePackedMsg, end) && + push16(pNfapiMsg->num_ucis, ppWritePackedMsg, end) + )) + return 0; + + for(int i=0; inum_ucis;i++) + { + if(!pack_nr_uci_indication_body(&(pNfapiMsg->uci_list[i]),ppWritePackedMsg,end)) + return 0; + } + +return 1; +} + +// Main pack function - public + +int nfapi_nr_p7_message_pack(void *pMessageBuf, void *pPackedBuf, uint32_t packedBufLen, nfapi_p7_codec_config_t* config) +{ + nfapi_p7_message_header_t *pMessageHeader = pMessageBuf; + uint8_t *pWritePackedMessage = pPackedBuf; + uint8_t *pPackedLengthField = &pWritePackedMessage[4]; + uint8_t *end = pPackedBuf + packedBufLen; + + if (pMessageBuf == NULL || pPackedBuf == NULL) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "P7 Pack supplied pointers are null\n"); + return -1; + } + /* + printf("\n P7 MESSAGE SENT: \n"); + for(int i=0; i< packedBufLen; i++){ + printf("%d", *(uint8_t *)(pMessageBuf + i)); + } + printf("\n"); + */ + // process the header + if(!(push16(pMessageHeader->phy_id, &pWritePackedMessage, end) && + push16(pMessageHeader->message_id, &pWritePackedMessage, end) && + push16(0/*pMessageHeader->message_length*/, &pWritePackedMessage, end) && + push16(pMessageHeader->m_segment_sequence, &pWritePackedMessage, end) && + push32(0/*pMessageHeader->checksum*/, &pWritePackedMessage, end) && + push32(pMessageHeader->transmit_timestamp, &pWritePackedMessage, end))) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "P7 Pack header failed\n"); + return -1; + } + + if (pMessageHeader->message_id != NFAPI_TIMING_INFO) + { + //NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() message_id:0x%04x phy_id:%u m_segment_sequence:%u timestamp:%u\n", __FUNCTION__, pMessageHeader->message_id, pMessageHeader->phy_id, pMessageHeader->m_segment_sequence, pMessageHeader->transmit_timestamp); + } + // look for the specific message + uint8_t result = 0; + switch (pMessageHeader->message_id) + { + case NFAPI_NR_PHY_MSG_TYPE_DL_TTI_REQUEST: + result = pack_dl_tti_request(pMessageHeader, &pWritePackedMessage, end, config); + printf("result of pack dl_tti_req is %d. \n",result); + break; + + case NFAPI_NR_PHY_MSG_TYPE_UL_TTI_REQUEST: + result = pack_ul_tti_request(pMessageHeader, &pWritePackedMessage, end, config); + break; + case NFAPI_NR_PHY_MSG_TYPE_TX_DATA_REQUEST: + result = pack_tx_data_request(pMessageHeader, &pWritePackedMessage, end, config); + break; + case NFAPI_NR_PHY_MSG_TYPE_UL_DCI_REQUEST: + result = pack_ul_dci_request(pMessageHeader, &pWritePackedMessage, end, config); + break; + + case NFAPI_UE_RELEASE_REQUEST: + result =pack_ue_release_request(pMessageHeader, &pWritePackedMessage, end, config); + break; + + case NFAPI_UE_RELEASE_RESPONSE: + result =pack_ue_release_response(pMessageHeader, &pWritePackedMessage, end, config); + break; + + case NFAPI_NR_PHY_MSG_TYPE_RX_DATA_INDICATION: + result = pack_nr_rx_data_indication(pMessageHeader, &pWritePackedMessage, end, config); + break; + + case NFAPI_NR_PHY_MSG_TYPE_CRC_INDICATION: + result = pack_nr_crc_indication(pMessageHeader, &pWritePackedMessage, end, config); + break; + + case NFAPI_NR_PHY_MSG_TYPE_UCI_INDICATION: + result = pack_nr_uci_indication(pMessageHeader, &pWritePackedMessage, end, config); + break; + + case NFAPI_NR_PHY_MSG_TYPE_SRS_INDICATION: + result = pack_nr_rach_indication(pMessageHeader, &pWritePackedMessage, end, config); + break; + + case NFAPI_NR_PHY_MSG_TYPE_RACH_INDICATION: + result = pack_nr_srs_indication(pMessageHeader, &pWritePackedMessage, end, config); + break; + + case NFAPI_NR_PHY_MSG_TYPE_DL_NODE_SYNC: + result = pack_nr_dl_node_sync(pMessageHeader, &pWritePackedMessage, end, config); + break; + + case NFAPI_NR_PHY_MSG_TYPE_UL_NODE_SYNC: + result = pack_nr_ul_node_sync(pMessageHeader, &pWritePackedMessage, end, config); + break; + + case NFAPI_TIMING_INFO: + result = pack_nr_timing_info(pMessageHeader, &pWritePackedMessage, end, config); + break; + + default: + { + if(pMessageHeader->message_id >= NFAPI_VENDOR_EXT_MSG_MIN && + pMessageHeader->message_id <= NFAPI_VENDOR_EXT_MSG_MAX) + { + if(config && config->pack_p7_vendor_extension) + { + result = (config->pack_p7_vendor_extension)(pMessageHeader, &pWritePackedMessage, end, config); + } + else + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s VE NFAPI message ID %d. No ve ecoder provided\n", __FUNCTION__, pMessageHeader->message_id); + } + } + else + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s NFAPI Unknown message ID %d\n", __FUNCTION__, pMessageHeader->message_id); + } + } + break; + } + + if(result == 0) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "P7 Pack failed to pack message\n"); + return -1; + } + + // check for a valid message length + uintptr_t msgHead = (uintptr_t)pPackedBuf; + uintptr_t msgEnd = (uintptr_t)pWritePackedMessage; + uint32_t packedMsgLen = msgEnd - msgHead; + uint16_t packedMsgLen16; + if (packedMsgLen > 0xFFFF || packedMsgLen > packedBufLen) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "Packed message length error %d, buffer supplied %d\n", packedMsgLen, packedBufLen); + return -1; + } + else + { + packedMsgLen16 = (uint16_t)packedMsgLen; + } + + // Update the message length in the header + pMessageHeader->message_length = packedMsgLen16; + + if(!push16(packedMsgLen16, &pPackedLengthField, end)) + return -1; + + if(1) + { + //quick test + if(pMessageHeader->message_length != packedMsgLen) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "nfapi packedMsgLen(%d) != message_length(%d) id %d\n", packedMsgLen, pMessageHeader->message_length, pMessageHeader->message_id); + } + } + + return (packedMsgLen); +} + +int nfapi_p7_message_pack(void *pMessageBuf, void *pPackedBuf, uint32_t packedBufLen, nfapi_p7_codec_config_t* config) +{ + nfapi_p7_message_header_t *pMessageHeader = pMessageBuf; + uint8_t *pWritePackedMessage = pPackedBuf; + uint8_t *pPackedLengthField = &pWritePackedMessage[4]; + uint8_t *end = pPackedBuf + packedBufLen; + + if (pMessageBuf == NULL || pPackedBuf == NULL) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "P7 Pack supplied pointers are null\n"); + return -1; + } + /* + printf("\n P7 MESSAGE SENT: \n"); + for(int i=0; i< packedBufLen; i++){ + printf("%d", *(uint8_t *)(pMessageBuf + i)); + } + printf("\n"); + */ + // process the header + if(!(push16(pMessageHeader->phy_id, &pWritePackedMessage, end) && + push16(pMessageHeader->message_id, &pWritePackedMessage, end) && + push16(0/*pMessageHeader->message_length*/, &pWritePackedMessage, end) && + push16(pMessageHeader->m_segment_sequence, &pWritePackedMessage, end) && + push32(0/*pMessageHeader->checksum*/, &pWritePackedMessage, end) && + push32(pMessageHeader->transmit_timestamp, &pWritePackedMessage, end))) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "P7 Pack header failed\n"); + return -1; + } + + if (pMessageHeader->message_id != NFAPI_TIMING_INFO) + { + //NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() message_id:0x%04x phy_id:%u m_segment_sequence:%u timestamp:%u\n", __FUNCTION__, pMessageHeader->message_id, pMessageHeader->phy_id, pMessageHeader->m_segment_sequence, pMessageHeader->transmit_timestamp); + } + // look for the specific message + uint8_t result = 0; + switch (pMessageHeader->message_id) + { + case NFAPI_DL_CONFIG_REQUEST: + result = pack_dl_config_request(pMessageHeader, &pWritePackedMessage, end, config); + break; + + case NFAPI_UL_CONFIG_REQUEST: + result = pack_ul_config_request(pMessageHeader, &pWritePackedMessage, end, config); + break; + case NFAPI_TX_REQUEST: + result = pack_tx_request(pMessageHeader, &pWritePackedMessage, end, config); + break; + case NFAPI_HI_DCI0_REQUEST: + result = pack_hi_dci0_request(pMessageHeader, &pWritePackedMessage, end, config); + break; + + case NFAPI_UE_RELEASE_REQUEST: + result =pack_ue_release_request(pMessageHeader, &pWritePackedMessage, end, config); + break; + + case NFAPI_UE_RELEASE_RESPONSE: + result =pack_ue_release_response(pMessageHeader, &pWritePackedMessage, end, config); + break; + + case NFAPI_HARQ_INDICATION: + result = pack_harq_indication(pMessageHeader, &pWritePackedMessage, end, config); + break; + + case NFAPI_CRC_INDICATION: + result = pack_crc_indication(pMessageHeader, &pWritePackedMessage, end, config); + break; + + case NFAPI_RX_ULSCH_INDICATION: + result = pack_rx_ulsch_indication(pMessageHeader, &pWritePackedMessage, end, config); + break; + + case NFAPI_RACH_INDICATION: + result = pack_rach_indication(pMessageHeader, &pWritePackedMessage, end, config); + break; + + case NFAPI_SRS_INDICATION: + result = pack_srs_indication(pMessageHeader, &pWritePackedMessage, end, config); + break; + + case NFAPI_RX_SR_INDICATION: + result = pack_sr_indication(pMessageHeader, &pWritePackedMessage, end, config); + break; + + case NFAPI_RX_CQI_INDICATION: + result = pack_cqi_indication(pMessageHeader, &pWritePackedMessage, end, config); + break; + + case NFAPI_LBT_DL_CONFIG_REQUEST: + result = pack_lbt_dl_config_request(pMessageHeader, &pWritePackedMessage, end, config); + break; + + case NFAPI_LBT_DL_INDICATION: + result = pack_lbt_dl_indication(pMessageHeader, &pWritePackedMessage, end, config); + break; + + case NFAPI_NB_HARQ_INDICATION: + result = pack_nb_harq_indication(pMessageHeader, &pWritePackedMessage, end, config); + break; + + case NFAPI_NRACH_INDICATION: + result = pack_nrach_indication(pMessageHeader, &pWritePackedMessage, end, config); + break; + + case NFAPI_DL_NODE_SYNC: + result = pack_dl_node_sync(pMessageHeader, &pWritePackedMessage, end, config); + break; + + case NFAPI_UL_NODE_SYNC: + result = pack_ul_node_sync(pMessageHeader, &pWritePackedMessage, end, config); + break; + + case NFAPI_TIMING_INFO: + result = pack_timing_info(pMessageHeader, &pWritePackedMessage, end, config); + break; + + default: + { + if(pMessageHeader->message_id >= NFAPI_VENDOR_EXT_MSG_MIN && + pMessageHeader->message_id <= NFAPI_VENDOR_EXT_MSG_MAX) + { + if(config && config->pack_p7_vendor_extension) + { + result = (config->pack_p7_vendor_extension)(pMessageHeader, &pWritePackedMessage, end, config); + } + else + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s VE NFAPI message ID %d. No ve ecoder provided\n", __FUNCTION__, pMessageHeader->message_id); + } + } + else + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s NFAPI Unknown message ID %d\n", __FUNCTION__, pMessageHeader->message_id); + } + } + break; + } + + if(result == 0) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "P7 Pack failed to pack message\n"); + return -1; + } + + // check for a valid message length + uintptr_t msgHead = (uintptr_t)pPackedBuf; + uintptr_t msgEnd = (uintptr_t)pWritePackedMessage; + uint32_t packedMsgLen = msgEnd - msgHead; + uint16_t packedMsgLen16; + if (packedMsgLen > 0xFFFF || packedMsgLen > packedBufLen) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "Packed message length error %d, buffer supplied %d\n", packedMsgLen, packedBufLen); + return -1; + } + else + { + packedMsgLen16 = (uint16_t)packedMsgLen; + } + + // Update the message length in the header + pMessageHeader->message_length = packedMsgLen16; + + if(!push16(packedMsgLen16, &pPackedLengthField, end)) + return -1; + + if(1) + { + //quick test + if(pMessageHeader->message_length != packedMsgLen) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "nfapi packedMsgLen(%d) != message_length(%d) id %d\n", packedMsgLen, pMessageHeader->message_length, pMessageHeader->message_id); + } + } + + return (packedMsgLen); +} + +// Unpack routines +// NR: +static uint8_t unpack_dl_tti_csi_rs_pdu_rel15_value(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_nr_dl_tti_csi_rs_pdu_rel15_t* value = (nfapi_nr_dl_tti_csi_rs_pdu_rel15_t*)tlv; + + return( + pull16(ppReadPackedMsg, &value->bwp_size, end) && + pull16(ppReadPackedMsg, &value->bwp_start, end) && + + pull8(ppReadPackedMsg, &value->subcarrier_spacing, end) && + pull8(ppReadPackedMsg, &value->cyclic_prefix, end) && + + pull16(ppReadPackedMsg, &value->start_rb, end) && + pull16(ppReadPackedMsg, &value->nr_of_rbs, end) && + + pull8(ppReadPackedMsg, &value->csi_type, end) && + pull8(ppReadPackedMsg, &value->row, end) && + + pull16(ppReadPackedMsg, &value->freq_domain, end) && + pull8(ppReadPackedMsg, &value->symb_l0, end) && + + pull8(ppReadPackedMsg, &value->symb_l1, end) && + pull8(ppReadPackedMsg, &value->cdm_type, end) && + + pull8(ppReadPackedMsg, &value->freq_density, end) && + pull16(ppReadPackedMsg, &value->scramb_id, end) && + + pull8(ppReadPackedMsg, &value->power_control_offset, end) && + pull8(ppReadPackedMsg, &value->power_control_offset_ss, end) + ); + +} + + +static uint8_t unpack_dl_tti_pdcch_pdu_rel15_value(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_nr_dl_tti_pdcch_pdu_rel15_t* value = (nfapi_nr_dl_tti_pdcch_pdu_rel15_t*)tlv; + + for(uint8_t i = 0; i < MAX_DCI_CORESET; ++i) + { + if(!(pull16(ppReadPackedMsg, &value->dci_pdu[i].RNTI, end) && + pull16(ppReadPackedMsg, &value->dci_pdu[i].ScramblingId, end) && + + pull16(ppReadPackedMsg, &value->dci_pdu[i].ScramblingRNTI, end) && + pull8(ppReadPackedMsg, &value->dci_pdu[i].CceIndex, end) && + pull8(ppReadPackedMsg, &value->dci_pdu[i].AggregationLevel, end) && + pull8(ppReadPackedMsg, &value->dci_pdu[i].beta_PDCCH_1_0, end) && + + pull8(ppReadPackedMsg, &value->dci_pdu[i].powerControlOffsetSS, end) && + pull16(ppReadPackedMsg, &value->dci_pdu[i].PayloadSizeBits, end) && + + pullarray8(ppReadPackedMsg, value->dci_pdu[i].Payload, value->dci_pdu[i].PayloadSizeBits, value->dci_pdu[i].PayloadSizeBits, end))) + + return 0; + } + + // TODO: resolve the packaging of array (currently sending a single element) + return( + pull16(ppReadPackedMsg, &value->BWPSize, end) && + pull16(ppReadPackedMsg, &value->BWPStart, end) && + pull8(ppReadPackedMsg, &value->SubcarrierSpacing, end) && + pull8(ppReadPackedMsg, &value->CyclicPrefix, end) && + + pull8(ppReadPackedMsg, &value->StartSymbolIndex, end) && + pull8(ppReadPackedMsg, &value->DurationSymbols, end) && + pullarray8(ppReadPackedMsg, value->FreqDomainResource, 6, 6, end) && + pull8(ppReadPackedMsg, &value->CceRegMappingType, end) && + + pull8(ppReadPackedMsg, &value->RegBundleSize, end) && + pull8(ppReadPackedMsg, &value->InterleaverSize, end) && + pull8(ppReadPackedMsg, &value->CoreSetType, end) && + pull16(ppReadPackedMsg, &value->ShiftIndex, end) && + + pull8(ppReadPackedMsg, &value->precoderGranularity, end) && + pull16(ppReadPackedMsg, &value->numDlDci, end)); + +} + + +static uint8_t unpack_dl_tti_pdsch_pdu_rel15_value(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_nr_dl_tti_pdsch_pdu_rel15_t* value = (nfapi_nr_dl_tti_pdsch_pdu_rel15_t*)tlv; + + // TODO: resolve the packaging of array (currently sending a single element) + return( + pull16(ppReadPackedMsg, &value->pduBitmap, end) && + pull16(ppReadPackedMsg, &value->rnti, end) && + pull16(ppReadPackedMsg, &value->pduIndex, end) && + pull16(ppReadPackedMsg, &value->BWPSize, end) && + + pull16(ppReadPackedMsg, &value->BWPStart, end) && + pull8(ppReadPackedMsg, &value->SubcarrierSpacing, end) && + pull8(ppReadPackedMsg, &value->CyclicPrefix, end) && + pull8(ppReadPackedMsg, &value->NrOfCodewords, end) && + + pullarray16(ppReadPackedMsg, value->targetCodeRate, 2, 1, end) && + pullarray8(ppReadPackedMsg, value->qamModOrder, 2, 1, end) && + pullarray8(ppReadPackedMsg, value->mcsIndex, 2, 1, end) && + pullarray8(ppReadPackedMsg, value->mcsTable, 2, 1, end) && + + pullarray8(ppReadPackedMsg, value->rvIndex, 2, 1, end) && + pullarray32(ppReadPackedMsg, value->TBSize, 2, 1, end) && + pull16(ppReadPackedMsg, &value->dataScramblingId, end) && + pull8(ppReadPackedMsg, &value->nrOfLayers, end) && + + pull8(ppReadPackedMsg, &value->transmissionScheme, end) && + pull8(ppReadPackedMsg, &value->refPoint, end) && + pull16(ppReadPackedMsg, &value->dlDmrsSymbPos, end) && + pull8(ppReadPackedMsg, &value->dmrsConfigType, end) && + + pull16(ppReadPackedMsg, &value->dlDmrsScramblingId, end) && + pull8(ppReadPackedMsg, &value->SCID, end) && + pull8(ppReadPackedMsg, &value->numDmrsCdmGrpsNoData, end) && + pull16(ppReadPackedMsg, &value->dmrsPorts, end) && + + pull8(ppReadPackedMsg, &value->resourceAlloc, end) && + pull16(ppReadPackedMsg, &value->rbStart, end) && + pull16(ppReadPackedMsg, &value->rbSize, end) && + + pull8(ppReadPackedMsg, &value->VRBtoPRBMapping, end) && + pull8(ppReadPackedMsg, &value->StartSymbolIndex, end) && + pull8(ppReadPackedMsg, &value->NrOfSymbols, end) && + pull8(ppReadPackedMsg, &value->PTRSPortIndex, end) && + + pull8(ppReadPackedMsg, &value->PTRSTimeDensity, end) && + pull8(ppReadPackedMsg, &value->PTRSFreqDensity, end) && + pull8(ppReadPackedMsg, &value->PTRSReOffset, end) + ); + +} + + +static uint8_t unpack_dl_tti_ssb_pdu_rel15_value(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + printf("ssb received and unpacked. \n"); + nfapi_nr_dl_tti_ssb_pdu_rel15_t* value = (nfapi_nr_dl_tti_ssb_pdu_rel15_t*)tlv; + + return( + pull16(ppReadPackedMsg, &value->PhysCellId, end) && + pull8(ppReadPackedMsg, &value->BetaPss, end) && + pull8(ppReadPackedMsg, &value->SsbBlockIndex, end) && + pull8(ppReadPackedMsg, &value->SsbSubcarrierOffset, end) && + pull16(ppReadPackedMsg, &value->ssbOffsetPointA, end) && + pull8(ppReadPackedMsg, &value->bchPayloadFlag, end) && + pull32(ppReadPackedMsg, &value->bchPayload, end) + // TODO: pack precoding_and_beamforming too + ); + +} + + +// LTE: +static uint8_t unpack_dl_config_dci_dl_pdu_rel8_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_dl_config_dci_dl_pdu_rel8_t* dci_dl_pdu_rel8 = (nfapi_dl_config_dci_dl_pdu_rel8_t*)tlv; + + return (pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->dci_format, end) && + pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->cce_idx, end) && + pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->aggregation_level, end) && + pull16(ppReadPackedMsg, &dci_dl_pdu_rel8->rnti, end) && + pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->resource_allocation_type, end) && + pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->virtual_resource_block_assignment_flag, end) && + pull32(ppReadPackedMsg, &dci_dl_pdu_rel8->resource_block_coding, end) && + pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->mcs_1, end) && + pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->redundancy_version_1, end) && + pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->new_data_indicator_1, end) && + pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->transport_block_to_codeword_swap_flag, end) && + pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->mcs_2, end) && + pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->redundancy_version_2, end) && + pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->new_data_indicator_2, end) && + pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->harq_process, end) && + pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->tpmi, end) && + pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->pmi, end) && + pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->precoding_information, end) && + pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->tpc, end) && + pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->downlink_assignment_index, end) && + pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->ngap, end) && + pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->transport_block_size_index, end) && + pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->downlink_power_offset, end) && + pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->allocate_prach_flag, end) && + pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->preamble_index, end) && + pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->prach_mask_index, end) && + pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->rnti_type, end) && + pull16(ppReadPackedMsg, &dci_dl_pdu_rel8->transmission_power, end)); + +} + +static uint8_t unpack_dl_config_dci_dl_pdu_rel9_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_dl_config_dci_dl_pdu_rel9_t* dci_dl_pdu_rel9 = (nfapi_dl_config_dci_dl_pdu_rel9_t*)tlv; + + return ( pull8(ppReadPackedMsg, &dci_dl_pdu_rel9->mcch_flag, end) && + pull8(ppReadPackedMsg, &dci_dl_pdu_rel9->mcch_change_notification, end) && + pull8(ppReadPackedMsg, &dci_dl_pdu_rel9->scrambling_identity, end)); +} + +static uint8_t unpack_dl_config_dci_dl_pdu_rel10_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_dl_config_dci_dl_pdu_rel10_t* dci_dl_pdu_rel10 = (nfapi_dl_config_dci_dl_pdu_rel10_t*)tlv; + + return (pull8(ppReadPackedMsg, &dci_dl_pdu_rel10->cross_carrier_scheduling_flag, end) && + pull8(ppReadPackedMsg, &dci_dl_pdu_rel10->carrier_indicator, end) && + pull8(ppReadPackedMsg, &dci_dl_pdu_rel10->srs_flag, end) && + pull8(ppReadPackedMsg, &dci_dl_pdu_rel10->srs_request, end) && + pull8(ppReadPackedMsg, &dci_dl_pdu_rel10->antenna_ports_scrambling_and_layers, end) && + pull8(ppReadPackedMsg, &dci_dl_pdu_rel10->total_dci_length_including_padding, end) && + pull8(ppReadPackedMsg, &dci_dl_pdu_rel10->n_dl_rb, end)); +} + +static uint8_t unpack_dl_config_dci_dl_pdu_rel11_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_dl_config_dci_dl_pdu_rel11_t* dci_dl_pdu_rel11 = (nfapi_dl_config_dci_dl_pdu_rel11_t*)tlv; + + return (pull8(ppReadPackedMsg, &dci_dl_pdu_rel11->harq_ack_resource_offset, end) && + pull8(ppReadPackedMsg, &dci_dl_pdu_rel11->pdsch_re_mapping_quasi_co_location_indicator, end)); +} + +static uint8_t unpack_dl_config_dci_dl_pdu_rel12_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_dl_config_dci_dl_pdu_rel12_t* dci_dl_pdu_rel12 = (nfapi_dl_config_dci_dl_pdu_rel12_t*)tlv; + + return (pull8(ppReadPackedMsg, &dci_dl_pdu_rel12->primary_cell_type, end) && + pull8(ppReadPackedMsg, &dci_dl_pdu_rel12->ul_dl_configuration_flag, end) && + pull8(ppReadPackedMsg, &dci_dl_pdu_rel12->number_ul_dl_configurations, end) && + pullarray8(ppReadPackedMsg, dci_dl_pdu_rel12->ul_dl_configuration_indication, NFAPI_MAX_UL_DL_CONFIGURATIONS, dci_dl_pdu_rel12->number_ul_dl_configurations, end)); +} + +static uint8_t unpack_tpm_value(uint8_t **ppReadPackedMsg, nfapi_dl_config_dci_dl_tpm_t *value, uint8_t *end) +{ + if(!(pull8(ppReadPackedMsg, &value->num_prb_per_subband, end) && + pull8(ppReadPackedMsg, &value->number_of_subbands, end) && + pull8(ppReadPackedMsg, &value->num_antennas, end))) + return 0; + + + uint8_t idx = 0; + for(idx = 0; idx < value->number_of_subbands; ++idx) + { + nfapi_dl_config_dci_dl_tpm_subband_info_t* subband_info = &(value->subband_info[idx]); + + if(!(pull8(ppReadPackedMsg, &subband_info->subband_index, end) && + pull8(ppReadPackedMsg, &subband_info->scheduled_ues, end))) + return 0; + + uint8_t antenna_idx = 0; + uint8_t scheduled_ue_idx = 0; + + for(antenna_idx = 0; antenna_idx < value->num_antennas; ++antenna_idx) + { + for(scheduled_ue_idx = 0; scheduled_ue_idx < subband_info->scheduled_ues; ++scheduled_ue_idx) + { + if(!pull16(ppReadPackedMsg, &(subband_info->precoding_value[antenna_idx][scheduled_ue_idx]), end)) + return 0; + } + } + + } + + + return 1; + +} + + +static uint8_t unpack_dl_config_dci_dl_pdu_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_dl_config_dci_dl_pdu_rel13_t* dci_dl_pdu_rel13 = (nfapi_dl_config_dci_dl_pdu_rel13_t*)tlv; + + // If the length is greater than 5 then the TPM struct flag and possiably the TPM structure have been + // added + uint8_t tpm_struct_flag_present = dci_dl_pdu_rel13->tl.length > 5; + dci_dl_pdu_rel13->tpm_struct_flag = 0; + + return (pull8(ppReadPackedMsg, &dci_dl_pdu_rel13->laa_end_partial_sf_flag, end) && + pull8(ppReadPackedMsg, &dci_dl_pdu_rel13->laa_end_partial_sf_configuration, end) && + pull8(ppReadPackedMsg, &dci_dl_pdu_rel13->initial_lbt_sf, end) && + pull8(ppReadPackedMsg, &dci_dl_pdu_rel13->codebook_size_determination, end) && + pull8(ppReadPackedMsg, &dci_dl_pdu_rel13->drms_table_flag, end) && + ( (tpm_struct_flag_present == 1) ? pull8(ppReadPackedMsg, &dci_dl_pdu_rel13->tpm_struct_flag, end) : 1) && + ( (tpm_struct_flag_present == 1 && dci_dl_pdu_rel13->tpm_struct_flag == 1) ? unpack_tpm_value(ppReadPackedMsg, &dci_dl_pdu_rel13->tpm, end) : 1)); + +} + +static uint8_t unpack_dl_config_bch_pdu_rel8_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_dl_config_bch_pdu_rel8_t* bch_pdu_rel8 = (nfapi_dl_config_bch_pdu_rel8_t*)tlv; + + return ( pull16(ppReadPackedMsg, &bch_pdu_rel8->length, end) && + pull16(ppReadPackedMsg, (uint16_t *)&bch_pdu_rel8->pdu_index, end) && + pull16(ppReadPackedMsg, &bch_pdu_rel8->transmission_power, end)); +} + +static uint8_t unpack_dl_config_mch_pdu_rel8_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_dl_config_mch_pdu_rel8_t* mch_pdu_rel8 = (nfapi_dl_config_mch_pdu_rel8_t*)tlv; + + return (pull16(ppReadPackedMsg, &mch_pdu_rel8->length, end) && + pull16(ppReadPackedMsg, (uint16_t *)&mch_pdu_rel8->pdu_index, end) && + pull16(ppReadPackedMsg, &mch_pdu_rel8->rnti, end) && + pull8(ppReadPackedMsg, &mch_pdu_rel8->resource_allocation_type, end) && + pull32(ppReadPackedMsg, &mch_pdu_rel8->resource_block_coding, end) && + pull8(ppReadPackedMsg, &mch_pdu_rel8->modulation, end) && + pull16(ppReadPackedMsg, &mch_pdu_rel8->transmission_power, end) && + pull16(ppReadPackedMsg, &mch_pdu_rel8->mbsfn_area_id, end)); +} + +static uint8_t unpack_dl_config_dlsch_pdu_rel8_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_dl_config_dlsch_pdu_rel8_t* dlsch_pdu_rel8 = (nfapi_dl_config_dlsch_pdu_rel8_t*)tlv; + + if (!(pull16(ppReadPackedMsg, &dlsch_pdu_rel8->length, end) && + pull16(ppReadPackedMsg, (uint16_t *)&dlsch_pdu_rel8->pdu_index, end) && + pull16(ppReadPackedMsg, &dlsch_pdu_rel8->rnti, end) && + pull8(ppReadPackedMsg, &dlsch_pdu_rel8->resource_allocation_type, end) && + pull8(ppReadPackedMsg, &dlsch_pdu_rel8->virtual_resource_block_assignment_flag, end) && + pull32(ppReadPackedMsg, &dlsch_pdu_rel8->resource_block_coding, end) && + pull8(ppReadPackedMsg, &dlsch_pdu_rel8->modulation, end) && + pull8(ppReadPackedMsg, &dlsch_pdu_rel8->redundancy_version, end) && + pull8(ppReadPackedMsg, &dlsch_pdu_rel8->transport_blocks, end) && + pull8(ppReadPackedMsg, &dlsch_pdu_rel8->transport_block_to_codeword_swap_flag, end) && + pull8(ppReadPackedMsg, &dlsch_pdu_rel8->transmission_scheme, end) && + pull8(ppReadPackedMsg, &dlsch_pdu_rel8->number_of_layers, end) && + pull8(ppReadPackedMsg, &dlsch_pdu_rel8->number_of_subbands, end) && + pullarray8(ppReadPackedMsg, dlsch_pdu_rel8->codebook_index, NFAPI_MAX_NUM_SUBBANDS, dlsch_pdu_rel8->number_of_subbands, end) && + pull8(ppReadPackedMsg, &dlsch_pdu_rel8->ue_category_capacity, end) && + pull8(ppReadPackedMsg, &dlsch_pdu_rel8->pa, end) && + pull8(ppReadPackedMsg, &dlsch_pdu_rel8->delta_power_offset_index, end) && + pull8(ppReadPackedMsg, &dlsch_pdu_rel8->ngap, end) && + pull8(ppReadPackedMsg, &dlsch_pdu_rel8->nprb, end) && + pull8(ppReadPackedMsg, &dlsch_pdu_rel8->transmission_mode, end) && + pull8(ppReadPackedMsg, &dlsch_pdu_rel8->num_bf_prb_per_subband, end) && + pull8(ppReadPackedMsg, &dlsch_pdu_rel8->num_bf_vector, end))) + return 0; + + uint16_t j = 0; + for(j = 0; j < dlsch_pdu_rel8->num_bf_vector; ++j) + { + if(!(pull8(ppReadPackedMsg, &dlsch_pdu_rel8->bf_vector[j].subband_index, end) && + pull8(ppReadPackedMsg, &dlsch_pdu_rel8->bf_vector[j].num_antennas, end) && + pullarray16(ppReadPackedMsg, dlsch_pdu_rel8->bf_vector[j].bf_value, NFAPI_MAX_NUM_ANTENNAS, dlsch_pdu_rel8->bf_vector[j].num_antennas, end))) + return 0; + } + return 1; +} +static uint8_t unpack_dl_config_dlsch_pdu_rel9_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_dl_config_dlsch_pdu_rel9_t* dlsch_pdu_rel9 = (nfapi_dl_config_dlsch_pdu_rel9_t*)tlv; + return ( pull8(ppReadPackedMsg, &dlsch_pdu_rel9->nscid, end) ); +} +static uint8_t unpack_dl_config_dlsch_pdu_rel10_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_dl_config_dlsch_pdu_rel10_t* dlsch_pdu_rel10 = (nfapi_dl_config_dlsch_pdu_rel10_t*)tlv; + + return ( pull8(ppReadPackedMsg, &dlsch_pdu_rel10->csi_rs_flag, end) && + pull8(ppReadPackedMsg, &dlsch_pdu_rel10->csi_rs_resource_config_r10, end) && + pull16(ppReadPackedMsg, &dlsch_pdu_rel10->csi_rs_zero_tx_power_resource_config_bitmap_r10, end) && + pull8(ppReadPackedMsg, &dlsch_pdu_rel10->csi_rs_number_nzp_configuration, end) && + pullarray8(ppReadPackedMsg, dlsch_pdu_rel10->csi_rs_resource_config, NFAPI_MAX_CSI_RS_RESOURCE_CONFIG, dlsch_pdu_rel10->csi_rs_number_nzp_configuration, end) && + pull8(ppReadPackedMsg, &dlsch_pdu_rel10->pdsch_start, end)) ; +} +static uint8_t unpack_dl_config_dlsch_pdu_rel11_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_dl_config_dlsch_pdu_rel11_t* dlsch_pdu_rel11 = (nfapi_dl_config_dlsch_pdu_rel11_t*)tlv; + + return ( pull8(ppReadPackedMsg, &dlsch_pdu_rel11->drms_config_flag, end) && + pull16(ppReadPackedMsg, &dlsch_pdu_rel11->drms_scrambling, end) && + pull8(ppReadPackedMsg, &dlsch_pdu_rel11->csi_config_flag, end) && + pull16(ppReadPackedMsg, &dlsch_pdu_rel11->csi_scrambling, end) && + pull8(ppReadPackedMsg, &dlsch_pdu_rel11->pdsch_re_mapping_flag, end) && + pull8(ppReadPackedMsg, &dlsch_pdu_rel11->pdsch_re_mapping_atenna_ports, end) && + pull8(ppReadPackedMsg, &dlsch_pdu_rel11->pdsch_re_mapping_freq_shift, end)); +} +static uint8_t unpack_dl_config_dlsch_pdu_rel12_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_dl_config_dlsch_pdu_rel12_t* dlsch_pdu_rel12 = (nfapi_dl_config_dlsch_pdu_rel12_t*)tlv; + + return ( pull8(ppReadPackedMsg, &dlsch_pdu_rel12->altcqi_table_r12, end) && + pull8(ppReadPackedMsg, &dlsch_pdu_rel12->maxlayers, end) && + pull8(ppReadPackedMsg, &dlsch_pdu_rel12->n_dl_harq, end)); +} +static uint8_t unpack_dl_config_dlsch_pdu_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_dl_config_dlsch_pdu_rel13_t* dlsch_pdu_rel13 = (nfapi_dl_config_dlsch_pdu_rel13_t*)tlv; + + return ( pull8(ppReadPackedMsg, &dlsch_pdu_rel13->dwpts_symbols, end) && + pull8(ppReadPackedMsg, &dlsch_pdu_rel13->initial_lbt_sf, end) && + pull8(ppReadPackedMsg, &dlsch_pdu_rel13->ue_type, end) && + pull8(ppReadPackedMsg, &dlsch_pdu_rel13->pdsch_payload_type, end) && + pull16(ppReadPackedMsg, &dlsch_pdu_rel13->initial_transmission_sf_io, end) && + pull8(ppReadPackedMsg, &dlsch_pdu_rel13->drms_table_flag, end)); +} + +static uint8_t unpack_dl_config_pch_pdu_rel8_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_dl_config_pch_pdu_rel8_t* pch_pdu_rel8 = (nfapi_dl_config_pch_pdu_rel8_t*)tlv; + + return ( pull16(ppReadPackedMsg, &pch_pdu_rel8->length, end) && + pull16(ppReadPackedMsg, (uint16_t *)&pch_pdu_rel8->pdu_index, end) && + pull16(ppReadPackedMsg, &pch_pdu_rel8->p_rnti, end) && + pull8(ppReadPackedMsg, &pch_pdu_rel8->resource_allocation_type, end) && + pull8(ppReadPackedMsg, &pch_pdu_rel8->virtual_resource_block_assignment_flag, end) && + pull32(ppReadPackedMsg, &pch_pdu_rel8->resource_block_coding, end) && + pull8(ppReadPackedMsg, &pch_pdu_rel8->mcs, end) && + pull8(ppReadPackedMsg, &pch_pdu_rel8->redundancy_version, end) && + pull8(ppReadPackedMsg, &pch_pdu_rel8->number_of_transport_blocks, end) && + pull8(ppReadPackedMsg, &pch_pdu_rel8->transport_block_to_codeword_swap_flag, end) && + pull8(ppReadPackedMsg, &pch_pdu_rel8->transmission_scheme, end) && + pull8(ppReadPackedMsg, &pch_pdu_rel8->number_of_layers, end) && + pull8(ppReadPackedMsg, &pch_pdu_rel8->codebook_index, end) && + pull8(ppReadPackedMsg, &pch_pdu_rel8->ue_category_capacity, end) && + pull8(ppReadPackedMsg, &pch_pdu_rel8->pa, end) && + pull16(ppReadPackedMsg, &pch_pdu_rel8->transmission_power, end) && + pull8(ppReadPackedMsg, &pch_pdu_rel8->nprb, end) && + pull8(ppReadPackedMsg, &pch_pdu_rel8->ngap, end)); +} +static uint8_t unpack_dl_config_pch_pdu_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_dl_config_pch_pdu_rel13_t* pch_pdu_rel13 = (nfapi_dl_config_pch_pdu_rel13_t*)tlv; + + return ( pull8(ppReadPackedMsg, &pch_pdu_rel13->ue_mode, end) && + pull16(ppReadPackedMsg, &pch_pdu_rel13->initial_transmission_sf_io, end)); +} + +static uint8_t unpack_dl_config_prs_pdu_rel9_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_dl_config_prs_pdu_rel9_t* prs_pdu_rel9 = (nfapi_dl_config_prs_pdu_rel9_t*)tlv; + + return ( pull16(ppReadPackedMsg, &prs_pdu_rel9->transmission_power, end) && + pull8(ppReadPackedMsg, &prs_pdu_rel9->prs_bandwidth, end) && + pull8(ppReadPackedMsg, &prs_pdu_rel9->prs_cyclic_prefix_type, end) && + pull8(ppReadPackedMsg, &prs_pdu_rel9->prs_muting, end)); +} + +static uint8_t unpack_dl_config_csi_rs_pdu_rel10_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_dl_config_csi_rs_pdu_rel10_t* csi_rs_pdu_rel10 = (nfapi_dl_config_csi_rs_pdu_rel10_t*)tlv; + + return ( pull8(ppReadPackedMsg, &csi_rs_pdu_rel10->csi_rs_antenna_port_count_r10, end) && + pull8(ppReadPackedMsg, &csi_rs_pdu_rel10->csi_rs_resource_config_r10, end) && + pull16(ppReadPackedMsg, &csi_rs_pdu_rel10->transmission_power, end) && + pull16(ppReadPackedMsg, &csi_rs_pdu_rel10->csi_rs_zero_tx_power_resource_config_bitmap_r10, end) && + pull8(ppReadPackedMsg, &csi_rs_pdu_rel10->csi_rs_number_of_nzp_configuration, end) && + pullarray8(ppReadPackedMsg, csi_rs_pdu_rel10->csi_rs_resource_config, NFAPI_MAX_CSI_RS_RESOURCE_CONFIG, csi_rs_pdu_rel10->csi_rs_number_of_nzp_configuration, end)); +} + +static uint8_t unpack_dl_config_csi_rs_pdu_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_dl_config_csi_rs_pdu_rel13_t* csi_rs_pdu_rel13 = (nfapi_dl_config_csi_rs_pdu_rel13_t*)tlv; + + if (!(pull8(ppReadPackedMsg, &csi_rs_pdu_rel13->csi_rs_class, end) && + pull8(ppReadPackedMsg, &csi_rs_pdu_rel13->cdm_type, end) && + pull8(ppReadPackedMsg, &csi_rs_pdu_rel13->num_bf_vector, end))) + return 0; + + + uint16_t idx =0; + for(idx = 0; idx < csi_rs_pdu_rel13->num_bf_vector; ++idx) + { + if(!(pull8(ppReadPackedMsg, &csi_rs_pdu_rel13->bf_vector[idx].csi_rs_resource_index, end))) + return 0; + NFAPI_TRACE(NFAPI_TRACE_ERROR, "FIXME : HOW TO DECODE BF VALUE \n"); + //pullarray16(ppReadPackedMsg, &csi_rs_pdu_rel13->bf_vector[idx].bf_vector, ??); + } + return 1; +} + +static uint8_t unpack_dl_config_epdcch_params_rel11_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_dl_config_epdcch_parameters_rel11_t* epdcch_params_rel11 = (nfapi_dl_config_epdcch_parameters_rel11_t*)tlv; + + return (pull8(ppReadPackedMsg, &epdcch_params_rel11->epdcch_resource_assignment_flag, end) && + pull16(ppReadPackedMsg, &epdcch_params_rel11->epdcch_id, end) && + pull8(ppReadPackedMsg, &epdcch_params_rel11->epdcch_start_symbol, end) && + pull8(ppReadPackedMsg, &epdcch_params_rel11->epdcch_num_prb, end) && + pullarray8(ppReadPackedMsg, epdcch_params_rel11->epdcch_prb_index, NFAPI_MAX_EPDCCH_PRB, epdcch_params_rel11->epdcch_num_prb, end) && + pull8(ppReadPackedMsg, &epdcch_params_rel11->bf_vector.subband_index, end) && + pull8(ppReadPackedMsg, &epdcch_params_rel11->bf_vector.num_antennas, end) && + pullarray16(ppReadPackedMsg, epdcch_params_rel11->bf_vector.bf_value, NFAPI_MAX_NUM_ANTENNAS, epdcch_params_rel11->bf_vector.num_antennas, end)); +} + +static uint8_t unpack_dl_config_epdcch_params_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_dl_config_epdcch_parameters_rel13_t* epdcch_params_rel13 = (nfapi_dl_config_epdcch_parameters_rel13_t*)tlv; + + return ( pull8(ppReadPackedMsg, &epdcch_params_rel13->dwpts_symbols, end) && + pull8(ppReadPackedMsg, &epdcch_params_rel13->initial_lbt_sf, end)); +} + +static uint8_t unpack_dl_config_mpdcch_pdu_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_dl_config_mpdcch_pdu_rel13_t* mpdcch_params_rel13 = (nfapi_dl_config_mpdcch_pdu_rel13_t*)tlv; + + + return ( pull8(ppReadPackedMsg, &mpdcch_params_rel13->mpdcch_narrow_band, end) && + pull8(ppReadPackedMsg, &mpdcch_params_rel13->number_of_prb_pairs, end) && + pull8(ppReadPackedMsg, &mpdcch_params_rel13->resource_block_assignment, end) && + pull8(ppReadPackedMsg, &mpdcch_params_rel13->mpdcch_tansmission_type, end) && + pull8(ppReadPackedMsg, &mpdcch_params_rel13->start_symbol, end) && + pull8(ppReadPackedMsg, &mpdcch_params_rel13->ecce_index, end) && + pull8(ppReadPackedMsg, &mpdcch_params_rel13->aggregation_level, end) && + pull8(ppReadPackedMsg, &mpdcch_params_rel13->rnti_type, end) && + pull16(ppReadPackedMsg, &mpdcch_params_rel13->rnti, end) && + pull8(ppReadPackedMsg, &mpdcch_params_rel13->ce_mode, end) && + pull16(ppReadPackedMsg, &mpdcch_params_rel13->drms_scrambling_init, end) && + pull16(ppReadPackedMsg, &mpdcch_params_rel13->initial_transmission_sf_io, end) && + pull16(ppReadPackedMsg, &mpdcch_params_rel13->transmission_power, end) && + pull8(ppReadPackedMsg, &mpdcch_params_rel13->dci_format, end) && + pull16(ppReadPackedMsg, &mpdcch_params_rel13->resource_block_coding, end) && + pull8(ppReadPackedMsg, &mpdcch_params_rel13->mcs, end) && + pull8(ppReadPackedMsg, &mpdcch_params_rel13->pdsch_reptition_levels, end) && + pull8(ppReadPackedMsg, &mpdcch_params_rel13->redundancy_version, end) && + pull8(ppReadPackedMsg, &mpdcch_params_rel13->new_data_indicator, end) && + pull8(ppReadPackedMsg, &mpdcch_params_rel13->harq_process, end) && + pull8(ppReadPackedMsg, &mpdcch_params_rel13->tpmi_length, end) && + pull8(ppReadPackedMsg, &mpdcch_params_rel13->tpmi, end) && + pull8(ppReadPackedMsg, &mpdcch_params_rel13->pmi_flag, end) && + pull8(ppReadPackedMsg, &mpdcch_params_rel13->pmi, end) && + pull8(ppReadPackedMsg, &mpdcch_params_rel13->harq_resource_offset, end) && + pull8(ppReadPackedMsg, &mpdcch_params_rel13->dci_subframe_repetition_number, end) && + pull8(ppReadPackedMsg, &mpdcch_params_rel13->tpc, end) && + pull8(ppReadPackedMsg, &mpdcch_params_rel13->downlink_assignment_index_length, end) && + pull8(ppReadPackedMsg, &mpdcch_params_rel13->downlink_assignment_index, end) && + pull8(ppReadPackedMsg, &mpdcch_params_rel13->allocate_prach_flag, end) && + pull8(ppReadPackedMsg, &mpdcch_params_rel13->preamble_index, end) && + pull8(ppReadPackedMsg, &mpdcch_params_rel13->prach_mask_index, end) && + pull8(ppReadPackedMsg, &mpdcch_params_rel13->starting_ce_level, end) && + pull8(ppReadPackedMsg, &mpdcch_params_rel13->srs_request, end) && + pull8(ppReadPackedMsg, &mpdcch_params_rel13->antenna_ports_and_scrambling_identity_flag, end) && + pull8(ppReadPackedMsg, &mpdcch_params_rel13->antenna_ports_and_scrambling_identity, end) && + pull8(ppReadPackedMsg, &mpdcch_params_rel13->frequency_hopping_enabled_flag, end) && + pull8(ppReadPackedMsg, &mpdcch_params_rel13->paging_direct_indication_differentiation_flag, end) && + pull8(ppReadPackedMsg, &mpdcch_params_rel13->direct_indication, end) && + pull8(ppReadPackedMsg, &mpdcch_params_rel13->total_dci_length_including_padding, end) && + pull8(ppReadPackedMsg, &mpdcch_params_rel13->number_of_tx_antenna_ports, end) && + pullarray16(ppReadPackedMsg, mpdcch_params_rel13->precoding_value, NFAPI_MAX_TX_PHYSICAL_ANTENNA_PORTS, mpdcch_params_rel13->number_of_tx_antenna_ports, end)); +} + + +static uint8_t unpack_dl_config_nbch_pdu_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_dl_config_nbch_pdu_rel13_t* nbch_params_rel13 = (nfapi_dl_config_nbch_pdu_rel13_t*)tlv; + + return ( pull16(ppReadPackedMsg, &nbch_params_rel13->length, end) && + pull16(ppReadPackedMsg, (uint16_t *)&nbch_params_rel13->pdu_index, end) && + pull16(ppReadPackedMsg, &nbch_params_rel13->transmission_power, end) && + pull16(ppReadPackedMsg, &nbch_params_rel13->hyper_sfn_2_lsbs, end)); +} + +static uint8_t unpack_dl_config_npdcch_pdu_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_dl_config_npdcch_pdu_rel13_t* npdcch_params_rel13 = (nfapi_dl_config_npdcch_pdu_rel13_t*)tlv; + + return ( pull16(ppReadPackedMsg, &npdcch_params_rel13->length, end) && + pull16(ppReadPackedMsg, (uint16_t *)&npdcch_params_rel13->pdu_index, end) && + pull8(ppReadPackedMsg, &npdcch_params_rel13->ncce_index, end) && + pull8(ppReadPackedMsg, &npdcch_params_rel13->aggregation_level, end) && + pull8(ppReadPackedMsg, &npdcch_params_rel13->start_symbol, end) && + pull8(ppReadPackedMsg, &npdcch_params_rel13->rnti_type, end) && + pull16(ppReadPackedMsg, &npdcch_params_rel13->rnti, end) && + pull8(ppReadPackedMsg, &npdcch_params_rel13->scrambling_reinitialization_batch_index, end) && + pull8(ppReadPackedMsg, &npdcch_params_rel13->nrs_antenna_ports_assumed_by_the_ue, end) && + pull8(ppReadPackedMsg, &npdcch_params_rel13->dci_format, end) && + pull8(ppReadPackedMsg, &npdcch_params_rel13->scheduling_delay, end) && + pull8(ppReadPackedMsg, &npdcch_params_rel13->resource_assignment, end) && + pull8(ppReadPackedMsg, &npdcch_params_rel13->repetition_number, end) && + pull8(ppReadPackedMsg, &npdcch_params_rel13->mcs, end) && + pull8(ppReadPackedMsg, &npdcch_params_rel13->new_data_indicator, end) && + pull8(ppReadPackedMsg, &npdcch_params_rel13->harq_ack_resource, end) && + pull8(ppReadPackedMsg, &npdcch_params_rel13->npdcch_order_indication, end) && + pull8(ppReadPackedMsg, &npdcch_params_rel13->starting_number_of_nprach_repetitions, end) && + pull8(ppReadPackedMsg, &npdcch_params_rel13->subcarrier_indication_of_nprach, end) && + pull8(ppReadPackedMsg, &npdcch_params_rel13->paging_direct_indication_differentation_flag, end) && + pull8(ppReadPackedMsg, &npdcch_params_rel13->direct_indication, end) && + pull8(ppReadPackedMsg, &npdcch_params_rel13->dci_subframe_repetition_number, end) && + pull8(ppReadPackedMsg, &npdcch_params_rel13->total_dci_length_including_padding, end)); +} + +static uint8_t unpack_dl_config_ndlsch_pdu_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_dl_config_ndlsch_pdu_rel13_t* ndlsch_params_rel13 = (nfapi_dl_config_ndlsch_pdu_rel13_t*)tlv; + + return ( pull16(ppReadPackedMsg, &ndlsch_params_rel13->length, end) && + pull16(ppReadPackedMsg, (uint16_t *)&ndlsch_params_rel13->pdu_index, end) && + pull8(ppReadPackedMsg, &ndlsch_params_rel13->start_symbol, end) && + pull8(ppReadPackedMsg, &ndlsch_params_rel13->rnti_type, end) && + pull16(ppReadPackedMsg, &ndlsch_params_rel13->rnti, end) && + pull16(ppReadPackedMsg, &ndlsch_params_rel13->resource_assignment, end) && + pull16(ppReadPackedMsg, &ndlsch_params_rel13->repetition_number, end) && + pull8(ppReadPackedMsg, &ndlsch_params_rel13->modulation, end) && + pull8(ppReadPackedMsg, &ndlsch_params_rel13->number_of_subframes_for_resource_assignment, end) && + pull8(ppReadPackedMsg, &ndlsch_params_rel13->scrambling_sequence_initialization_cinit, end) && + pull16(ppReadPackedMsg, &ndlsch_params_rel13->sf_idx, end) && + pull8(ppReadPackedMsg, &ndlsch_params_rel13->nrs_antenna_ports_assumed_by_the_ue, end)); +} + + +static uint8_t unpack_dl_tti_request_body_value(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg) +{ + nfapi_nr_dl_tti_request_pdu_t* value = (nfapi_nr_dl_tti_request_pdu_t*)msg; + + if(!(pull16(ppReadPackedMsg, &value->PDUSize, end) && + pull16(ppReadPackedMsg, &value->PDUType, end) )) + return 0; + + + // first match the pdu type, then call the respective function + switch(value->PDUType) + { + case NFAPI_NR_DL_TTI_CSI_RS_PDU_TYPE: + { + if(!(unpack_dl_tti_csi_rs_pdu_rel15_value(&value->csi_rs_pdu.csi_rs_pdu_rel15,ppReadPackedMsg,end))) + return 0; + } + break; + + case NFAPI_NR_DL_TTI_PDCCH_PDU_TYPE: + { + if(!(unpack_dl_tti_pdcch_pdu_rel15_value(&value->pdcch_pdu.pdcch_pdu_rel15,ppReadPackedMsg,end))) + return 0; + } + break; + case NFAPI_NR_DL_TTI_PDSCH_PDU_TYPE: + { + if(!(unpack_dl_tti_pdsch_pdu_rel15_value(&value->pdsch_pdu.pdsch_pdu_rel15,ppReadPackedMsg,end))) + return 0; + } + break; + case NFAPI_NR_DL_TTI_SSB_PDU_TYPE: + { + if(!(unpack_dl_tti_ssb_pdu_rel15_value(&value->ssb_pdu.ssb_pdu_rel15,ppReadPackedMsg,end))) + return 0; + } + break; + + default: + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "FIXME : Invalid DL_TTI pdu type %d \n", value->PDUType ); + } + break; + } + + return 1; +} + + + + +static uint8_t unpack_dl_config_request_body_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) +{ + nfapi_dl_config_request_body_t* value = (nfapi_dl_config_request_body_t*)tlv; + + if(!(pull8(ppReadPackedMsg, &value->number_pdcch_ofdm_symbols, end) && + pull8(ppReadPackedMsg, &value->number_dci, end) && + pull16(ppReadPackedMsg, &value->number_pdu, end) && + pull8(ppReadPackedMsg, &value->number_pdsch_rnti, end) && + pull16(ppReadPackedMsg, &value->transmission_power_pcfich, end))) + return 0; + + if(value->number_pdu > NFAPI_DL_CONFIG_MAX_PDU) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s number of dl config pdu's exceed maxium (count:%d max:%d)\n", __FUNCTION__, value->number_pdu, NFAPI_DL_CONFIG_MAX_PDU); + return 0; + } + + if(value->number_pdu) + { + value->dl_config_pdu_list = (nfapi_dl_config_request_pdu_t*)nfapi_p7_allocate(sizeof(nfapi_dl_config_request_pdu_t) * value->number_pdu, config); + if(value->dl_config_pdu_list == NULL) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s failed to allocate dl config pdu list (count:%d)\n", __FUNCTION__, value->number_pdu); + return 0; + } + } + else + { + value->dl_config_pdu_list = 0; + } + + uint16_t i; + uint16_t total_number_of_pdus = value->number_pdu; + for(i = 0; i < total_number_of_pdus; ++i) + { + nfapi_dl_config_request_pdu_t* pdu = &(value->dl_config_pdu_list[i]); + + if(!(pull8(ppReadPackedMsg, &pdu->pdu_type, end) && + pull8(ppReadPackedMsg, &pdu->pdu_size, end))) + return 0; + + uint8_t *packedPduEnd = (*ppReadPackedMsg) + pdu->pdu_size - 2; + + if(packedPduEnd > end) + { + // pdu end of beyond buffer end + return 0; + } + + switch(pdu->pdu_type) + { + case NFAPI_DL_CONFIG_DCI_DL_PDU_TYPE: + { + unpack_tlv_t unpack_fns[] = + { + { NFAPI_DL_CONFIG_REQUEST_DCI_DL_PDU_REL8_TAG, &pdu->dci_dl_pdu.dci_dl_pdu_rel8, &unpack_dl_config_dci_dl_pdu_rel8_value}, + { NFAPI_DL_CONFIG_REQUEST_DCI_DL_PDU_REL9_TAG, &pdu->dci_dl_pdu.dci_dl_pdu_rel9, &unpack_dl_config_dci_dl_pdu_rel9_value}, + { NFAPI_DL_CONFIG_REQUEST_DCI_DL_PDU_REL10_TAG, &pdu->dci_dl_pdu.dci_dl_pdu_rel10, &unpack_dl_config_dci_dl_pdu_rel10_value}, + { NFAPI_DL_CONFIG_REQUEST_DCI_DL_PDU_REL11_TAG, &pdu->dci_dl_pdu.dci_dl_pdu_rel11, &unpack_dl_config_dci_dl_pdu_rel11_value}, + { NFAPI_DL_CONFIG_REQUEST_DCI_DL_PDU_REL12_TAG, &pdu->dci_dl_pdu.dci_dl_pdu_rel12, &unpack_dl_config_dci_dl_pdu_rel12_value}, + { NFAPI_DL_CONFIG_REQUEST_DCI_DL_PDU_REL13_TAG, &pdu->dci_dl_pdu.dci_dl_pdu_rel13, &unpack_dl_config_dci_dl_pdu_rel13_value}, + }; + + unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); + } + break; + case NFAPI_DL_CONFIG_BCH_PDU_TYPE: + { + unpack_tlv_t unpack_fns[] = + { + { NFAPI_DL_CONFIG_REQUEST_BCH_PDU_REL8_TAG, &pdu->bch_pdu.bch_pdu_rel8, &unpack_dl_config_bch_pdu_rel8_value}, + }; + + unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); + } + break; + case NFAPI_DL_CONFIG_MCH_PDU_TYPE: + { + unpack_tlv_t unpack_fns[] = + { + { NFAPI_DL_CONFIG_REQUEST_MCH_PDU_REL8_TAG, &pdu->mch_pdu.mch_pdu_rel8, &unpack_dl_config_mch_pdu_rel8_value}, + }; + + unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); + } + break; + case NFAPI_DL_CONFIG_DLSCH_PDU_TYPE: + { + unpack_tlv_t unpack_fns[] = + { + { NFAPI_DL_CONFIG_REQUEST_DLSCH_PDU_REL8_TAG, &pdu->dlsch_pdu.dlsch_pdu_rel8, &unpack_dl_config_dlsch_pdu_rel8_value}, + { NFAPI_DL_CONFIG_REQUEST_DLSCH_PDU_REL9_TAG, &pdu->dlsch_pdu.dlsch_pdu_rel9, &unpack_dl_config_dlsch_pdu_rel9_value}, + { NFAPI_DL_CONFIG_REQUEST_DLSCH_PDU_REL10_TAG, &pdu->dlsch_pdu.dlsch_pdu_rel10, &unpack_dl_config_dlsch_pdu_rel10_value}, + { NFAPI_DL_CONFIG_REQUEST_DLSCH_PDU_REL11_TAG, &pdu->dlsch_pdu.dlsch_pdu_rel11, &unpack_dl_config_dlsch_pdu_rel11_value}, + { NFAPI_DL_CONFIG_REQUEST_DLSCH_PDU_REL12_TAG, &pdu->dlsch_pdu.dlsch_pdu_rel12, &unpack_dl_config_dlsch_pdu_rel12_value}, + { NFAPI_DL_CONFIG_REQUEST_DLSCH_PDU_REL13_TAG, &pdu->dlsch_pdu.dlsch_pdu_rel13, &unpack_dl_config_dlsch_pdu_rel13_value}, + }; + + unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); + } + break; + case NFAPI_DL_CONFIG_PCH_PDU_TYPE: + { + unpack_tlv_t unpack_fns[] = + { + { NFAPI_DL_CONFIG_REQUEST_PCH_PDU_REL8_TAG, &pdu->pch_pdu.pch_pdu_rel8, &unpack_dl_config_pch_pdu_rel8_value}, + { NFAPI_DL_CONFIG_REQUEST_PCH_PDU_REL13_TAG, &pdu->pch_pdu.pch_pdu_rel13, &unpack_dl_config_pch_pdu_rel13_value}, + }; + + unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); + } + break; + case NFAPI_DL_CONFIG_PRS_PDU_TYPE: + { + unpack_tlv_t unpack_fns[] = + { + { NFAPI_DL_CONFIG_REQUEST_PRS_PDU_REL9_TAG, &pdu->prs_pdu.prs_pdu_rel9, &unpack_dl_config_prs_pdu_rel9_value}, + }; + + unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); + } + break; + case NFAPI_DL_CONFIG_CSI_RS_PDU_TYPE: + { + unpack_tlv_t unpack_fns[] = + { + { NFAPI_DL_CONFIG_REQUEST_CSI_RS_PDU_REL10_TAG, &pdu->csi_rs_pdu.csi_rs_pdu_rel10, &unpack_dl_config_csi_rs_pdu_rel10_value}, + { NFAPI_DL_CONFIG_REQUEST_CSI_RS_PDU_REL13_TAG, &pdu->csi_rs_pdu.csi_rs_pdu_rel13, &unpack_dl_config_csi_rs_pdu_rel13_value}, + }; + + unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); + } + break; + case NFAPI_DL_CONFIG_EPDCCH_DL_PDU_TYPE: + { + unpack_tlv_t unpack_fns[] = + { + { NFAPI_DL_CONFIG_REQUEST_EPDCCH_PDU_REL8_TAG, &pdu->epdcch_pdu.epdcch_pdu_rel8, &unpack_dl_config_dci_dl_pdu_rel8_value}, + { NFAPI_DL_CONFIG_REQUEST_EPDCCH_PDU_REL9_TAG, &pdu->epdcch_pdu.epdcch_pdu_rel9, &unpack_dl_config_dci_dl_pdu_rel9_value}, + { NFAPI_DL_CONFIG_REQUEST_EPDCCH_PDU_REL10_TAG, &pdu->epdcch_pdu.epdcch_pdu_rel10, &unpack_dl_config_dci_dl_pdu_rel10_value}, + { NFAPI_DL_CONFIG_REQUEST_EPDCCH_PDU_REL11_TAG, &pdu->epdcch_pdu.epdcch_pdu_rel11, &unpack_dl_config_dci_dl_pdu_rel11_value}, + { NFAPI_DL_CONFIG_REQUEST_EPDCCH_PDU_REL12_TAG, &pdu->epdcch_pdu.epdcch_pdu_rel12, &unpack_dl_config_dci_dl_pdu_rel12_value}, + { NFAPI_DL_CONFIG_REQUEST_EPDCCH_PDU_REL13_TAG, &pdu->epdcch_pdu.epdcch_pdu_rel13, &unpack_dl_config_dci_dl_pdu_rel13_value}, + { NFAPI_DL_CONFIG_REQUEST_EPDCCH_PARAM_REL11_TAG, &pdu->epdcch_pdu.epdcch_params_rel11, &unpack_dl_config_epdcch_params_rel11_value}, + { NFAPI_DL_CONFIG_REQUEST_EPDCCH_PARAM_REL13_TAG, &pdu->epdcch_pdu.epdcch_params_rel13, &unpack_dl_config_epdcch_params_rel13_value}, + }; + + unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); + } + break; + case NFAPI_DL_CONFIG_MPDCCH_PDU_TYPE: + { + unpack_tlv_t unpack_fns[] = + { + { NFAPI_DL_CONFIG_REQUEST_MPDCCH_PDU_REL13_TAG, &pdu->mpdcch_pdu.mpdcch_pdu_rel13, &unpack_dl_config_mpdcch_pdu_rel13_value}, + }; + + unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); + } + break; + case NFAPI_DL_CONFIG_NBCH_PDU_TYPE: + { + unpack_tlv_t unpack_fns[] = + { + { NFAPI_DL_CONFIG_REQUEST_NBCH_PDU_REL13_TAG, &pdu->nbch_pdu.nbch_pdu_rel13, &unpack_dl_config_nbch_pdu_rel13_value}, + }; + + unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); + } + break; + case NFAPI_DL_CONFIG_NPDCCH_PDU_TYPE: + { + unpack_tlv_t unpack_fns[] = + { + { NFAPI_DL_CONFIG_REQUEST_NPDCCH_PDU_REL13_TAG, &pdu->npdcch_pdu.npdcch_pdu_rel13, &unpack_dl_config_npdcch_pdu_rel13_value}, + }; + + unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); + + } + break; + case NFAPI_DL_CONFIG_NDLSCH_PDU_TYPE: + { + unpack_tlv_t unpack_fns[] = + { + { NFAPI_DL_CONFIG_REQUEST_NDLSCH_PDU_REL13_TAG, &pdu->ndlsch_pdu.ndlsch_pdu_rel13, &unpack_dl_config_ndlsch_pdu_rel13_value}, + }; + + unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); + + } + break; + default: + // Need to log an error + break; + } + } + + return 1; +} + + +static uint8_t unpack_dl_tti_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config) +{ + nfapi_nr_dl_tti_request_t *pNfapiMsg = (nfapi_nr_dl_tti_request_t*)msg; + + if (!(pull16(ppReadPackedMsg,&pNfapiMsg->SFN, end) && + pull16(ppReadPackedMsg, &pNfapiMsg->Slot, end) && + pull8(ppReadPackedMsg, &pNfapiMsg->dl_tti_request_body.nGroup, end) && + pull8(ppReadPackedMsg, &pNfapiMsg->dl_tti_request_body.nPDUs, end) && + pullarray8(ppReadPackedMsg,pNfapiMsg->dl_tti_request_body.nUe ,256,pNfapiMsg->dl_tti_request_body.nGroup, end) + //pusharray8(pNfapiMsg->PduIdx[0] ,256,256, ppWritePackedMsg, end) + )) + return 0; + + int arr[12]; + for(int i=0;idl_tti_request_body.nGroup;i++) + { + for(int j=0;jdl_tti_request_body.nUe[i];j++) + { + arr[j] = pNfapiMsg->dl_tti_request_body.PduIdx[i][j]; + } + if(!(pullarrays32(ppReadPackedMsg,arr,12,pNfapiMsg->dl_tti_request_body.nUe[i], end))) + return 0; + } + + for(int i=0;idl_tti_request_body.nPDUs;i++) + { + if(!unpack_dl_tti_request_body_value(ppReadPackedMsg, end, &pNfapiMsg->dl_tti_request_body.dl_tti_pdu_list[i])) + return 0; + } + +return 1; +} + + +static uint8_t unpack_ul_tti_request_prach_pdu(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_nr_prach_pdu_t* prach_pdu = (nfapi_nr_prach_pdu_t*)tlv; + + return( + pull16(ppReadPackedMsg, &prach_pdu->phys_cell_id, end) && + pull8(ppReadPackedMsg, &prach_pdu->num_prach_ocas, end) && + pull8(ppReadPackedMsg, &prach_pdu->prach_format, end) && + pull8(ppReadPackedMsg, &prach_pdu->num_ra, end) && + pull8(ppReadPackedMsg, &prach_pdu->prach_start_symbol, end) && + pull16(ppReadPackedMsg, &prach_pdu->num_cs, end) + // TODO: ignoring beamforming tlv for now + ); +} + + +static uint8_t unpack_ul_tti_request_pucch_pdu(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_nr_pucch_pdu_t* pucch_pdu = (nfapi_nr_pucch_pdu_t*)tlv; + + return( + pull16(ppReadPackedMsg, &pucch_pdu->rnti, end) && + pull32(ppReadPackedMsg, &pucch_pdu->handle, end) && + pull16(ppReadPackedMsg, &pucch_pdu->bwp_size, end) && + pull16(ppReadPackedMsg, &pucch_pdu->bwp_start, end) && + pull8(ppReadPackedMsg, &pucch_pdu->subcarrier_spacing, end) && + pull8(ppReadPackedMsg, &pucch_pdu->cyclic_prefix, end) && + pull8(ppReadPackedMsg, &pucch_pdu->format_type, end) && + pull8(ppReadPackedMsg, &pucch_pdu->multi_slot_tx_indicator, end) && + pull16(ppReadPackedMsg, &pucch_pdu->prb_start, end) && + pull16(ppReadPackedMsg, &pucch_pdu->prb_size, end) && + pull8(ppReadPackedMsg, &pucch_pdu->start_symbol_index, end) && + pull8(ppReadPackedMsg, &pucch_pdu->nr_of_symbols, end) && + pull8(ppReadPackedMsg, &pucch_pdu->freq_hop_flag, end) && + pull16(ppReadPackedMsg, &pucch_pdu->second_hop_prb, end) && + pull8(ppReadPackedMsg, &pucch_pdu->group_hop_flag, end) && + pull8(ppReadPackedMsg, &pucch_pdu->sequence_hop_flag, end) && + pull16(ppReadPackedMsg, &pucch_pdu->hopping_id, end) && + pull16(ppReadPackedMsg, &pucch_pdu->initial_cyclic_shift, end) && + pull16(ppReadPackedMsg, &pucch_pdu->data_scrambling_id, end) && + pull8(ppReadPackedMsg, &pucch_pdu->time_domain_occ_idx, end) && + pull8(ppReadPackedMsg, &pucch_pdu->pre_dft_occ_idx, end) && + pull8(ppReadPackedMsg, &pucch_pdu->pre_dft_occ_len, end) && + pull8(ppReadPackedMsg, &pucch_pdu->add_dmrs_flag, end) && + pull16(ppReadPackedMsg, &pucch_pdu->dmrs_scrambling_id, end) && + pull8(ppReadPackedMsg, &pucch_pdu->dmrs_cyclic_shift, end) && + pull8(ppReadPackedMsg, &pucch_pdu->sr_flag, end) && + pull8(ppReadPackedMsg, &pucch_pdu->bit_len_harq, end) && + pull16(ppReadPackedMsg, &pucch_pdu->bit_len_csi_part1, end) && + pull16(ppReadPackedMsg, &pucch_pdu->bit_len_csi_part2, end) + // TODO: ignoring beamforming tlv for now + ); +} + + +static uint8_t unpack_ul_tti_request_pusch_pdu(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_nr_pusch_pdu_t* pusch_pdu = (nfapi_nr_pusch_pdu_t*)tlv; + + if (!( + pull16(ppReadPackedMsg, &pusch_pdu->pdu_bit_map, end) && + pull16(ppReadPackedMsg, &pusch_pdu->rnti, end) && + pull32(ppReadPackedMsg, &pusch_pdu->handle, end) && + pull16(ppReadPackedMsg, &pusch_pdu->bwp_size, end) && + pull16(ppReadPackedMsg, &pusch_pdu->bwp_start, end) && + pull8(ppReadPackedMsg, &pusch_pdu->subcarrier_spacing, end) && + pull8(ppReadPackedMsg, &pusch_pdu->cyclic_prefix, end) && + pull16(ppReadPackedMsg, &pusch_pdu->target_code_rate, end) && + pull8(ppReadPackedMsg, &pusch_pdu->qam_mod_order, end) && + pull8(ppReadPackedMsg, &pusch_pdu->mcs_index, end) && + pull8(ppReadPackedMsg, &pusch_pdu->mcs_table, end) && + pull8(ppReadPackedMsg, &pusch_pdu->transform_precoding, end) && + pull16(ppReadPackedMsg, &pusch_pdu->data_scrambling_id, end) && + pull8(ppReadPackedMsg, &pusch_pdu->nrOfLayers, end) && + pull16(ppReadPackedMsg, &pusch_pdu->ul_dmrs_symb_pos, end) && + pull8(ppReadPackedMsg, &pusch_pdu->dmrs_config_type, end) && + pull16(ppReadPackedMsg, &pusch_pdu->ul_dmrs_scrambling_id, end) && + pull8(ppReadPackedMsg, &pusch_pdu->scid, end) && + pull8(ppReadPackedMsg, &pusch_pdu->num_dmrs_cdm_grps_no_data, end) && + pull16(ppReadPackedMsg, &pusch_pdu->dmrs_ports, end) && + pull8(ppReadPackedMsg, &pusch_pdu->resource_alloc, end) && + pull8(ppReadPackedMsg, &pusch_pdu->resource_alloc,end) && + pull16(ppReadPackedMsg, &pusch_pdu->dmrs_ports, end) && + pull16(ppReadPackedMsg, &pusch_pdu->rb_start, end) && + pull16(ppReadPackedMsg, &pusch_pdu->rb_size, end) && + pull8(ppReadPackedMsg, &pusch_pdu->vrb_to_prb_mapping, end) && + pull8(ppReadPackedMsg, &pusch_pdu->frequency_hopping, end) && + pull16(ppReadPackedMsg, &pusch_pdu->tx_direct_current_location, end) && + pull8(ppReadPackedMsg, &pusch_pdu->uplink_frequency_shift_7p5khz, end) && + pull8(ppReadPackedMsg, &pusch_pdu->start_symbol_index, end) && + pull8(ppReadPackedMsg, &pusch_pdu->nr_of_symbols, end) + // TODO: ignoring beamforming tlv for now + )) + return 0; + + + //Pack Optional Data only included if indicated in pduBitmap + switch(pusch_pdu->pdu_bit_map){ + case PUSCH_PDU_BITMAP_PUSCH_DATA: + { + // pack optional TLVs + return( + pull8(ppReadPackedMsg, &pusch_pdu->pusch_data.rv_index, end) && + pull8(ppReadPackedMsg, &pusch_pdu->pusch_data.harq_process_id, end) && + pull32(ppReadPackedMsg, &pusch_pdu->pusch_data.tb_size, end) && + pull16(ppReadPackedMsg, &pusch_pdu->pusch_data.num_cb, end) && + pullarray8(ppReadPackedMsg, pusch_pdu->pusch_data.cb_present_and_position,1,1,end) + ); + } + break; + + case PUSCH_PDU_BITMAP_PUSCH_UCI: + { + return( + pull16(ppReadPackedMsg, &pusch_pdu->pusch_uci.harq_ack_bit_length, end) && + pull16(ppReadPackedMsg, &pusch_pdu->pusch_uci.csi_part1_bit_length, end) && + pull16(ppReadPackedMsg, &pusch_pdu->pusch_uci.csi_part2_bit_length, end) && + pull8(ppReadPackedMsg, &pusch_pdu->pusch_uci.alpha_scaling, end) && + pull8(ppReadPackedMsg, &pusch_pdu->pusch_uci.beta_offset_harq_ack, end) && + pull8(ppReadPackedMsg, &pusch_pdu->pusch_uci.beta_offset_csi1, end) && + pull8(ppReadPackedMsg, &pusch_pdu->pusch_uci.beta_offset_csi2, end) + ); + } + break; + + case PUSCH_PDU_BITMAP_PUSCH_PTRS: + { + return( + pull8(ppReadPackedMsg, &pusch_pdu->pusch_ptrs.num_ptrs_ports, end) && + pull8(ppReadPackedMsg, &pusch_pdu->pusch_ptrs.ptrs_ports_list->ptrs_dmrs_port, end) && ++ pull16(ppReadPackedMsg, &pusch_pdu->pusch_ptrs.ptrs_ports_list->ptrs_port_index, end) && ++ pull8(ppReadPackedMsg, &pusch_pdu->pusch_ptrs.ptrs_ports_list->ptrs_re_offset, end) && + pull8(ppReadPackedMsg, &pusch_pdu->pusch_ptrs.ptrs_time_density, end) && + pull8(ppReadPackedMsg, &pusch_pdu->pusch_ptrs.ptrs_freq_density, end) && + pull8(ppReadPackedMsg, &pusch_pdu->pusch_ptrs.ul_ptrs_power, end) + ); + } + break; + + case PUSCH_PDU_BITMAP_DFTS_OFDM: + { + return( + pull8(ppReadPackedMsg, &pusch_pdu->dfts_ofdm.low_papr_group_number, end) && + pull16(ppReadPackedMsg, &pusch_pdu->dfts_ofdm.low_papr_sequence_number, end) && + pull8(ppReadPackedMsg, &pusch_pdu->dfts_ofdm.ul_ptrs_sample_density, end) && + pull8(ppReadPackedMsg, &pusch_pdu->dfts_ofdm.ul_ptrs_time_density_transform_precoding, end) + ); + } + break; + + default: + { + NFAPI_TRACE(NFAPI_TRACE_INFO, "Invalid pdu bitmap %d \n", pusch_pdu->pdu_bit_map ); + } + } + + return 1; +} + + +static uint8_t unpack_ul_tti_request_srs_pdu(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_nr_srs_pdu_t* srs_pdu = (nfapi_nr_srs_pdu_t*)tlv; + + return( + pull16(ppReadPackedMsg, &srs_pdu->rnti, end) && + pull32(ppReadPackedMsg, &srs_pdu->handle, end) && + pull16(ppReadPackedMsg, &srs_pdu->bwp_size, end) && + pull16(ppReadPackedMsg, &srs_pdu->bwp_start, end) && + pull8(ppReadPackedMsg, &srs_pdu->subcarrier_spacing, end) && + pull8(ppReadPackedMsg, &srs_pdu->cyclic_prefix, end) && + pull8(ppReadPackedMsg, &srs_pdu->num_ant_ports, end) && + pull8(ppReadPackedMsg, &srs_pdu->num_symbols, end) && + pull8(ppReadPackedMsg, &srs_pdu->num_repetitions, end) && + pull8(ppReadPackedMsg, &srs_pdu->time_start_position, end) && + pull8(ppReadPackedMsg, &srs_pdu->config_index, end) && + pull16(ppReadPackedMsg, &srs_pdu->sequence_id, end) && + pull8(ppReadPackedMsg, &srs_pdu->bandwidth_index, end) && + pull8(ppReadPackedMsg, &srs_pdu->comb_size, end) && + pull8(ppReadPackedMsg, &srs_pdu->comb_offset, end) && + pull8(ppReadPackedMsg, &srs_pdu->cyclic_shift, end) && + pull8(ppReadPackedMsg, &srs_pdu->frequency_position, end) && + pull8(ppReadPackedMsg, &srs_pdu->frequency_shift, end) && + pull8(ppReadPackedMsg, &srs_pdu->frequency_hopping, end) && + pull8(ppReadPackedMsg, &srs_pdu->group_or_sequence_hopping, end) && + pull8(ppReadPackedMsg, &srs_pdu->resource_type, end) && + pull16(ppReadPackedMsg, &srs_pdu->t_srs, end) && + pull16(ppReadPackedMsg, &srs_pdu->t_offset, end) + // TODO: ignoring beamforming tlv for now + ); +} + + +static uint8_t unpack_ul_tti_pdu_list_value(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg) +{ + nfapi_nr_ul_tti_request_number_of_pdus_t* pNfapiMsg = (nfapi_nr_ul_tti_request_number_of_pdus_t*)msg; + + if(!(pull16(ppReadPackedMsg, &pNfapiMsg->pdu_size, end) && + pull16(ppReadPackedMsg, &pNfapiMsg->pdu_type, end) )) + return 0; + + + // first natch the pdu type, then call the respective function + switch(pNfapiMsg->pdu_type) + { + + case NFAPI_NR_UL_CONFIG_PRACH_PDU_TYPE: + { + if(!unpack_ul_tti_request_prach_pdu(&pNfapiMsg->prach_pdu, ppReadPackedMsg, end)) + return 0; + } + break; + + case NFAPI_NR_UL_CONFIG_PUCCH_PDU_TYPE: + { + if(!unpack_ul_tti_request_pucch_pdu(&pNfapiMsg->pucch_pdu, ppReadPackedMsg, end)) + return 0; + } + break; + + case NFAPI_NR_UL_CONFIG_PUSCH_PDU_TYPE: + { + if(!unpack_ul_tti_request_pusch_pdu(&pNfapiMsg->pusch_pdu, ppReadPackedMsg, end)) + return 0; + } + break; + + case NFAPI_NR_UL_CONFIG_SRS_PDU_TYPE: + { + if(!unpack_ul_tti_request_srs_pdu(&pNfapiMsg->srs_pdu, ppReadPackedMsg, end)) + return 0; + } + break; + + default: + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "FIXME : Invalid UL_TTI pdu type %d \n", pNfapiMsg->pdu_type ); + } + break; + + + } + + return 1; +} + + +static uint8_t unpack_ul_tti_groups_list_value(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg) +{ + nfapi_nr_ul_tti_request_number_of_groups_t* pNfapiMsg = (nfapi_nr_ul_tti_request_number_of_groups_t*)msg; + + if(!pull8(ppReadPackedMsg, &pNfapiMsg->n_ue, end)) + return 0; + for (int i = 0; i < pNfapiMsg->n_ue; i++) + { + if(!pull8(ppReadPackedMsg, &pNfapiMsg->ue_list[i].pdu_idx ,end) ) + return 0; + } + return 1; +} + + +static uint8_t unpack_ul_tti_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config) +{ + nfapi_nr_ul_tti_request_t *pNfapiMsg = (nfapi_nr_ul_tti_request_t*)msg; + + if (!( + pull16(ppReadPackedMsg, &pNfapiMsg->SFN, end) && + pull16(ppReadPackedMsg, &pNfapiMsg->Slot, end) && + pull8(ppReadPackedMsg, &pNfapiMsg->n_pdus, end) && + pull8(ppReadPackedMsg, &pNfapiMsg->n_group, end) && + pull8(ppReadPackedMsg, &pNfapiMsg->rach_present, end) && + pull8(ppReadPackedMsg, &pNfapiMsg->n_ulcch, end) && + pull8(ppReadPackedMsg, &pNfapiMsg->n_ulsch, end) )) + return 0; + + for(int i=0; i< pNfapiMsg->n_pdus; i++) + { + if (!unpack_ul_tti_pdu_list_value(ppReadPackedMsg, end, &pNfapiMsg->pdus_list[i])) + return 0; + } + + for(int i=0; i< pNfapiMsg->n_group; i++) + { + if (!unpack_ul_tti_groups_list_value(ppReadPackedMsg, end, &pNfapiMsg->groups_list[i])) + return 0; + } + + return 1; +} + + + +static uint8_t unpack_dl_config_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config) +{ + nfapi_dl_config_request_t *pNfapiMsg = (nfapi_dl_config_request_t*)msg; + + unpack_p7_tlv_t unpack_fns[] = + { + { NFAPI_DL_CONFIG_REQUEST_BODY_TAG, &pNfapiMsg->dl_config_request_body, &unpack_dl_config_request_body_value}, + }; + + return ( pull16(ppReadPackedMsg, &pNfapiMsg->sfn_sf, end) && + unpack_p7_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); +} + +static uint8_t unpack_ul_config_ulsch_pdu_rel8_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + + + + nfapi_ul_config_ulsch_pdu_rel8_t* ulsch_pdu_rel8 = (nfapi_ul_config_ulsch_pdu_rel8_t*)tlv; + + return (pull32(ppReadPackedMsg, &ulsch_pdu_rel8->handle, end) && + pull16(ppReadPackedMsg, &ulsch_pdu_rel8->size, end) && + pull16(ppReadPackedMsg, &ulsch_pdu_rel8->rnti, end) && + pull8(ppReadPackedMsg, &ulsch_pdu_rel8->resource_block_start, end) && + pull8(ppReadPackedMsg, &ulsch_pdu_rel8->number_of_resource_blocks, end) && + pull8(ppReadPackedMsg, &ulsch_pdu_rel8->modulation_type, end) && + pull8(ppReadPackedMsg, &ulsch_pdu_rel8->cyclic_shift_2_for_drms, end) && + pull8(ppReadPackedMsg, &ulsch_pdu_rel8->frequency_hopping_enabled_flag, end) && + pull8(ppReadPackedMsg, &ulsch_pdu_rel8->frequency_hopping_bits, end) && + pull8(ppReadPackedMsg, &ulsch_pdu_rel8->new_data_indication, end) && + pull8(ppReadPackedMsg, &ulsch_pdu_rel8->redundancy_version, end) && + pull8(ppReadPackedMsg, &ulsch_pdu_rel8->harq_process_number, end) && + pull8(ppReadPackedMsg, &ulsch_pdu_rel8->ul_tx_mode, end) && + pull8(ppReadPackedMsg, &ulsch_pdu_rel8->current_tx_nb, end) && + pull8(ppReadPackedMsg, &ulsch_pdu_rel8->n_srs, end )); +} + +static uint8_t unpack_ul_config_ulsch_pdu_rel10_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_ul_config_ulsch_pdu_rel10_t* ulsch_pdu_rel10 = (nfapi_ul_config_ulsch_pdu_rel10_t*)tlv; + + return (pull8(ppReadPackedMsg, &ulsch_pdu_rel10->resource_allocation_type, end) && + pull32(ppReadPackedMsg, &ulsch_pdu_rel10->resource_block_coding, end) && + pull8(ppReadPackedMsg, &ulsch_pdu_rel10->transport_blocks, end) && + pull8(ppReadPackedMsg, &ulsch_pdu_rel10->transmission_scheme, end) && + pull8(ppReadPackedMsg, &ulsch_pdu_rel10->number_of_layers, end) & + pull8(ppReadPackedMsg, &ulsch_pdu_rel10->codebook_index, end) && + pull8(ppReadPackedMsg, &ulsch_pdu_rel10->disable_sequence_hopping_flag, end)); +} +static uint8_t unpack_ul_config_ulsch_pdu_rel11_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_ul_config_ulsch_pdu_rel11_t* ulsch_pdu_rel11 = (nfapi_ul_config_ulsch_pdu_rel11_t*)tlv; + + return ( pull8(ppReadPackedMsg, &ulsch_pdu_rel11->virtual_cell_id_enabled_flag, end) && + pull16(ppReadPackedMsg, &ulsch_pdu_rel11->npusch_identity, end) && + pull8(ppReadPackedMsg, &ulsch_pdu_rel11->dmrs_config_flag, end) && + pull16(ppReadPackedMsg, &ulsch_pdu_rel11->ndmrs_csh_identity, end)); +} +static uint8_t unpack_ul_config_ulsch_pdu_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_ul_config_ulsch_pdu_rel13_t* ulsch_pdu_rel13 = (nfapi_ul_config_ulsch_pdu_rel13_t*)tlv; + + return (pull8(ppReadPackedMsg, &ulsch_pdu_rel13->ue_type, end) && + pull16(ppReadPackedMsg, &ulsch_pdu_rel13->total_number_of_repetitions, end) && + pull16(ppReadPackedMsg, &ulsch_pdu_rel13->repetition_number, end) && + pull16(ppReadPackedMsg, &ulsch_pdu_rel13->initial_transmission_sf_io, end) && + pull8(ppReadPackedMsg, &ulsch_pdu_rel13->empty_symbols_due_to_re_tunning, end)); +} +static uint8_t unpack_ul_config_cqi_ri_info_rel8_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_ul_config_cqi_ri_information_rel8_t* cqi_ri_info_rel8 = (nfapi_ul_config_cqi_ri_information_rel8_t*)tlv; + + return (pull8(ppReadPackedMsg, &cqi_ri_info_rel8->dl_cqi_pmi_size_rank_1, end) && + pull8(ppReadPackedMsg, &cqi_ri_info_rel8->dl_cqi_pmi_size_rank_greater_1, end) && + pull8(ppReadPackedMsg, &cqi_ri_info_rel8->ri_size, end) && + pull8(ppReadPackedMsg, &cqi_ri_info_rel8->delta_offset_cqi, end) && + pull8(ppReadPackedMsg, &cqi_ri_info_rel8->delta_offset_ri, end)); +} + +static uint8_t unpack_ul_config_cqi_ri_info_rel9_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_ul_config_cqi_ri_information_rel9_t* cqi_ri_info_rel9 = (nfapi_ul_config_cqi_ri_information_rel9_t*)tlv; + + if(!(pull8(ppReadPackedMsg, &cqi_ri_info_rel9->report_type, end) && + pull8(ppReadPackedMsg, &cqi_ri_info_rel9->delta_offset_cqi, end) && + pull8(ppReadPackedMsg, &cqi_ri_info_rel9->delta_offset_ri, end))) + return 0; + + switch(cqi_ri_info_rel9->report_type) + { + case NFAPI_CSI_REPORT_TYPE_PERIODIC: + { + if(!(pull8(ppReadPackedMsg, &cqi_ri_info_rel9->periodic_cqi_pmi_ri_report.dl_cqi_pmi_ri_size, end) && + pull8(ppReadPackedMsg, &cqi_ri_info_rel9->periodic_cqi_pmi_ri_report.control_type, end))) + return 0; + } + break; + case NFAPI_CSI_REPORT_TYPE_APERIODIC: + { + if(pull8(ppReadPackedMsg, &cqi_ri_info_rel9->aperiodic_cqi_pmi_ri_report.number_of_cc, end) ==0) + return 0; + + uint8_t i; + for(i = 0; i < cqi_ri_info_rel9->aperiodic_cqi_pmi_ri_report.number_of_cc; ++i) + { + if(pull8(ppReadPackedMsg, &cqi_ri_info_rel9->aperiodic_cqi_pmi_ri_report.cc[i].ri_size, end) == 0) + return 0; + + uint8_t j; + for(j = 0; j < 8; ++j) + { + if(pull8(ppReadPackedMsg, &cqi_ri_info_rel9->aperiodic_cqi_pmi_ri_report.cc[i].dl_cqi_pmi_size[j], end) == 0) + return 0; + } + } + } + break; + default: + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "FIXME : Invalid report type %d \n", cqi_ri_info_rel9->report_type ); + return 0; + } + break; + }; + return 1; +} + +// NOTE : This function is a little unconventional as we uese the side to +// determine the report type +static uint8_t unpack_ul_config_cqi_ri_info_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_ul_config_cqi_ri_information_rel13_t* cqi_ri_info_rel13 = (nfapi_ul_config_cqi_ri_information_rel13_t*)tlv; + if(cqi_ri_info_rel13->tl.length == 0) + { + cqi_ri_info_rel13->report_type = NFAPI_CSI_REPORT_TYPE_APERIODIC; + } + else + { + cqi_ri_info_rel13->report_type = NFAPI_CSI_REPORT_TYPE_PERIODIC; + if(pull16(ppReadPackedMsg, &cqi_ri_info_rel13->periodic_cqi_pmi_ri_report.dl_cqi_pmi_ri_size_2, end) == 0) + return 0; + } + return 1; +} +static uint8_t unpack_ul_config_cqi_init_tx_params_rel8_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_ul_config_initial_transmission_parameters_rel8_t* init_tx_params_rel8 = (nfapi_ul_config_initial_transmission_parameters_rel8_t*)tlv; + + return (pull8(ppReadPackedMsg, &init_tx_params_rel8->n_srs_initial, end) && + pull8(ppReadPackedMsg, &init_tx_params_rel8->initial_number_of_resource_blocks, end)); +} +static uint8_t unpack_ul_config_ulsch_harq_info_rel10_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_ul_config_ulsch_harq_information_rel10_t* harq_info_rel10 = (nfapi_ul_config_ulsch_harq_information_rel10_t*)tlv; + + return (pull8(ppReadPackedMsg, &harq_info_rel10->harq_size, end) && + pull8(ppReadPackedMsg, &harq_info_rel10->delta_offset_harq, end) && + pull8(ppReadPackedMsg, &harq_info_rel10->ack_nack_mode, end)); +} + +static uint8_t unpack_ul_config_ulsch_harq_info_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_ul_config_ulsch_harq_information_rel13_t* harq_info_rel13 = (nfapi_ul_config_ulsch_harq_information_rel13_t*)tlv; + + return (pull16(ppReadPackedMsg, &harq_info_rel13->harq_size_2, end) && + pull8(ppReadPackedMsg, &harq_info_rel13->delta_offset_harq_2, end)); +} + +static uint8_t unpack_ul_config_ue_info_rel8_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_ul_config_ue_information_rel8_t* ue_info_rel8 = (nfapi_ul_config_ue_information_rel8_t*)tlv; + + return (pull32(ppReadPackedMsg, &ue_info_rel8->handle, end) && + pull16(ppReadPackedMsg, (uint16_t *)&ue_info_rel8->rnti, end)); +} +static uint8_t unpack_ul_config_ue_info_rel11_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_ul_config_ue_information_rel11_t* ue_info_rel11 = (nfapi_ul_config_ue_information_rel11_t*)tlv; + + return (pull8(ppReadPackedMsg, &ue_info_rel11->virtual_cell_id_enabled_flag, end) && + pull16(ppReadPackedMsg, &ue_info_rel11->npusch_identity, end)); +} +static uint8_t unpack_ul_config_ue_info_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_ul_config_ue_information_rel13_t* ue_info_rel13 = (nfapi_ul_config_ue_information_rel13_t*)tlv; + + return (pull8(ppReadPackedMsg, &ue_info_rel13->ue_type, end) && + pull8(ppReadPackedMsg, &ue_info_rel13->empty_symbols, end) && + pull16(ppReadPackedMsg, &ue_info_rel13->total_number_of_repetitions, end) && + pull16(ppReadPackedMsg, &ue_info_rel13->repetition_number, end)); +} + +static uint8_t unpack_ul_config_cqi_info_rel8_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_ul_config_cqi_information_rel8_t* cqi_info_rel8 = (nfapi_ul_config_cqi_information_rel8_t*)tlv; + + return ( pull16(ppReadPackedMsg, &cqi_info_rel8->pucch_index, end) && + pull8(ppReadPackedMsg, &cqi_info_rel8->dl_cqi_pmi_size, end)); +} +static uint8_t unpack_ul_config_cqi_info_rel10_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_ul_config_cqi_information_rel10_t* cqi_info_rel10 = (nfapi_ul_config_cqi_information_rel10_t*)tlv; + + return (pull8(ppReadPackedMsg, &cqi_info_rel10->number_of_pucch_resource, end) && + pull16(ppReadPackedMsg, &cqi_info_rel10->pucch_index_p1, end)); +} +static uint8_t unpack_ul_config_cqi_info_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_ul_config_cqi_information_rel13_t* cqi_info_rel13 = (nfapi_ul_config_cqi_information_rel13_t*)tlv; + + return (pull8(ppReadPackedMsg, &cqi_info_rel13->csi_mode, end) && + pull16(ppReadPackedMsg, &cqi_info_rel13->dl_cqi_pmi_size_2, end) && + pull8(ppReadPackedMsg, &cqi_info_rel13->starting_prb, end) && + pull8(ppReadPackedMsg, &cqi_info_rel13->n_prb, end) && + pull8(ppReadPackedMsg, &cqi_info_rel13->cdm_index, end) && + pull8(ppReadPackedMsg, &cqi_info_rel13->n_srs, end)); +} + +static uint8_t unpack_ul_config_sr_info_rel8_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_ul_config_sr_information_rel8_t* sr_info_rel8 = (nfapi_ul_config_sr_information_rel8_t*)tlv; + + return ( pull16(ppReadPackedMsg, &sr_info_rel8->pucch_index, end)); +} + +static uint8_t unpack_ul_config_sr_info_rel10_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_ul_config_sr_information_rel10_t* sr_info_rel10 = (nfapi_ul_config_sr_information_rel10_t*)tlv; + + return (pull8(ppReadPackedMsg, &sr_info_rel10->number_of_pucch_resources, end) && + pull16(ppReadPackedMsg, &sr_info_rel10->pucch_index_p1, end)); +} + +static uint8_t unpack_ul_config_harq_info_rel10_tdd_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_ul_config_harq_information_rel10_tdd_t* harq_info_tdd_rel10 = (nfapi_ul_config_harq_information_rel10_tdd_t*)tlv; + + return (pull8(ppReadPackedMsg, &harq_info_tdd_rel10->harq_size, end) && + pull8(ppReadPackedMsg, &harq_info_tdd_rel10->ack_nack_mode, end) && + pull8(ppReadPackedMsg, &harq_info_tdd_rel10->number_of_pucch_resources, end) && + pull16(ppReadPackedMsg, &harq_info_tdd_rel10->n_pucch_1_0, end) && + pull16(ppReadPackedMsg, &harq_info_tdd_rel10->n_pucch_1_1, end) && + pull16(ppReadPackedMsg, &harq_info_tdd_rel10->n_pucch_1_2, end) && + pull16(ppReadPackedMsg, &harq_info_tdd_rel10->n_pucch_1_3, end)); +} + +static uint8_t unpack_ul_config_harq_info_rel8_fdd_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_ul_config_harq_information_rel8_fdd_t* harq_info_fdd_rel8 = (nfapi_ul_config_harq_information_rel8_fdd_t*)tlv; + + return (pull16(ppReadPackedMsg, &harq_info_fdd_rel8->n_pucch_1_0, end) && + pull8(ppReadPackedMsg, &harq_info_fdd_rel8->harq_size, end)); +} + +static uint8_t unpack_ul_config_harq_info_rel9_fdd_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_ul_config_harq_information_rel9_fdd_t* harq_info_fdd_rel9 = (nfapi_ul_config_harq_information_rel9_fdd_t*)tlv; + + return (pull8(ppReadPackedMsg, &harq_info_fdd_rel9->harq_size, end) && + pull8(ppReadPackedMsg, &harq_info_fdd_rel9->ack_nack_mode, end) && + pull8(ppReadPackedMsg, &harq_info_fdd_rel9->number_of_pucch_resources, end) && + pull16(ppReadPackedMsg, &harq_info_fdd_rel9->n_pucch_1_0, end) && + pull16(ppReadPackedMsg, &harq_info_fdd_rel9->n_pucch_1_1, end) && + pull16(ppReadPackedMsg, &harq_info_fdd_rel9->n_pucch_1_2, end) && + pull16(ppReadPackedMsg, &harq_info_fdd_rel9->n_pucch_1_3, end)); +} + +static uint8_t unpack_ul_config_harq_info_rel11_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_ul_config_harq_information_rel11_t* harq_info_rel11 = (nfapi_ul_config_harq_information_rel11_t*)tlv; + + return (pull8(ppReadPackedMsg, &harq_info_rel11->num_ant_ports, end) && + pull16(ppReadPackedMsg, &harq_info_rel11->n_pucch_2_0, end) && + pull16(ppReadPackedMsg, &harq_info_rel11->n_pucch_2_1, end) && + pull16(ppReadPackedMsg, &harq_info_rel11->n_pucch_2_2, end) && + pull16(ppReadPackedMsg, &harq_info_rel11->n_pucch_2_3, end)); +} + +static uint8_t unpack_ul_config_harq_info_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_ul_config_harq_information_rel13_t* harq_info_rel13 = (nfapi_ul_config_harq_information_rel13_t*)tlv; + + return (pull16(ppReadPackedMsg, &harq_info_rel13->harq_size_2, end) && + pull8(ppReadPackedMsg, &harq_info_rel13->starting_prb, end) && + pull8(ppReadPackedMsg, &harq_info_rel13->n_prb, end) && + pull8(ppReadPackedMsg, &harq_info_rel13->cdm_index, end) && + pull8(ppReadPackedMsg, &harq_info_rel13->n_srs, end)); +} + + +static uint8_t unpack_ul_config_srs_pdu_rel8_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_ul_config_srs_pdu_rel8_t* srs_pdu_rel8 = (nfapi_ul_config_srs_pdu_rel8_t*)tlv; + + return (pull32(ppReadPackedMsg, &srs_pdu_rel8->handle, end) && + pull16(ppReadPackedMsg, &srs_pdu_rel8->size, end) && + pull16(ppReadPackedMsg, &srs_pdu_rel8->rnti, end) && + pull8(ppReadPackedMsg, &srs_pdu_rel8->srs_bandwidth, end) && + pull8(ppReadPackedMsg, &srs_pdu_rel8->frequency_domain_position, end) && + pull8(ppReadPackedMsg, &srs_pdu_rel8->srs_hopping_bandwidth, end) && + pull8(ppReadPackedMsg, &srs_pdu_rel8->transmission_comb, end) && + pull16(ppReadPackedMsg, &srs_pdu_rel8->i_srs, end) && + pull8(ppReadPackedMsg, &srs_pdu_rel8->sounding_reference_cyclic_shift, end)); +} + +static uint8_t unpack_ul_config_srs_pdu_rel10_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_ul_config_srs_pdu_rel10_t* srs_pdu_rel10 = (nfapi_ul_config_srs_pdu_rel10_t*)tlv; + return pull8(ppReadPackedMsg, &srs_pdu_rel10->antenna_port, end); +} + +static uint8_t unpack_ul_config_srs_pdu_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_ul_config_srs_pdu_rel13_t* srs_pdu_rel13 = (nfapi_ul_config_srs_pdu_rel13_t*)tlv; + + return (pull8(ppReadPackedMsg, &srs_pdu_rel13->number_of_combs, end)); +} + +static uint8_t unpack_ul_nb_harq_info_rel13_fdd_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_ul_config_nb_harq_information_rel13_fdd_t* nb_harq_info_fdd_rel13 = (nfapi_ul_config_nb_harq_information_rel13_fdd_t*)tlv; + + return (pull8(ppReadPackedMsg, &nb_harq_info_fdd_rel13->harq_ack_resource, end)); +} + +static uint8_t unpack_ul_config_nulsch_pdu_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_ul_config_nulsch_pdu_rel13_t* nulsch_pdu_rel13 = (nfapi_ul_config_nulsch_pdu_rel13_t*)tlv; + + if(!(pull8(ppReadPackedMsg, &nulsch_pdu_rel13->nulsch_format, end) && + pull32(ppReadPackedMsg, &nulsch_pdu_rel13->handle, end) && + pull16(ppReadPackedMsg, &nulsch_pdu_rel13->size, end) && + pull16(ppReadPackedMsg, &nulsch_pdu_rel13->rnti, end) && + pull8(ppReadPackedMsg, &nulsch_pdu_rel13->subcarrier_indication, end) && + pull8(ppReadPackedMsg, &nulsch_pdu_rel13->resource_assignment, end) && + pull8(ppReadPackedMsg, &nulsch_pdu_rel13->mcs, end) && + pull8(ppReadPackedMsg, &nulsch_pdu_rel13->redudancy_version, end) && + pull8(ppReadPackedMsg, &nulsch_pdu_rel13->repetition_number, end) && + pull8(ppReadPackedMsg, &nulsch_pdu_rel13->new_data_indication, end) && + pull8(ppReadPackedMsg, &nulsch_pdu_rel13->n_srs, end) && + pull16(ppReadPackedMsg, &nulsch_pdu_rel13->scrambling_sequence_initialization_cinit, end) && + pull16(ppReadPackedMsg, &nulsch_pdu_rel13->sf_idx, end))) + return 0; + + unpack_tlv_t unpack_fns[] = + { + { NFAPI_UL_CONFIG_REQUEST_UE_INFORMATION_REL8_TAG, &nulsch_pdu_rel13->ue_information.ue_information_rel8, &unpack_ul_config_ue_info_rel8_value}, + { NFAPI_UL_CONFIG_REQUEST_UE_INFORMATION_REL11_TAG, &nulsch_pdu_rel13->ue_information.ue_information_rel11, &unpack_ul_config_ue_info_rel11_value}, + { NFAPI_UL_CONFIG_REQUEST_UE_INFORMATION_REL13_TAG, &nulsch_pdu_rel13->ue_information.ue_information_rel13, &unpack_ul_config_ue_info_rel13_value}, + { NFAPI_UL_CONFIG_REQUEST_NB_HARQ_INFORMATION_REL13_FDD_TAG, &nulsch_pdu_rel13->nb_harq_information.nb_harq_information_rel13_fdd, &unpack_ul_nb_harq_info_rel13_fdd_value}, + }; + + return unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, 0, 0); +} + +static uint8_t unpack_ul_config_nrach_pdu_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_ul_config_nrach_pdu_rel13_t* nrach_pdu_rel13 = (nfapi_ul_config_nrach_pdu_rel13_t*)tlv; + + return (pull8(ppReadPackedMsg, &nrach_pdu_rel13->nprach_config_0, end) && + pull8(ppReadPackedMsg, &nrach_pdu_rel13->nprach_config_1, end) && + pull8(ppReadPackedMsg, &nrach_pdu_rel13->nprach_config_2, end)); +} + + +static uint8_t unpack_ul_config_request_body_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) +{ + #define UL_CONFIG_ULSCH_PDU_UNPACK_FNS(_pdu) \ + { NFAPI_UL_CONFIG_REQUEST_ULSCH_PDU_REL8_TAG, &_pdu.ulsch_pdu_rel8, &unpack_ul_config_ulsch_pdu_rel8_value}, \ + { NFAPI_UL_CONFIG_REQUEST_ULSCH_PDU_REL10_TAG, &_pdu.ulsch_pdu_rel10, &unpack_ul_config_ulsch_pdu_rel10_value}, \ + { NFAPI_UL_CONFIG_REQUEST_ULSCH_PDU_REL11_TAG, &_pdu.ulsch_pdu_rel11, &unpack_ul_config_ulsch_pdu_rel11_value}, \ + { NFAPI_UL_CONFIG_REQUEST_ULSCH_PDU_REL13_TAG, &_pdu.ulsch_pdu_rel13, &unpack_ul_config_ulsch_pdu_rel13_value}, + + #define UL_CONFIG_CQI_RI_INFO_UNPACK_FNS(_pdu) \ + { NFAPI_UL_CONFIG_REQUEST_CQI_RI_INFORMATION_REL8_TAG, &_pdu.cqi_ri_information_rel8, &unpack_ul_config_cqi_ri_info_rel8_value}, \ + { NFAPI_UL_CONFIG_REQUEST_CQI_RI_INFORMATION_REL9_TAG, &_pdu.cqi_ri_information_rel9, &unpack_ul_config_cqi_ri_info_rel9_value}, \ + { NFAPI_UL_CONFIG_REQUEST_CQI_RI_INFORMATION_REL13_TAG, &_pdu.cqi_ri_information_rel13, &unpack_ul_config_cqi_ri_info_rel13_value}, + + #define UL_CONFIG_ULSCH_HARQ_INFO_UNPACK_FNS(_pdu) \ + { NFAPI_UL_CONFIG_REQUEST_ULSCH_HARQ_INFORMATION_REL10_TAG, &_pdu.harq_information_rel10, &unpack_ul_config_ulsch_harq_info_rel10_value},\ + { NFAPI_UL_CONFIG_REQUEST_ULSCH_HARQ_INFORMATION_REL13_TAG, &_pdu.harq_information_rel13, &unpack_ul_config_ulsch_harq_info_rel13_value}, + + #define UL_CONFIG_INIT_TX_PARAMS_UNPACK_FNS(_pdu) \ + { NFAPI_UL_CONFIG_REQUEST_INITIAL_TRANSMISSION_PARAMETERS_REL8_TAG, &_pdu.initial_transmission_parameters_rel8, &unpack_ul_config_cqi_init_tx_params_rel8_value}, + + #define UL_CONFIG_UCI_UE_INFO_UNPACK_FNS(_pdu) \ + { NFAPI_UL_CONFIG_REQUEST_UE_INFORMATION_REL8_TAG, &_pdu.ue_information_rel8, &unpack_ul_config_ue_info_rel8_value}, \ + { NFAPI_UL_CONFIG_REQUEST_UE_INFORMATION_REL11_TAG, &_pdu.ue_information_rel11, &unpack_ul_config_ue_info_rel11_value}, \ + { NFAPI_UL_CONFIG_REQUEST_UE_INFORMATION_REL13_TAG, &_pdu.ue_information_rel13, &unpack_ul_config_ue_info_rel13_value}, + + #define UL_CONFIG_UCI_CQI_INFO_UNPACK_FNS(_pdu) \ + { NFAPI_UL_CONFIG_REQUEST_CQI_INFORMATION_REL8_TAG, &_pdu.cqi_information_rel8, &unpack_ul_config_cqi_info_rel8_value}, \ + { NFAPI_UL_CONFIG_REQUEST_CQI_INFORMATION_REL10_TAG, &_pdu.cqi_information_rel10, &unpack_ul_config_cqi_info_rel10_value}, \ + { NFAPI_UL_CONFIG_REQUEST_CQI_INFORMATION_REL13_TAG, &_pdu.cqi_information_rel13, &unpack_ul_config_cqi_info_rel13_value}, + + #define UL_CONFIG_UCI_SR_INFO_UNPACK_FNS(_pdu) \ + { NFAPI_UL_CONFIG_REQUEST_SR_INFORMATION_REL8_TAG, &_pdu.sr_information_rel8, &unpack_ul_config_sr_info_rel8_value}, \ + { NFAPI_UL_CONFIG_REQUEST_SR_INFORMATION_REL10_TAG, &_pdu.sr_information_rel10, &unpack_ul_config_sr_info_rel10_value}, + + #define UL_CONFIG_UCI_HARQ_INFO_UNPACK_FNS(_pdu) \ + { NFAPI_UL_CONFIG_REQUEST_HARQ_INFORMATION_REL10_TDD_TAG, &_pdu.harq_information_rel10_tdd, &unpack_ul_config_harq_info_rel10_tdd_value}, \ + { NFAPI_UL_CONFIG_REQUEST_HARQ_INFORMATION_REL8_FDD_TAG, &_pdu.harq_information_rel8_fdd, &unpack_ul_config_harq_info_rel8_fdd_value}, \ + { NFAPI_UL_CONFIG_REQUEST_HARQ_INFORMATION_REL9_FDD_TAG, &_pdu.harq_information_rel9_fdd, &unpack_ul_config_harq_info_rel9_fdd_value}, \ + { NFAPI_UL_CONFIG_REQUEST_HARQ_INFORMATION_REL11_TAG, &_pdu.harq_information_rel11, &unpack_ul_config_harq_info_rel11_value}, \ + { NFAPI_UL_CONFIG_REQUEST_HARQ_INFORMATION_REL13_TAG, &_pdu.harq_information_rel13, &unpack_ul_config_harq_info_rel13_value}, + + #define UL_CONFIG_SRS_PDU_UNPACK_FNS(_pdu) \ + { NFAPI_UL_CONFIG_REQUEST_SRS_PDU_REL8_TAG, &_pdu.srs_pdu_rel8, &unpack_ul_config_srs_pdu_rel8_value}, \ + { NFAPI_UL_CONFIG_REQUEST_SRS_PDU_REL10_TAG, &_pdu.srs_pdu_rel10, &unpack_ul_config_srs_pdu_rel10_value}, \ + { NFAPI_UL_CONFIG_REQUEST_SRS_PDU_REL13_TAG, &_pdu.srs_pdu_rel13, &unpack_ul_config_srs_pdu_rel13_value}, + + #define UL_CONFIG_NULSCH_PDU_UNPACK_FNS(_pdu) \ + { NFAPI_UL_CONFIG_REQUEST_NULSCH_PDU_REL13_TAG, &_pdu.nulsch_pdu_rel13, &unpack_ul_config_nulsch_pdu_rel13_value}, + + #define UL_CONFIG_NRACH_PDU_UNPACK_FNS(_pdu) \ + { NFAPI_UL_CONFIG_REQUEST_NRACH_PDU_REL13_TAG, &_pdu.nrach_pdu_rel13, &unpack_ul_config_nrach_pdu_rel13_value}, + + + nfapi_ul_config_request_body_t* value = (nfapi_ul_config_request_body_t*)tlv; + + if(!(pull8(ppReadPackedMsg, &value->number_of_pdus, end) && + pull8(ppReadPackedMsg, &value->rach_prach_frequency_resources, end) && + pull8(ppReadPackedMsg, &value->srs_present, end))) + return 0; + + if(value->number_of_pdus > NFAPI_UL_CONFIG_MAX_PDU) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s number of ul config pdus exceed maxium (count:%d max:%d)\n", __FUNCTION__, value->number_of_pdus, NFAPI_UL_CONFIG_MAX_PDU); + return 0; + } + + if(value->number_of_pdus > 0) + { + value->ul_config_pdu_list = (nfapi_ul_config_request_pdu_t*)nfapi_p7_allocate(sizeof(nfapi_ul_config_request_pdu_t) * value->number_of_pdus, config); + + if(value->ul_config_pdu_list == NULL) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s failed to allocate ul config pdu list (count:%d)\n", __FUNCTION__, value->number_of_pdus); + return 0; + } + } + else + { + value->ul_config_pdu_list = 0; + } + + + uint16_t i; + uint16_t total_number_of_pdus = value->number_of_pdus; + for(i = 0; i < total_number_of_pdus; ++i) + { + nfapi_ul_config_request_pdu_t* pdu = &(value->ul_config_pdu_list[i]); + + if(!(pull8(ppReadPackedMsg, &pdu->pdu_type, end) && + pull8(ppReadPackedMsg, &pdu->pdu_size, end))) + return 0; + + uint8_t *packedPduEnd = (*ppReadPackedMsg) + pdu->pdu_size - 2; + + if(packedPduEnd > end) + { + // pdu end is past buffer end + return 0; + } + + switch(pdu->pdu_type) + { + case NFAPI_UL_CONFIG_ULSCH_PDU_TYPE: + { + unpack_tlv_t unpack_fns[] = + { + UL_CONFIG_ULSCH_PDU_UNPACK_FNS(pdu->ulsch_pdu) + }; + + unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); + } + break; + + case NFAPI_UL_CONFIG_ULSCH_CQI_RI_PDU_TYPE: + { + unpack_tlv_t unpack_fns[] = + { + UL_CONFIG_ULSCH_PDU_UNPACK_FNS(pdu->ulsch_cqi_ri_pdu.ulsch_pdu) + UL_CONFIG_CQI_RI_INFO_UNPACK_FNS(pdu->ulsch_cqi_ri_pdu.cqi_ri_information) + UL_CONFIG_INIT_TX_PARAMS_UNPACK_FNS(pdu->ulsch_cqi_ri_pdu.initial_transmission_parameters) + }; + + unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); + } + break; + case NFAPI_UL_CONFIG_ULSCH_HARQ_PDU_TYPE: + { + unpack_tlv_t unpack_fns[] = + { + UL_CONFIG_ULSCH_PDU_UNPACK_FNS(pdu->ulsch_harq_pdu.ulsch_pdu) + UL_CONFIG_ULSCH_HARQ_INFO_UNPACK_FNS(pdu->ulsch_harq_pdu.harq_information) + UL_CONFIG_INIT_TX_PARAMS_UNPACK_FNS(pdu->ulsch_harq_pdu.initial_transmission_parameters) + }; + + unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); + } + break; + case NFAPI_UL_CONFIG_ULSCH_CQI_HARQ_RI_PDU_TYPE: + { + unpack_tlv_t unpack_fns[] = + { + UL_CONFIG_ULSCH_PDU_UNPACK_FNS(pdu->ulsch_cqi_harq_ri_pdu.ulsch_pdu) + UL_CONFIG_CQI_RI_INFO_UNPACK_FNS(pdu->ulsch_cqi_harq_ri_pdu.cqi_ri_information) + UL_CONFIG_ULSCH_HARQ_INFO_UNPACK_FNS(pdu->ulsch_cqi_harq_ri_pdu.harq_information) + UL_CONFIG_INIT_TX_PARAMS_UNPACK_FNS(pdu->ulsch_cqi_harq_ri_pdu.initial_transmission_parameters) + }; + + unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); + } + break; + case NFAPI_UL_CONFIG_UCI_CQI_PDU_TYPE: + { + unpack_tlv_t unpack_fns[] = + { + UL_CONFIG_UCI_UE_INFO_UNPACK_FNS(pdu->uci_cqi_pdu.ue_information) + UL_CONFIG_UCI_CQI_INFO_UNPACK_FNS(pdu->uci_cqi_pdu.cqi_information) + }; + + unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); + } + break; + case NFAPI_UL_CONFIG_UCI_SR_PDU_TYPE: + { + unpack_tlv_t unpack_fns[] = + { + UL_CONFIG_UCI_UE_INFO_UNPACK_FNS(pdu->uci_sr_pdu.ue_information) + UL_CONFIG_UCI_SR_INFO_UNPACK_FNS(pdu->uci_sr_pdu.sr_information) + }; + + unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); + } + break; + case NFAPI_UL_CONFIG_UCI_HARQ_PDU_TYPE: + { + unpack_tlv_t unpack_fns[] = + { + UL_CONFIG_UCI_UE_INFO_UNPACK_FNS(pdu->uci_harq_pdu.ue_information) + UL_CONFIG_UCI_HARQ_INFO_UNPACK_FNS(pdu->uci_harq_pdu.harq_information) + }; + + unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); + } + break; + case NFAPI_UL_CONFIG_UCI_SR_HARQ_PDU_TYPE: + { + unpack_tlv_t unpack_fns[] = + { + UL_CONFIG_UCI_UE_INFO_UNPACK_FNS(pdu->uci_sr_harq_pdu.ue_information) + UL_CONFIG_UCI_SR_INFO_UNPACK_FNS(pdu->uci_sr_harq_pdu.sr_information) + UL_CONFIG_UCI_HARQ_INFO_UNPACK_FNS(pdu->uci_sr_harq_pdu.harq_information) + }; + + unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); + } + break; + case NFAPI_UL_CONFIG_UCI_CQI_HARQ_PDU_TYPE: + { + unpack_tlv_t unpack_fns[] = + { + UL_CONFIG_UCI_UE_INFO_UNPACK_FNS(pdu->uci_cqi_harq_pdu.ue_information) + UL_CONFIG_UCI_CQI_INFO_UNPACK_FNS(pdu->uci_cqi_harq_pdu.cqi_information) + UL_CONFIG_UCI_HARQ_INFO_UNPACK_FNS(pdu->uci_cqi_harq_pdu.harq_information) + }; + + unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); + } + break; + case NFAPI_UL_CONFIG_UCI_CQI_SR_PDU_TYPE: + { + unpack_tlv_t unpack_fns[] = + { + UL_CONFIG_UCI_UE_INFO_UNPACK_FNS(pdu->uci_cqi_sr_pdu.ue_information) + UL_CONFIG_UCI_CQI_INFO_UNPACK_FNS(pdu->uci_cqi_sr_pdu.cqi_information) + UL_CONFIG_UCI_SR_INFO_UNPACK_FNS(pdu->uci_cqi_sr_pdu.sr_information) + }; + + unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); + } + break; + case NFAPI_UL_CONFIG_UCI_CQI_SR_HARQ_PDU_TYPE: + { + unpack_tlv_t unpack_fns[] = + { + UL_CONFIG_UCI_UE_INFO_UNPACK_FNS(pdu->uci_cqi_sr_harq_pdu.ue_information) + UL_CONFIG_UCI_CQI_INFO_UNPACK_FNS(pdu->uci_cqi_sr_harq_pdu.cqi_information) + UL_CONFIG_UCI_SR_INFO_UNPACK_FNS(pdu->uci_cqi_sr_harq_pdu.sr_information) + UL_CONFIG_UCI_HARQ_INFO_UNPACK_FNS(pdu->uci_cqi_sr_harq_pdu.harq_information) + }; + + unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); + } + break; + case NFAPI_UL_CONFIG_SRS_PDU_TYPE: + { + unpack_tlv_t unpack_fns[] = + { + UL_CONFIG_SRS_PDU_UNPACK_FNS(pdu->srs_pdu) + }; + + unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); + } + break; + case NFAPI_UL_CONFIG_HARQ_BUFFER_PDU_TYPE: + { + unpack_tlv_t unpack_fns[] = + { + UL_CONFIG_UCI_UE_INFO_UNPACK_FNS(pdu->harq_buffer_pdu.ue_information) + }; + + unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); + } + break; + case NFAPI_UL_CONFIG_ULSCH_UCI_CSI_PDU_TYPE: + { + unpack_tlv_t unpack_fns[] = + { + UL_CONFIG_ULSCH_PDU_UNPACK_FNS(pdu->ulsch_uci_csi_pdu.ulsch_pdu) + UL_CONFIG_UCI_CQI_INFO_UNPACK_FNS(pdu->ulsch_uci_csi_pdu.csi_information) + }; + + unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); + } + break; + case NFAPI_UL_CONFIG_ULSCH_UCI_HARQ_PDU_TYPE: + { + unpack_tlv_t unpack_fns[] = + { + UL_CONFIG_ULSCH_PDU_UNPACK_FNS(pdu->ulsch_uci_harq_pdu.ulsch_pdu) + UL_CONFIG_UCI_HARQ_INFO_UNPACK_FNS(pdu->ulsch_uci_harq_pdu.harq_information) + }; + + unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); + } + break; + case NFAPI_UL_CONFIG_ULSCH_CSI_UCI_HARQ_PDU_TYPE: + { + unpack_tlv_t unpack_fns[] = + { + UL_CONFIG_ULSCH_PDU_UNPACK_FNS(pdu->ulsch_csi_uci_harq_pdu.ulsch_pdu) + UL_CONFIG_UCI_CQI_INFO_UNPACK_FNS(pdu->ulsch_csi_uci_harq_pdu.csi_information) + UL_CONFIG_UCI_HARQ_INFO_UNPACK_FNS(pdu->ulsch_csi_uci_harq_pdu.harq_information) + }; + + unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); + } + break; + case NFAPI_UL_CONFIG_NULSCH_PDU_TYPE: + { + unpack_tlv_t unpack_fns[] = + { + UL_CONFIG_NULSCH_PDU_UNPACK_FNS(pdu->nulsch_pdu) + }; + + unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); + } + break; + case NFAPI_UL_CONFIG_NRACH_PDU_TYPE: + { + unpack_tlv_t unpack_fns[] = + { + UL_CONFIG_NRACH_PDU_UNPACK_FNS(pdu->nrach_pdu) + }; + + unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); + } + break; + } + } + return 1; +} + + +static uint8_t unpack_ul_config_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config) +{ + nfapi_ul_config_request_t *pNfapiMsg = (nfapi_ul_config_request_t*)msg; + + unpack_p7_tlv_t unpack_fns[] = + { + { NFAPI_UL_CONFIG_REQUEST_BODY_TAG, &pNfapiMsg->ul_config_request_body, &unpack_ul_config_request_body_value}, + }; + + return (pull16(ppReadPackedMsg, &pNfapiMsg->sfn_sf, end) && + unpack_p7_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); +} + +static uint8_t unpack_hi_dci0_hi_pdu_rel8_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_hi_dci0_hi_pdu_rel8_t* hi_pdu_rel8 = (nfapi_hi_dci0_hi_pdu_rel8_t*)tlv; + + return( pull8(ppReadPackedMsg, &hi_pdu_rel8->resource_block_start, end) && + pull8(ppReadPackedMsg, &hi_pdu_rel8->cyclic_shift_2_for_drms, end) && + pull8(ppReadPackedMsg, &hi_pdu_rel8->hi_value, end) && + pull8(ppReadPackedMsg, &hi_pdu_rel8->i_phich, end) && + pull16(ppReadPackedMsg, &hi_pdu_rel8->transmission_power, end)); +} + +static uint8_t unpack_hi_dci0_hi_pdu_rel10_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_hi_dci0_hi_pdu_rel10_t* hi_pdu_rel10 = (nfapi_hi_dci0_hi_pdu_rel10_t*)tlv; + + return (pull8(ppReadPackedMsg, &hi_pdu_rel10->flag_tb2, end) && + pull8(ppReadPackedMsg, &hi_pdu_rel10->hi_value_2, end)); +} + +static uint8_t unpack_hi_dci0_dci_pdu_rel8_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_hi_dci0_dci_pdu_rel8_t* dci_pdu_rel8 = (nfapi_hi_dci0_dci_pdu_rel8_t*)tlv; + + return (pull8(ppReadPackedMsg, &dci_pdu_rel8->dci_format, end) && + pull8(ppReadPackedMsg, &dci_pdu_rel8->cce_index, end) && + pull8(ppReadPackedMsg, &dci_pdu_rel8->aggregation_level, end) && + pull16(ppReadPackedMsg, &dci_pdu_rel8->rnti, end) && + pull8(ppReadPackedMsg, &dci_pdu_rel8->resource_block_start, end) && + pull8(ppReadPackedMsg, &dci_pdu_rel8->number_of_resource_block, end) && + pull8(ppReadPackedMsg, &dci_pdu_rel8->mcs_1, end) && + pull8(ppReadPackedMsg, &dci_pdu_rel8->cyclic_shift_2_for_drms, end) && + pull8(ppReadPackedMsg, &dci_pdu_rel8->frequency_hopping_enabled_flag, end) && + pull8(ppReadPackedMsg, &dci_pdu_rel8->frequency_hopping_bits, end) && + pull8(ppReadPackedMsg, &dci_pdu_rel8->new_data_indication_1, end) && + pull8(ppReadPackedMsg, &dci_pdu_rel8->ue_tx_antenna_seleciton, end) && + pull8(ppReadPackedMsg, &dci_pdu_rel8->tpc, end) && + pull8(ppReadPackedMsg, &dci_pdu_rel8->cqi_csi_request, end) && + pull8(ppReadPackedMsg, &dci_pdu_rel8->ul_index, end) && + pull8(ppReadPackedMsg, &dci_pdu_rel8->dl_assignment_index, end) && + pull32(ppReadPackedMsg, &dci_pdu_rel8->tpc_bitmap, end) && + pull16(ppReadPackedMsg, &dci_pdu_rel8->transmission_power, end)); +} + +static uint8_t unpack_hi_dci0_dci_pdu_rel10_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_hi_dci0_dci_pdu_rel10_t* dci_pdu_rel10 = (nfapi_hi_dci0_dci_pdu_rel10_t*)tlv; + + return (pull8(ppReadPackedMsg, &dci_pdu_rel10->cross_carrier_scheduling_flag, end) && + pull8(ppReadPackedMsg, &dci_pdu_rel10->carrier_indicator, end) && + pull8(ppReadPackedMsg, &dci_pdu_rel10->size_of_cqi_csi_feild, end) && + pull8(ppReadPackedMsg, &dci_pdu_rel10->srs_flag, end) && + pull8(ppReadPackedMsg, &dci_pdu_rel10->srs_request, end) && + pull8(ppReadPackedMsg, &dci_pdu_rel10->resource_allocation_flag, end) && + pull8(ppReadPackedMsg, &dci_pdu_rel10->resource_allocation_type, end) && + pull32(ppReadPackedMsg, &dci_pdu_rel10->resource_block_coding, end) && + pull8(ppReadPackedMsg, &dci_pdu_rel10->mcs_2, end) && + pull8(ppReadPackedMsg, &dci_pdu_rel10->new_data_indication_2, end) && + pull8(ppReadPackedMsg, &dci_pdu_rel10->number_of_antenna_ports, end) && + pull8(ppReadPackedMsg, &dci_pdu_rel10->tpmi, end) && + pull8(ppReadPackedMsg, &dci_pdu_rel10->total_dci_length_including_padding, end) && + pull8(ppReadPackedMsg, &dci_pdu_rel10->n_ul_rb, end)); +} + +static uint8_t unpack_hi_dci0_dci_pdu_rel12_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_hi_dci0_dci_pdu_rel12_t* dci_pdu_rel12 = (nfapi_hi_dci0_dci_pdu_rel12_t*)tlv; + + return ( pull8(ppReadPackedMsg, &dci_pdu_rel12->pscch_resource, end) && + pull8(ppReadPackedMsg, &dci_pdu_rel12->time_resource_pattern, end)); +} + +static uint8_t unpack_hi_dci0_mpdcch_dci_pdu_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_hi_dci0_mpdcch_dci_pdu_rel13_t* value = (nfapi_hi_dci0_mpdcch_dci_pdu_rel13_t*)tlv; + + return (pull8(ppReadPackedMsg, &value->mpdcch_narrowband, end) && + pull8(ppReadPackedMsg, &value->number_of_prb_pairs, end) && + pull8(ppReadPackedMsg, &value->resource_block_assignment, end) && + pull8(ppReadPackedMsg, &value->mpdcch_transmission_type, end) && + pull8(ppReadPackedMsg, &value->start_symbol, end) && + pull8(ppReadPackedMsg, &value->ecce_index, end) && + pull8(ppReadPackedMsg, &value->aggreagation_level, end) && + pull8(ppReadPackedMsg, &value->rnti_type, end) && + pull16(ppReadPackedMsg, &value->rnti, end) && + pull8(ppReadPackedMsg, &value->ce_mode, end) && + pull16(ppReadPackedMsg, &value->drms_scrambling_init, end) && + pull16(ppReadPackedMsg, &value->initial_transmission_sf_io, end) && + pull16(ppReadPackedMsg, &value->transmission_power, end) && + pull8(ppReadPackedMsg, &value->dci_format, end) && + pull8(ppReadPackedMsg, &value->resource_block_start, end) && + pull8(ppReadPackedMsg, &value->number_of_resource_blocks, end) && + pull8(ppReadPackedMsg, &value->mcs, end) && + pull8(ppReadPackedMsg, &value->pusch_repetition_levels, end) && + pull8(ppReadPackedMsg, &value->frequency_hopping_flag, end) && + pull8(ppReadPackedMsg, &value->new_data_indication, end) && + pull8(ppReadPackedMsg, &value->harq_process, end) && + pull8(ppReadPackedMsg, &value->redudency_version, end) && + pull8(ppReadPackedMsg, &value->tpc, end) && + pull8(ppReadPackedMsg, &value->csi_request, end) && + pull8(ppReadPackedMsg, &value->ul_inex, end) && + pull8(ppReadPackedMsg, &value->dai_presence_flag, end) && + pull8(ppReadPackedMsg, &value->dl_assignment_index, end) && + pull8(ppReadPackedMsg, &value->srs_request, end) && + pull8(ppReadPackedMsg, &value->dci_subframe_repetition_number, end) && + pull32(ppReadPackedMsg, &value->tcp_bitmap, end) && + pull8(ppReadPackedMsg, &value->total_dci_length_include_padding, end) && + pull8(ppReadPackedMsg, &value->number_of_tx_antenna_ports, end) && + pullarray16(ppReadPackedMsg, value->precoding_value, NFAPI_MAX_TX_PHYSICAL_ANTENNA_PORTS, value->number_of_tx_antenna_ports, end)); +} + +static uint8_t unpack_hi_dci0_npdcch_dci_pdu_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_hi_dci0_npdcch_dci_pdu_rel13_t* value = (nfapi_hi_dci0_npdcch_dci_pdu_rel13_t*)tlv; + + return (pull8(ppReadPackedMsg, &value->ncce_index, end) && + pull8(ppReadPackedMsg, &value->aggregation_level, end) && + pull8(ppReadPackedMsg, &value->start_symbol, end) && + pull16(ppReadPackedMsg, &value->rnti, end) && + pull8(ppReadPackedMsg, &value->scrambling_reinitialization_batch_index, end) && + pull8(ppReadPackedMsg, &value->nrs_antenna_ports_assumed_by_the_ue, end) && + pull8(ppReadPackedMsg, &value->subcarrier_indication, end) && + pull8(ppReadPackedMsg, &value->resource_assignment, end) && + pull8(ppReadPackedMsg, &value->scheduling_delay, end) && + pull8(ppReadPackedMsg, &value->mcs, end) && + pull8(ppReadPackedMsg, &value->redudancy_version, end) && + pull8(ppReadPackedMsg, &value->repetition_number, end) && + pull8(ppReadPackedMsg, &value->new_data_indicator, end) && + pull8(ppReadPackedMsg, &value->dci_subframe_repetition_number, end)); +} + +static uint8_t unpack_hi_dci0_request_body_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) +{ + nfapi_hi_dci0_request_body_t* value = (nfapi_hi_dci0_request_body_t*)tlv; + + if(!(pull16(ppReadPackedMsg, &value->sfnsf, end) && + pull8(ppReadPackedMsg, &value->number_of_dci, end) && + pull8(ppReadPackedMsg, &value->number_of_hi, end))) + return 0; + + uint8_t totalNumPdus = value->number_of_hi + value->number_of_dci; + + if(totalNumPdus > NFAPI_HI_DCI0_MAX_PDU) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s number of dci0 pdu's exceed maxium (count:%d max:%d)\n", __FUNCTION__, totalNumPdus, NFAPI_HI_DCI0_MAX_PDU); + return 0; + } + + if(totalNumPdus > 0) + { + value->hi_dci0_pdu_list = (nfapi_hi_dci0_request_pdu_t*)nfapi_p7_allocate(sizeof(nfapi_hi_dci0_request_pdu_t) * totalNumPdus, config); + if(value->hi_dci0_pdu_list == NULL) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s failed to allocate hi dci0 pdu list (count:%d)\n", __FUNCTION__, totalNumPdus); + return 0; + } + } + else + { + value->hi_dci0_pdu_list = 0; + } + + uint8_t i; + for(i = 0; i < totalNumPdus; ++i) + { + nfapi_hi_dci0_request_pdu_t* pdu = &(value->hi_dci0_pdu_list[i]); + + if(!(pull8(ppReadPackedMsg, &pdu->pdu_type, end) && + pull8(ppReadPackedMsg, &pdu->pdu_size, end))) + return 0; + + uint8_t *packedPduEnd = (*ppReadPackedMsg) + pdu->pdu_size - 2; + + if(packedPduEnd > end) + { + // pdu end if past buffer end + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s pdu size to big %d %d\n", __FUNCTION__, packedPduEnd, end); + return 0; + } + + switch(pdu->pdu_type) + { + case NFAPI_HI_DCI0_HI_PDU_TYPE: + { + unpack_tlv_t unpack_fns[] = + { + { NFAPI_HI_DCI0_REQUEST_HI_PDU_REL8_TAG, &pdu->hi_pdu.hi_pdu_rel8, &unpack_hi_dci0_hi_pdu_rel8_value}, + { NFAPI_HI_DCI0_REQUEST_HI_PDU_REL10_TAG, &pdu->hi_pdu.hi_pdu_rel10, &unpack_hi_dci0_hi_pdu_rel10_value}, + }; + + unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); + } + break; + case NFAPI_HI_DCI0_DCI_PDU_TYPE: + { + unpack_tlv_t unpack_fns[] = + { + { NFAPI_HI_DCI0_REQUEST_DCI_PDU_REL8_TAG, &pdu->dci_pdu.dci_pdu_rel8, &unpack_hi_dci0_dci_pdu_rel8_value}, + { NFAPI_HI_DCI0_REQUEST_DCI_PDU_REL10_TAG, &pdu->dci_pdu.dci_pdu_rel10, &unpack_hi_dci0_dci_pdu_rel10_value}, + { NFAPI_HI_DCI0_REQUEST_DCI_PDU_REL12_TAG, &pdu->dci_pdu.dci_pdu_rel12, &unpack_hi_dci0_dci_pdu_rel12_value}, + }; + + unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); + } + break; + case NFAPI_HI_DCI0_EPDCCH_DCI_PDU_TYPE: + { + unpack_tlv_t unpack_fns[] = + { + { NFAPI_HI_DCI0_REQUEST_EPDCCH_DCI_PDU_REL8_TAG, &pdu->epdcch_dci_pdu.epdcch_dci_pdu_rel8, &unpack_hi_dci0_dci_pdu_rel8_value}, + { NFAPI_HI_DCI0_REQUEST_EPDCCH_DCI_PDU_REL10_TAG, &pdu->epdcch_dci_pdu.epdcch_dci_pdu_rel10, &unpack_hi_dci0_dci_pdu_rel10_value}, + { NFAPI_HI_DCI0_REQUEST_EPDCCH_PARAMETERS_REL11_TAG, &pdu->epdcch_dci_pdu.epdcch_parameters_rel11, &unpack_dl_config_epdcch_params_rel11_value}, + }; + + unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); + } + break; + case NFAPI_HI_DCI0_MPDCCH_DCI_PDU_TYPE: + { + unpack_tlv_t unpack_fns[] = + { + { NFAPI_HI_DCI0_REQUEST_MPDCCH_DCI_PDU_REL13_TAG, &pdu->mpdcch_dci_pdu.mpdcch_dci_pdu_rel13, &unpack_hi_dci0_mpdcch_dci_pdu_rel13_value}, + }; + + unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); + } + break; + case NFAPI_HI_DCI0_NPDCCH_DCI_PDU_TYPE: + { + unpack_tlv_t unpack_fns[] = + { + { NFAPI_HI_DCI0_REQUEST_NPDCCH_DCI_PDU_REL13_TAG, &pdu->npdcch_dci_pdu.npdcch_dci_pdu_rel13, &unpack_hi_dci0_npdcch_dci_pdu_rel13_value}, + }; + + unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); + } + break; + default: + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "FIXME : Invalid pdu type %d \n", pdu->pdu_type ); + } + break; + }; + } + + return 1; +} +//unpack_ul_dci_pdu_list_value + +static uint8_t unpack_ul_dci_pdu_list_value(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg) +{ + nfapi_nr_ul_dci_request_pdus_t* value = (nfapi_nr_ul_dci_request_pdus_t*)msg; + for(uint8_t i = 0; i < MAX_DCI_CORESET; ++i) + { + if(!(pull16(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].RNTI, end) && + pull16(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].ScramblingId, end) && + + pull16(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].ScramblingRNTI, end) && + pull8(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].CceIndex, end) && + pull8(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].AggregationLevel, end) && + pull8(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].beta_PDCCH_1_0, end) && + + pull8(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].powerControlOffsetSS, end) && + pull16(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].PayloadSizeBits, end) && + + pullarray8(ppReadPackedMsg, value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].Payload, value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].PayloadSizeBits, value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].PayloadSizeBits, end))) + + return 0; + } + + return (pull16(ppReadPackedMsg, &value->PDUType, end) && + pull16(ppReadPackedMsg, &value->PDUSize, end) && + pull16(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.BWPSize, end) && + pull16(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.BWPStart, end) && + pull8(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.SubcarrierSpacing, end) && + pull8(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.CyclicPrefix, end) && + + pull8(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.StartSymbolIndex, end) && + pull8(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.DurationSymbols, end) && + pullarray8(ppReadPackedMsg, value->pdcch_pdu.pdcch_pdu_rel15.FreqDomainResource, 6, 6, end) && + pull8(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.CceRegMappingType, end) && + + pull8(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.RegBundleSize, end) && + pull8(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.InterleaverSize, end) && + pull8(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.CoreSetType, end) && + pull16(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.ShiftIndex, end) && + pull8(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.precoderGranularity, end) && + pull16(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.numDlDci, end)); + +} + +static uint8_t unpack_ul_dci_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config) +{ +nfapi_nr_ul_dci_request_t *pNfapiMsg = (nfapi_nr_ul_dci_request_t*)msg; + + if (!(pull16(ppReadPackedMsg, &pNfapiMsg->SFN, end) && + pull16(ppReadPackedMsg, &pNfapiMsg->Slot, end) && + pull8(ppReadPackedMsg, &pNfapiMsg->numPdus, end) + )) + return 0; + for(int i=0; i< pNfapiMsg->numPdus; i++) + { + if (!unpack_ul_dci_pdu_list_value(ppReadPackedMsg, end, &pNfapiMsg->ul_dci_pdu_list[i])) + return 0; + } + + return 1; + +} + +static uint8_t unpack_hi_dci0_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config) +{ + nfapi_hi_dci0_request_t *pNfapiMsg = (nfapi_hi_dci0_request_t*)msg; + + unpack_p7_tlv_t unpack_fns[] = + { + { NFAPI_HI_DCI0_REQUEST_BODY_TAG, &pNfapiMsg->hi_dci0_request_body, &unpack_hi_dci0_request_body_value}, + }; + + return (pull16(ppReadPackedMsg, &pNfapiMsg->sfn_sf, end) && + unpack_p7_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); + +} +static uint8_t unpack_tx_data_pdu_list_value(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg) +{ + nfapi_nr_pdu_t* pNfapiMsg = (nfapi_nr_pdu_t*)msg; + + if(!(pull32(ppReadPackedMsg, &pNfapiMsg->num_TLV, end) && + pull16(ppReadPackedMsg, &pNfapiMsg->PDU_index, end) && + pull16(ppReadPackedMsg, &pNfapiMsg->PDU_length, end) + )) + return 0; + + uint16_t i = 0; + uint16_t total_number_of_tlvs = pNfapiMsg->num_TLV; + for(; i < total_number_of_tlvs; ++i) + { + + if (!(pull16(ppReadPackedMsg, &pNfapiMsg->TLVs[i].length, end) && + pull16(ppReadPackedMsg, &pNfapiMsg->TLVs[i].tag, end))) + return 0; + + switch(pNfapiMsg->TLVs[i].tag){ + case 0: + { + if(!pullarray32(ppReadPackedMsg, pNfapiMsg->TLVs[i].value.direct, 16384, pNfapiMsg->TLVs[i].length, end)) + return 0; + break; + + } + + case 1: + { + if(!pullarray32(ppReadPackedMsg, pNfapiMsg->TLVs[i].value.ptr, pNfapiMsg->TLVs[i].length , pNfapiMsg->TLVs[i].length, end)) + return 0; + break; + + } + + default: + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "FIXME : Invalid tag value %d \n", pNfapiMsg->TLVs[i].tag ); + break; + } + + } + } + + + return 1; +} + +static uint8_t unpack_tx_data_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config) +{ + nfapi_nr_tx_data_request_t *pNfapiMsg = (nfapi_nr_tx_data_request_t*)msg; + + if(!(pull16(ppReadPackedMsg, &pNfapiMsg->SFN, end) && + pull16(ppReadPackedMsg, &pNfapiMsg->Slot, end) && + pull16(ppReadPackedMsg, &pNfapiMsg->Number_of_PDUs, end))) + return 0; + + for(int i=0; i< pNfapiMsg->Number_of_PDUs; i++) + { + if (!unpack_tx_data_pdu_list_value(ppReadPackedMsg, end, &pNfapiMsg->pdu_list[i])) + return 0; + } + + return 1; +} + +static uint8_t unpack_tx_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config) +{ + uint8_t proceed = 1; + nfapi_tx_request_t *pNfapiMsg = (nfapi_tx_request_t*)msg; + + if(pull16(ppReadPackedMsg, &pNfapiMsg->sfn_sf, end) == 0) + return 0; + + while (((uint8_t*)(*ppReadPackedMsg) < end) && proceed) + { + nfapi_tl_t generic_tl; + if(unpack_tl(ppReadPackedMsg, &generic_tl, end) == 0) + return 0; + + switch(generic_tl.tag) + { + case NFAPI_TX_REQUEST_BODY_TAG: + { + pNfapiMsg->tx_request_body.tl = generic_tl; + + if( pull16(ppReadPackedMsg, &pNfapiMsg->tx_request_body.number_of_pdus, end) == 0) + return 0; + + if(pNfapiMsg->tx_request_body.number_of_pdus > NFAPI_TX_MAX_PDU) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s number of tx pdu's exceed maxium (count:%d max:%d)\n", __FUNCTION__, pNfapiMsg->tx_request_body.number_of_pdus, NFAPI_TX_MAX_PDU); + return 0; + } + + if(pNfapiMsg->tx_request_body.number_of_pdus > 0) + { + pNfapiMsg->tx_request_body.tx_pdu_list = (nfapi_tx_request_pdu_t*)nfapi_p7_allocate(sizeof(nfapi_tx_request_pdu_t) * pNfapiMsg->tx_request_body.number_of_pdus, config); + if(pNfapiMsg->tx_request_body.tx_pdu_list == NULL) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s failed to allocate tx pdu list (count:%d)\n", __FUNCTION__, pNfapiMsg->tx_request_body.number_of_pdus); + return 0; + } + } + else + { + pNfapiMsg->tx_request_body.tx_pdu_list = 0; + } + + + uint16_t i; + uint16_t totalNumPdus = pNfapiMsg->tx_request_body.number_of_pdus; + for(i = 0; i < totalNumPdus; ++i) + { + nfapi_tx_request_pdu_t* pdu = &(pNfapiMsg->tx_request_body.tx_pdu_list[i]); + if (pdu) { + uint16_t length = 0; + uint16_t index = 0; + + if(!(pull16(ppReadPackedMsg, &length, end) && + pull16(ppReadPackedMsg, &index, end))) + return 0; + + pdu->pdu_length = length; + pdu->pdu_index = index; + + + // TODO : May need to rethink this bit + pdu->num_segments = 1; + pdu->segments[0].segment_length = pdu->pdu_length; + pdu->segments[0].segment_data = nfapi_p7_allocate(pdu->pdu_length, config); + + if(pdu->segments[0].segment_data) + { + if(!pullarray8(ppReadPackedMsg, pdu->segments[0].segment_data, pdu->segments[0].segment_length, pdu->segments[0].segment_length, end)) + return 0; + if (pdu->segments[0].segment_length == 3) + { + NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() BCH? segment_data:%x %x %x\n", __FUNCTION__, + pdu->segments[0].segment_data[0], + pdu->segments[0].segment_data[1], + pdu->segments[0].segment_data[2] + ); + } + } + else + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "unpack_tx_request: Failed to allocate pdu (len:%d) %d/%d %d\n", pdu->pdu_length, totalNumPdus, i, pdu->pdu_index); + } + } else { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "NULL pdu\n"); + } + } + } + break; + default: + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "unpack_tx_request FIXME : Invalid pdu type %d \n", generic_tl.tag ); + } + break; + }; + } + + return 1; +} + + +//UNPACK NR UPLINK INDICATION FUNCTIONS + +//RX DATA INDICATION + +static uint8_t unpack_nr_rx_data_indication_body(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_nr_rx_data_pdu_t* value = (nfapi_nr_rx_data_pdu_t*)tlv; + + if(!(pull32(ppReadPackedMsg, &value->handle, end) && + pull16(ppReadPackedMsg, &value->rnti, end) && + pull8(ppReadPackedMsg, &value->harq_id, end) && + pull16(ppReadPackedMsg, &value->pdu_length, end) && + pull8(ppReadPackedMsg, &value->ul_cqi, end) && + pull16(ppReadPackedMsg, &value->timing_advance, end) && + pull16(ppReadPackedMsg, &value->rssi, end) + )) + return 0; + return 1; +} + + +static uint8_t unpack_nr_rx_data_indication(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config) +{ + // uint8_t *ptr = *ppReadPackedMsg; + // printf("\n Read P7 message rx data indication unpack: "); + // while(ptr < end){ + // printf(" %d ", *ptr); + // ptr++; + // } + // printf("\n"); + nfapi_nr_rx_data_indication_t *pNfapiMsg = (nfapi_nr_rx_data_indication_t*)msg; + + printf("\n"); + if (!(pull16(ppReadPackedMsg, &pNfapiMsg->sfn , end) && + pull16(ppReadPackedMsg, &pNfapiMsg->slot , end) && + pull16(ppReadPackedMsg, &pNfapiMsg->number_of_pdus, end) + )) + return 0; + + for(int i=0; inumber_of_pdus;i++) + { + if(!unpack_nr_rx_data_indication_body(&pNfapiMsg->pdu_list, ppReadPackedMsg, end)) + return 0; + } + +return 1; +} + +//NR CRC INDICATION + +static uint8_t unpack_nr_crc_indication_body(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_nr_crc_t* value = (nfapi_nr_crc_t*)tlv; + + if(!(pull32(ppReadPackedMsg, &value->handle, end) && + pull16(ppReadPackedMsg, &value->rnti, end) && + pull8(ppReadPackedMsg, &value->harq_id, end) && + pull8(ppReadPackedMsg, &value->tb_crc_status, end) && + pull16(ppReadPackedMsg, &value->num_cb, end) && + //pullarray8(ppReadPackedMsg, value->cb_crc_status, (int)(value->num_cb / 8) + 1, (int)(value->num_cb / 8) + 1, end) && //length is ceil(NumCb/8) + pull8(ppReadPackedMsg, &value->ul_cqi, end) && + pull16(ppReadPackedMsg, &value->timing_advance, end) && + pull16(ppReadPackedMsg, &value->rssi, end) + )) + return 0; + + return 1; +} + +static uint8_t unpack_nr_crc_indication(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config) +{ + uint8_t *ptr = *ppReadPackedMsg; + // printf("\n Read P7 message indication unpack: "); + // while(ptr < end){ + // printf(" %d ", *ptr); + // ptr++; + // } + // printf("\n"); + nfapi_nr_crc_indication_t *pNfapiMsg = (nfapi_nr_crc_indication_t*)msg; + + if (!(pull16(ppReadPackedMsg, &pNfapiMsg->sfn , end) && + pull16(ppReadPackedMsg, &pNfapiMsg->slot , end) && + pull16(ppReadPackedMsg, &pNfapiMsg->number_crcs, end) + )) + return 0; + + for(int i=0; inumber_crcs;i++) + { + if(!unpack_nr_crc_indication_body(&pNfapiMsg->crc_list,ppReadPackedMsg,end)) + return 0; + } + +return 1; +} + +//SRS INDICATION + +static uint8_t unpack_nr_srs_indication_body(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_nr_srs_indication_pdu_t* value = (nfapi_nr_srs_indication_pdu_t*)tlv; + + if(!(pull32(ppReadPackedMsg, &value->handle, end) && + pull16(ppReadPackedMsg, &value->rnti, end) && + pull16(ppReadPackedMsg, &value->timing_advance, end) && + pull8(ppReadPackedMsg, &value->num_symbols, end) && + pull8(ppReadPackedMsg, &value->wide_band_snr, end) && + pull8(ppReadPackedMsg, &value->num_reported_symbols, end) && + pull16(ppReadPackedMsg, &value->reported_symbol_list->num_rbs, end) + )) + return 0; + for(int i = 0; i < value->reported_symbol_list->num_rbs; i++) + { + if(!(pull8(ppReadPackedMsg, &value->reported_symbol_list->rb_list->rb_snr, end) + )) + return 0; + } + return 1; +} + +static uint8_t unpack_nr_srs_indication(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config) +{ + nfapi_nr_srs_indication_t *pNfapiMsg = (nfapi_nr_srs_indication_t*)msg; + + if (!(pull16(ppReadPackedMsg,&pNfapiMsg->sfn , end) && + pull16(ppReadPackedMsg,&pNfapiMsg->slot , end) && + pull8(ppReadPackedMsg,&pNfapiMsg->number_of_pdus, end) + )) + return 0; + + for(int i=0; inumber_of_pdus;i++) + { + if(!unpack_nr_srs_indication_body(&pNfapiMsg->pdu_list,ppReadPackedMsg,end)) + return 0; + } + +return 1; +} + +//NR RACH + +static uint8_t unpack_nr_rach_indication_body(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_nr_prach_indication_pdu_t* value = (nfapi_nr_prach_indication_pdu_t*)tlv; + + if(!(pull16(ppReadPackedMsg, &value->phy_cell_id, end) && + pull8(ppReadPackedMsg, &value->symbol_index, end) && + pull8(ppReadPackedMsg, &value->slot_index, end) && + pull8(ppReadPackedMsg, &value->freq_index, end) && + pull8(ppReadPackedMsg, &value->avg_rssi, end) && + pull8(ppReadPackedMsg, &value->avg_snr, end) && + pull8(ppReadPackedMsg, &value->num_preamble, end) + )) + return 0; + for(int i = 0; i < value->num_preamble; i++) + { + if(!(pull8(ppReadPackedMsg, &value->preamble_list->preamble_index, end) && + pull16(ppReadPackedMsg, &value->preamble_list->timing_advance, end) && + pull32(ppReadPackedMsg, &value->preamble_list->preamble_pwr, end) + )) + return 0; + } + return 1; +} + +static uint8_t unpack_nr_rach_indication(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config) { + + nfapi_nr_rach_indication_t *pNfapiMsg = (nfapi_nr_rach_indication_t*)msg; + if (!(pull16(ppReadPackedMsg, &pNfapiMsg->sfn , end) && + pull16(ppReadPackedMsg, &pNfapiMsg->slot , end) && + pull8(ppReadPackedMsg, &pNfapiMsg->number_of_pdus, end) + )) + return 0; + + for(int i=0; i< pNfapiMsg->number_of_pdus;i++) + { + if(!unpack_nr_rach_indication_body(&pNfapiMsg->pdu_list,ppReadPackedMsg,end)) + return 0; + } + +return 1; +} + +//NR UCI + +static uint8_t unpack_nr_uci_pucch_0_1(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_nr_uci_pucch_pdu_format_0_1_t* value = (nfapi_nr_uci_pucch_pdu_format_0_1_t*)tlv; + + uint8_t *ptr = *ppReadPackedMsg; + printf("\n Read P7 message uci_0_1 indication unpack: "); + while(ptr < end){ + printf(" %d ", *ptr); + ptr++; + } + printf("\n"); + + if(!(pull8(ppReadPackedMsg, &value->pduBitmap, end) && + pull32(ppReadPackedMsg, &value->handle, end) && + pull16(ppReadPackedMsg, &value->rnti, end) && + pull8(ppReadPackedMsg, &value->pucch_format, end) && + pull8(ppReadPackedMsg, &value->ul_cqi, end) && + pull16(ppReadPackedMsg, &value->timing_advance, end) && + pull16(ppReadPackedMsg, &value->rssi, end) + )) + return 0; + if (value->pduBitmap & 0x01) { //SR + if(!(pull8(ppReadPackedMsg, &value->sr->sr_indication, end) && + pull8(ppReadPackedMsg, &value->sr->sr_confidence_level, end) + )) + return 0; + } + + // if (((value->pduBitmap >> 1) & 0x01)) { //HARQ + // uint8_t* temp; //&value->harq->num_harq &value->harq->harq_confidence_level &value->harq->harq_list[0].harq_value + // temp = (uint8_t*) malloc(sizeof(uint8_t)); + // //printf("value->harq->num_harq = %d \n", value->harq->num_harq); + // // if(!(pull8(ppReadPackedMsg, temp, end) && + // // pull8(ppReadPackedMsg, temp, end) + // // )) + // // return 0; + + // // for(int i=0; i<1;i++) + // // { + // // if(!(pull8(ppReadPackedMsg, temp, end) + // // )) + // // return 0; + // // } + // } + + return 1; +} + + +static uint8_t unpack_nr_uci_pucch_2_3_4(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_nr_uci_pucch_pdu_format_2_3_4_t* value = (nfapi_nr_uci_pucch_pdu_format_2_3_4_t*) tlv; + + if(!(pull8(ppReadPackedMsg, &value->pduBitmap, end) && + pull32(ppReadPackedMsg, &value->handle, end) && + pull16(ppReadPackedMsg, &value->rnti, end) && + pull8(ppReadPackedMsg, &value->pucch_format, end) && + pull8(ppReadPackedMsg, &value->ul_cqi, end) && + pull16(ppReadPackedMsg, &value->timing_advance, end) && + pull16(ppReadPackedMsg, &value->rssi, end) + )) + return 0; + if (value->pduBitmap & 0x01) { //SR + if(!(pull16(ppReadPackedMsg, &value->sr.sr_bit_len, end) && + pullarray8(ppReadPackedMsg, value->sr.sr_payload, (int)(value->sr.sr_bit_len / 8) + 1, (int)(value->sr.sr_bit_len / 8) + 1, end) + )) + return 0; + } + + if (((value->pduBitmap >> 1) & 0x01)) { //HARQ + if(!(pull8(ppReadPackedMsg, &value->harq.harq_crc, end) && + pull16(ppReadPackedMsg, &value->harq.harq_bit_len, end) && + pullarray8(ppReadPackedMsg, value->harq.harq_payload, (int)(value->harq.harq_bit_len / 8) + 1, (int)(value->harq.harq_bit_len / 8) + 1, end) + )) + return 0; + } + + if (((value->pduBitmap >> 2) & 0x01)) { //CSI-1 + if(!(pull8(ppReadPackedMsg, &value->csi_part1.csi_part1_crc, end) && + pull16(ppReadPackedMsg, &value->csi_part1.csi_part1_bit_len, end) && + pullarray8(ppReadPackedMsg, value->csi_part1.csi_part1_payload, (int)(value->csi_part1.csi_part1_bit_len / 8) + 1, (int)(value->csi_part1.csi_part1_bit_len / 8) + 1, end) + )) + return 0; + } + + if (((value->pduBitmap >> 3) & 0x01)) { //CSI-2 + if(!(pull8(ppReadPackedMsg, &value->csi_part2.csi_part2_crc, end) && + pull16(ppReadPackedMsg, &value->csi_part2.csi_part2_bit_len, end) && + pullarray8(ppReadPackedMsg, value->csi_part2.csi_part2_payload, (int)(value->csi_part2.csi_part2_bit_len / 8) + 1, (int)(value->csi_part2.csi_part2_bit_len / 8) + 1, end) + )) + return 0; + } + + return 1; +} + +static uint8_t unpack_nr_uci_indication_body(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_nr_uci_t* value = (nfapi_nr_uci_t*)tlv; + + if(!(pull16(ppReadPackedMsg, &value->pdu_type, end) && + pull16(ppReadPackedMsg, &value->pdu_size, end) + )) + return 0; + + switch (value->pdu_type) { + case NFAPI_NR_UCI_PUSCH_PDU_TYPE: + printf("Unhandled NFAPI_NR_UCI_PUSCH_PDU_TYPE \n"); + break; + + case NFAPI_NR_UCI_FORMAT_0_1_PDU_TYPE: { + nfapi_nr_uci_pucch_pdu_format_0_1_t* uci_pdu = &value->pucch_pdu_format_0_1; + unpack_nr_uci_pucch_0_1(&uci_pdu, ppReadPackedMsg, end); + break; + } + case NFAPI_NR_UCI_FORMAT_2_3_4_PDU_TYPE: { + nfapi_nr_uci_pucch_pdu_format_2_3_4_t *uci_pdu = &value->pucch_pdu_format_2_3_4; + unpack_nr_uci_pucch_2_3_4(&uci_pdu, ppReadPackedMsg, end); + break; + } + } + + return 1; +} + +static uint8_t unpack_nr_uci_indication(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config) +{ + nfapi_nr_uci_indication_t *pNfapiMsg = (nfapi_nr_uci_indication_t*)msg; + + if (!(pull16(ppReadPackedMsg, &pNfapiMsg->sfn , end) && + pull16(ppReadPackedMsg, &pNfapiMsg->slot , end) && + pull16(ppReadPackedMsg, &pNfapiMsg->num_ucis, end) + )) + return 0; + + for(int i=0; inum_ucis;i++) + { + if(!unpack_nr_uci_indication_body(&pNfapiMsg->uci_list,ppReadPackedMsg,end)) + return 0; + } + +return 1; +} + + +static uint8_t unpack_ue_release_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config) +{ + uint8_t proceed = 1; + nfapi_ue_release_request_t *pNfapiMsg = (nfapi_ue_release_request_t*)msg; + + if(pull16(ppReadPackedMsg, &pNfapiMsg->sfn_sf, end) == 0) + return 0; + + while (((uint8_t*)(*ppReadPackedMsg) < end) && proceed) + { + nfapi_tl_t generic_tl; + if(unpack_tl(ppReadPackedMsg, &generic_tl, end) == 0) + return 0; + + switch(generic_tl.tag) + { + case NFAPI_UE_RELEASE_BODY_TAG: + { + pNfapiMsg->ue_release_request_body.tl = generic_tl; + if( pull16(ppReadPackedMsg, &pNfapiMsg->ue_release_request_body.number_of_TLVs, end) == 0) + return 0; + + if(pNfapiMsg->ue_release_request_body.number_of_TLVs > NFAPI_RELEASE_MAX_RNTI) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s number of relese rnti's exceed maxium (count:%d max:%d)\n", __FUNCTION__, pNfapiMsg->ue_release_request_body.number_of_TLVs, NFAPI_RELEASE_MAX_RNTI); + return 0; + } else { + uint8_t j; + uint16_t num = pNfapiMsg->ue_release_request_body.number_of_TLVs; + for(j = 0; j < num; ++j){ + if(pull16(ppReadPackedMsg, &pNfapiMsg->ue_release_request_body.ue_release_request_TLVs_list[j].rnti, end) == 0){ + return 0; + } + } + } + } + break; + default: + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "unpack_ue_release_request FIXME : Invalid type %d \n", generic_tl.tag ); + } + break; + }; + } + + return 1; +} + +static uint8_t unpack_harq_indication_tdd_harq_data_bundling(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_harq_indication_tdd_harq_data_bundling_t* value = (nfapi_harq_indication_tdd_harq_data_bundling_t*)tlv; + + return (pull8(ppReadPackedMsg, &value->value_0, end) && + pull8(ppReadPackedMsg, &value->value_1, end)); +} + +static uint8_t unpack_harq_indication_tdd_harq_data_multiplexing(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_harq_indication_tdd_harq_data_multiplexing_t* value = (nfapi_harq_indication_tdd_harq_data_multiplexing_t*)tlv; + + return (pull8(ppReadPackedMsg, &value->value_0, end) && + pull8(ppReadPackedMsg, &value->value_1, end) && + pull8(ppReadPackedMsg, &value->value_2, end) && + pull8(ppReadPackedMsg, &value->value_3, end)); +} +static uint8_t unpack_harq_indication_tdd_harq_data_special_bundling(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_harq_indication_tdd_harq_data_special_bundling_t* value = (nfapi_harq_indication_tdd_harq_data_special_bundling_t*)tlv; + return ( pull8(ppReadPackedMsg, &value->value_0, end)); +} +static uint8_t unpack_harq_indication_tdd_harq_data(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_harq_indication_tdd_harq_data_t* value = (nfapi_harq_indication_tdd_harq_data_t*)tlv; + return (pull8(ppReadPackedMsg, &value->value_0, end)); +} + +static uint8_t unpack_harq_indication_tdd_rel8_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_harq_indication_tdd_rel8_t* value = (nfapi_harq_indication_tdd_rel8_t*)tlv; + + if(!(pull8(ppReadPackedMsg, &value->mode, end) && + pull8(ppReadPackedMsg, &value->number_of_ack_nack, end))) + return 0; + + uint8_t result = 0; + switch(value->mode) + { + case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_BUNDLING: + result = unpack_harq_indication_tdd_harq_data_bundling(&value->harq_data.bundling, ppReadPackedMsg, end); + break; + case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_MULIPLEXING: + result = unpack_harq_indication_tdd_harq_data_multiplexing(&value->harq_data.multiplex, ppReadPackedMsg, end); + break; + case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_SPECIAL_BUNDLING: + result = unpack_harq_indication_tdd_harq_data_special_bundling(&value->harq_data.special_bundling, ppReadPackedMsg, end); + break; + case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_FORMAT_3: + case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_CHANNEL_SELECTION: + result = 1; + break; + default: + // TODO add error message + return 0; + break; + } + return result; +} + +static uint8_t unpack_harq_indication_tdd_rel9_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_harq_indication_tdd_rel9_t* value = (nfapi_harq_indication_tdd_rel9_t*)tlv; + + if(!(pull8(ppReadPackedMsg, &value->mode, end) && + pull8(ppReadPackedMsg, &value->number_of_ack_nack, end))) + return 0; + + if(value->number_of_ack_nack > NFAPI_MAX_NUMBER_ACK_NACK_TDD) + { + // TODO : add error message + return 0; + } + + uint16_t idx = 0; + for(idx = 0; idx < value->number_of_ack_nack; ++idx) + { + uint8_t result = 0; + switch(value->mode) + { + case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_BUNDLING: + result = unpack_harq_indication_tdd_harq_data(&value->harq_data[idx].bundling, ppReadPackedMsg, end); + break; + case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_MULIPLEXING: + result = unpack_harq_indication_tdd_harq_data(&value->harq_data[idx].multiplex, ppReadPackedMsg, end); + break; + case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_SPECIAL_BUNDLING: + result = unpack_harq_indication_tdd_harq_data_special_bundling(&value->harq_data[idx].special_bundling, ppReadPackedMsg, end); + break; + case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_CHANNEL_SELECTION: + result = unpack_harq_indication_tdd_harq_data(&value->harq_data[idx].channel_selection, ppReadPackedMsg, end); + break; + case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_FORMAT_3: + result = unpack_harq_indication_tdd_harq_data(&value->harq_data[idx].format_3, ppReadPackedMsg, end); + break; + default: + // TODO add error message + return 0; + break; + } + + if(result == 0) + return 0; + } + return 1; +} + +static uint8_t unpack_harq_indication_tdd_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_harq_indication_tdd_rel13_t* value = (nfapi_harq_indication_tdd_rel13_t*)tlv; + + if(!(pull8(ppReadPackedMsg, &value->mode, end) && + pull16(ppReadPackedMsg, &value->number_of_ack_nack, end))) + return 0; + + if(value->number_of_ack_nack > NFAPI_MAX_NUMBER_ACK_NACK_TDD) + { + // TODO : add error message + return 0; + } + + uint16_t idx = 0; + for(idx = 0; idx < value->number_of_ack_nack; ++idx) + { + uint8_t result = 0; + switch(value->mode) + { + case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_BUNDLING: + result = unpack_harq_indication_tdd_harq_data(&value->harq_data[idx].bundling, ppReadPackedMsg, end); + break; + case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_MULIPLEXING: + result = unpack_harq_indication_tdd_harq_data(&value->harq_data[idx].multiplex, ppReadPackedMsg, end); + break; + case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_SPECIAL_BUNDLING: + result = unpack_harq_indication_tdd_harq_data_special_bundling(&value->harq_data[idx].special_bundling, ppReadPackedMsg, end); + break; + case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_CHANNEL_SELECTION: + result = unpack_harq_indication_tdd_harq_data(&value->harq_data[idx].channel_selection, ppReadPackedMsg, end); + break; + case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_FORMAT_3: + result = unpack_harq_indication_tdd_harq_data(&value->harq_data[idx].format_3, ppReadPackedMsg, end); + break; + case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_FORMAT_4: + result = unpack_harq_indication_tdd_harq_data(&value->harq_data[idx].format_4, ppReadPackedMsg, end); + break; + case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_FORMAT_5: + result = unpack_harq_indication_tdd_harq_data(&value->harq_data[idx].format_5, ppReadPackedMsg, end); + break; + default: + // TODO add error message + return 0; + break; + } + + if(result == 0) + return 0; + } + return 1; +} + +static uint8_t unpack_harq_indication_fdd_rel8_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_harq_indication_fdd_rel8_t* value = (nfapi_harq_indication_fdd_rel8_t*)tlv; + return (pull8(ppReadPackedMsg, &value->harq_tb1, end) && + pull8(ppReadPackedMsg, &value->harq_tb2, end)); +} + +static uint8_t unpack_harq_indication_fdd_rel9_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_harq_indication_fdd_rel9_t* value = (nfapi_harq_indication_fdd_rel9_t*)tlv; + + return (pull8(ppReadPackedMsg, &value->mode, end) && + pull8(ppReadPackedMsg, &value->number_of_ack_nack, end) && + pullarray8(ppReadPackedMsg, value->harq_tb_n, NFAPI_HARQ_ACK_NACK_REL9_MAX, value->number_of_ack_nack, end)); +} + +static uint8_t unpack_harq_indication_fdd_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_harq_indication_fdd_rel13_t* value = (nfapi_harq_indication_fdd_rel13_t*)tlv; + + return (pull8(ppReadPackedMsg, &value->mode, end) && + pull16(ppReadPackedMsg, &value->number_of_ack_nack, end) && + pullarray8(ppReadPackedMsg, value->harq_tb_n, NFAPI_HARQ_ACK_NACK_REL13_MAX, value->number_of_ack_nack, end)); +} + +static uint8_t unpack_ul_cqi_information_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_ul_cqi_information_t* value = (nfapi_ul_cqi_information_t*)tlv; + + return (pull8(ppReadPackedMsg, &value->ul_cqi, end) && + pull8(ppReadPackedMsg, &value->channel, end)); +} + + + +static uint8_t unpack_harq_indication_body_value(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) +{ + nfapi_harq_indication_body_t* value = (nfapi_harq_indication_body_t*)tlv; + uint8_t* harqBodyEnd = *ppReadPackedMsg + value->tl.length; + + if(harqBodyEnd > end) + return 0; + + if(pull16(ppReadPackedMsg, &value->number_of_harqs, end) == 0) + return 0; + + if(value->number_of_harqs > NFAPI_HARQ_IND_MAX_PDU) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s number of harq ind pdus exceed maxium (count:%d max:%d)\n", __FUNCTION__, value->number_of_harqs, NFAPI_HARQ_IND_MAX_PDU); + return 0; + } + + value->harq_pdu_list = (nfapi_harq_indication_pdu_t*)nfapi_p7_allocate(sizeof(nfapi_harq_indication_pdu_t) * value->number_of_harqs, config); + if(value->harq_pdu_list == NULL) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s failed to allocate harq ind pdu list (count:%d)\n", __FUNCTION__, value->number_of_harqs); + return 0; + } + + uint8_t i = 0; + for(i = 0; i < value->number_of_harqs; ++i) + { + nfapi_harq_indication_pdu_t* pdu = &(value->harq_pdu_list[i]); + if(pull16(ppReadPackedMsg, &pdu->instance_length, end) == 0) + return 0; + + uint8_t* harqPduInstanceEnd = *ppReadPackedMsg + pdu->instance_length; + + unpack_tlv_t unpack_fns[] = + { + { NFAPI_RX_UE_INFORMATION_TAG, &pdu->rx_ue_information, unpack_rx_ue_information_value }, + { NFAPI_HARQ_INDICATION_TDD_REL8_TAG, &pdu->harq_indication_tdd_rel8, &unpack_harq_indication_tdd_rel8_value}, + { NFAPI_HARQ_INDICATION_TDD_REL9_TAG, &pdu->harq_indication_tdd_rel9, &unpack_harq_indication_tdd_rel9_value}, + { NFAPI_HARQ_INDICATION_TDD_REL13_TAG, &pdu->harq_indication_tdd_rel13, &unpack_harq_indication_tdd_rel13_value}, + { NFAPI_HARQ_INDICATION_FDD_REL8_TAG, &pdu->harq_indication_fdd_rel8, &unpack_harq_indication_fdd_rel8_value}, + { NFAPI_HARQ_INDICATION_FDD_REL9_TAG, &pdu->harq_indication_fdd_rel9, &unpack_harq_indication_fdd_rel9_value}, + { NFAPI_HARQ_INDICATION_FDD_REL13_TAG, &pdu->harq_indication_fdd_rel13, &unpack_harq_indication_fdd_rel13_value}, + { NFAPI_UL_CQI_INFORMATION_TAG, &pdu->ul_cqi_information, &unpack_ul_cqi_information_value} + }; + + if(unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, harqPduInstanceEnd, 0, 0) == 0) + return 0; + + } + + return 1; +} + +static uint8_t unpack_harq_indication(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config) +{ + nfapi_harq_indication_t *pNfapiMsg = (nfapi_harq_indication_t*)msg; + + unpack_p7_tlv_t unpack_fns[] = + { + { NFAPI_HARQ_INDICATION_BODY_TAG, &pNfapiMsg->harq_indication_body, &unpack_harq_indication_body_value}, + }; + + return (pull16(ppReadPackedMsg, &pNfapiMsg->sfn_sf, end) && + unpack_p7_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); +} + +static uint8_t unpack_crc_indication_rel8_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_crc_indication_rel8_t* crc_pdu_rel8 = (nfapi_crc_indication_rel8_t*)tlv; + return ( pull8(ppReadPackedMsg, &crc_pdu_rel8->crc_flag, end) ); +} + +static uint8_t unpack_crc_indication_body_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) +{ + nfapi_crc_indication_body_t* value = (nfapi_crc_indication_body_t*)tlv; + uint8_t* crcBodyEnd = *ppReadPackedMsg + value->tl.length; + + if(crcBodyEnd > end) + return 0; + + if(pull16(ppReadPackedMsg, &value->number_of_crcs, end) == 0) + return 0; + + if(value->number_of_crcs > NFAPI_CRC_IND_MAX_PDU) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s number of crc ind pdu's exceed maxium (count:%d max:%d)\n", __FUNCTION__, value->number_of_crcs, NFAPI_CRC_IND_MAX_PDU); + return 0; + } + + if(value->number_of_crcs > 0) + { + value->crc_pdu_list = (nfapi_crc_indication_pdu_t*)nfapi_p7_allocate(sizeof(nfapi_crc_indication_pdu_t) * value->number_of_crcs, config); + if(value->crc_pdu_list == NULL) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s failed to allocate crc ind pdu list (count:%d)\n", __FUNCTION__, value->number_of_crcs); + return 0; + } + } + else + { + value->crc_pdu_list = 0; + } + + + uint8_t i = 0; + for(i = 0; i < value->number_of_crcs; ++i) + { + nfapi_crc_indication_pdu_t* pdu = &(value->crc_pdu_list[i]); + + if(pull16(ppReadPackedMsg, &pdu->instance_length, end) == 0) + return 0; + + uint8_t* crcPduInstanceEnd = *ppReadPackedMsg + pdu->instance_length; + + + unpack_tlv_t unpack_fns[] = + { + { NFAPI_RX_UE_INFORMATION_TAG, &pdu->rx_ue_information, unpack_rx_ue_information_value }, + { NFAPI_CRC_INDICATION_REL8_TAG, &pdu->crc_indication_rel8, unpack_crc_indication_rel8_value }, + }; + + if(unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, crcPduInstanceEnd, 0, 0) == 0) + return 0; + } + + return 1; +} + +static uint8_t unpack_crc_indication(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config) +{ + nfapi_crc_indication_t *pNfapiMsg = (nfapi_crc_indication_t*)msg; + + unpack_p7_tlv_t unpack_fns[] = + { + { NFAPI_CRC_INDICATION_BODY_TAG, &pNfapiMsg->crc_indication_body, &unpack_crc_indication_body_value}, + }; + + return (pull16(ppReadPackedMsg, &pNfapiMsg->sfn_sf, end) && + unpack_p7_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); +} + +static uint8_t unpack_rx_indication_rel8_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_rx_indication_rel8_t* value = (nfapi_rx_indication_rel8_t*)tlv; + + return (pull16(ppReadPackedMsg, &value->length, end) && + pull16(ppReadPackedMsg, &value->offset, end) && + pull8(ppReadPackedMsg, &value->ul_cqi, end) && + pull16(ppReadPackedMsg, &value->timing_advance, end)); +} +static uint8_t unpack_rx_indication_rel9_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_rx_indication_rel9_t* value = (nfapi_rx_indication_rel9_t*)tlv; + return (pull16(ppReadPackedMsg, &value->timing_advance_r9, end)); +} + +static uint8_t unpack_rx_indication_body_value(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) +{ + nfapi_rx_indication_body_t* value = (nfapi_rx_indication_body_t*)tlv; + + // the rxBodyEnd points to the end of the cqi PDU's + uint8_t* rxBodyEnd = *ppReadPackedMsg + value->tl.length; + uint8_t* rxPduEnd = rxBodyEnd; + + uint8_t* numberOfPdusAddress = *ppReadPackedMsg; + + if(rxBodyEnd > end) + { + // pdu end is past buffer end + return 0; + } + + if(pull16(ppReadPackedMsg, &value->number_of_pdus, end) == 0) + return 0; + + if(value->number_of_pdus > NFAPI_RX_IND_MAX_PDU) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s number of rx ind pdu's exceed maxium (count:%d max:%d)\n", __FUNCTION__, value->number_of_pdus, NFAPI_RX_IND_MAX_PDU); + return 0; + } + + if(value->number_of_pdus > 0) + { + value->rx_pdu_list = (nfapi_rx_indication_pdu_t*)nfapi_p7_allocate(sizeof(nfapi_rx_indication_pdu_t) * value->number_of_pdus, config); + if(value->rx_pdu_list == NULL) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s failed to allocate rx ind pdu list (count:%d)\n", __FUNCTION__, value->number_of_pdus); + return 0; + } + } + else + { + value->rx_pdu_list = 0; + } + + uint8_t i = 0; + nfapi_rx_indication_pdu_t* pdu = 0; + while((uint8_t*)(*ppReadPackedMsg) < rxBodyEnd && (uint8_t*)(*ppReadPackedMsg) < rxPduEnd) + { + nfapi_tl_t generic_tl; + if( unpack_tl(ppReadPackedMsg, &generic_tl, end) == 0) + return 0; + + switch(generic_tl.tag) + { + case NFAPI_RX_UE_INFORMATION_TAG: + { + pdu = &(value->rx_pdu_list[i++]); + pdu->rx_ue_information.tl = generic_tl; + if(unpack_rx_ue_information_value(&pdu->rx_ue_information, ppReadPackedMsg, end) == 0) + return 0; + } + break; + case NFAPI_RX_INDICATION_REL8_TAG: + { + if(pdu != 0) + { + pdu->rx_indication_rel8.tl = generic_tl; + if(unpack_rx_indication_rel8_value(&pdu->rx_indication_rel8, ppReadPackedMsg, end) == 0) + return 0; + + if(pdu->rx_indication_rel8.offset > 0) + { + // Need to check that the data is within the tlv + if(numberOfPdusAddress + pdu->rx_indication_rel8.offset + pdu->rx_indication_rel8.length <= rxBodyEnd) + { + // If this the first pdu set the rxPduEnd + if(numberOfPdusAddress + pdu->rx_indication_rel8.offset < rxPduEnd) + { + rxPduEnd = numberOfPdusAddress + pdu->rx_indication_rel8.offset; + + if(rxPduEnd > end) + { + // pdu end is past buffer end + return 0; + } + } + } + else + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "FIXME: the rx data is outside of the tlv\n"); + } + } + } + } + break; + case NFAPI_RX_INDICATION_REL9_TAG: + { + if(pdu != 0) + { + pdu->rx_indication_rel9.tl = generic_tl; + if(unpack_rx_indication_rel9_value(&pdu->rx_indication_rel9, ppReadPackedMsg, end) == 0) + return 0; + } + } + break; + default: + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "RX_ULSCH.indication Invalid pdu type %d \n", generic_tl.tag ); + } + break; + } + } + + uint8_t idx = 0; + for(idx = 0; idx < value->number_of_pdus; ++idx) + { + if(value->rx_pdu_list[idx].rx_indication_rel8.tl.tag == NFAPI_RX_INDICATION_REL8_TAG) + { + uint32_t length = value->rx_pdu_list[idx].rx_indication_rel8.length; + value->rx_pdu_list[idx].data = nfapi_p7_allocate(length, config); + if(pullarray8(ppReadPackedMsg, value->rx_pdu_list[idx].data, length, length, end) == 0) + { + return 0; + } + } + } + + return 1; +} + +static uint8_t unpack_rx_indication(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config) +{ + nfapi_rx_indication_t *pNfapiMsg = (nfapi_rx_indication_t*)msg; + + unpack_p7_tlv_t unpack_fns[] = + { + { NFAPI_RX_INDICATION_BODY_TAG, &pNfapiMsg->rx_indication_body, &unpack_rx_indication_body_value}, + }; + + return (pull16(ppReadPackedMsg, &pNfapiMsg->sfn_sf, end) && + unpack_p7_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); +} + +static uint8_t unpack_preamble_pdu_rel8_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_preamble_pdu_rel8_t* preamble_pdu_rel8 = (nfapi_preamble_pdu_rel8_t*)tlv; + + return (pull16(ppReadPackedMsg, &preamble_pdu_rel8->rnti, end) && + pull8(ppReadPackedMsg, &preamble_pdu_rel8->preamble, end) && + pull16(ppReadPackedMsg, &preamble_pdu_rel8->timing_advance, end)); +} + +static uint8_t unpack_preamble_pdu_rel9_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_preamble_pdu_rel9_t* preamble_pdu_rel9 = (nfapi_preamble_pdu_rel9_t*)tlv; + return pull16(ppReadPackedMsg, &preamble_pdu_rel9->timing_advance_r9, end); +} + +static uint8_t unpack_preamble_pdu_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_preamble_pdu_rel13_t* preamble_pdu_rel13 = (nfapi_preamble_pdu_rel13_t*)tlv; + return pull8(ppReadPackedMsg, &preamble_pdu_rel13->rach_resource_type, end); +} + +static uint8_t unpack_rach_indication_body_value(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) +{ + nfapi_rach_indication_body_t* value = (nfapi_rach_indication_body_t*)tlv; + uint8_t* rachBodyEnd = *ppReadPackedMsg + value->tl.length; + + if(rachBodyEnd > end) + return 0; + + if(pull16(ppReadPackedMsg, &value->number_of_preambles, end) == 0) + return 0; + + if(value->number_of_preambles > NFAPI_PREAMBLE_MAX_PDU) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s number of preamble du's exceed maxium (count:%d max:%d)\n", __FUNCTION__, value->number_of_preambles, NFAPI_PREAMBLE_MAX_PDU); + return 0; + } + + if(value->number_of_preambles > 0) + { + value->preamble_list = (nfapi_preamble_pdu_t*)nfapi_p7_allocate(sizeof(nfapi_preamble_pdu_t) * value->number_of_preambles, config); + if(value->preamble_list == NULL) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s failed to allocate preamble pdu list (count:%d)\n", __FUNCTION__, value->number_of_preambles); + return 0; + } + } + else + { + value->preamble_list = 0; + } + + + uint8_t i = 0; + for(i = 0; i < value->number_of_preambles; ++i) + { + nfapi_preamble_pdu_t* pdu = &(value->preamble_list[i]); + + if(pull16(ppReadPackedMsg, &pdu->instance_length, end) == 0) + return 0; + + uint8_t* preamblePduInstanceEnd = *ppReadPackedMsg + pdu->instance_length; + + + unpack_tlv_t unpack_fns[] = + { + { NFAPI_PREAMBLE_REL8_TAG, &pdu->preamble_rel8, unpack_preamble_pdu_rel8_value }, + { NFAPI_PREAMBLE_REL9_TAG, &pdu->preamble_rel9, unpack_preamble_pdu_rel9_value }, + { NFAPI_PREAMBLE_REL13_TAG, &pdu->preamble_rel13, unpack_preamble_pdu_rel13_value }, + }; + + if(unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, preamblePduInstanceEnd, 0, 0) == 0) + return 0; + } + return 1; +} + +static uint8_t unpack_rach_indication(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config) +{ + nfapi_rach_indication_t *pNfapiMsg = (nfapi_rach_indication_t*)msg; + + unpack_p7_tlv_t unpack_fns[] = + { + { NFAPI_RACH_INDICATION_BODY_TAG, &pNfapiMsg->rach_indication_body, &unpack_rach_indication_body_value}, + }; + + return (pull16(ppReadPackedMsg, &pNfapiMsg->sfn_sf, end) && + unpack_p7_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); +} + +static uint8_t unpack_srs_indication_fdd_rel8_value(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_srs_indication_fdd_rel8_t* srs_pdu_fdd_rel8 = (nfapi_srs_indication_fdd_rel8_t*)tlv; + + if(!(pull16(ppReadPackedMsg, &srs_pdu_fdd_rel8->doppler_estimation, end) && + pull16(ppReadPackedMsg, &srs_pdu_fdd_rel8->timing_advance, end) && + pull8(ppReadPackedMsg, &srs_pdu_fdd_rel8->number_of_resource_blocks, end) && + pull8(ppReadPackedMsg, &srs_pdu_fdd_rel8->rb_start, end) && + pullarray8(ppReadPackedMsg, srs_pdu_fdd_rel8->snr, NFAPI_NUM_RB_MAX, srs_pdu_fdd_rel8->number_of_resource_blocks, end))) + return 0; + return 1; +} + +static uint8_t unpack_srs_indication_fdd_rel9_value(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_srs_indication_fdd_rel9_t* srs_pdu_fdd_rel9 = (nfapi_srs_indication_fdd_rel9_t*)tlv; + return (pull16(ppReadPackedMsg, &srs_pdu_fdd_rel9->timing_advance_r9, end)); +} + +static uint8_t unpack_srs_indication_tdd_rel10_value(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_srs_indication_ttd_rel10_t* srs_pdu_tdd_rel10 = (nfapi_srs_indication_ttd_rel10_t*)tlv; + return (pull8(ppReadPackedMsg, &srs_pdu_tdd_rel10->uppts_symbol, end)); +} + +static uint8_t unpack_srs_indication_fdd_rel11_value(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_srs_indication_fdd_rel11_t* srs_pdu_fdd_rel11 = (nfapi_srs_indication_fdd_rel11_t*)tlv; + return ( pull16(ppReadPackedMsg, &srs_pdu_fdd_rel11->ul_rtoa, end)); +} + +static uint8_t unpack_tdd_channel_measurement_value(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_tdd_channel_measurement_t* value = (nfapi_tdd_channel_measurement_t*)tlv; + + if(!(pull8(ppReadPackedMsg, &value->num_prb_per_subband, end) && + pull8(ppReadPackedMsg, &value->number_of_subbands, end) && + pull8(ppReadPackedMsg, &value->num_atennas, end))) + return 0; + + if(value->number_of_subbands > NFAPI_MAX_NUM_SUBBANDS) + { + // todo : add error + return 0; + } + + if(value->num_atennas > NFAPI_MAX_NUM_PHYSICAL_ANTENNAS) + { + // todo : add error + return 0; + } + + uint8_t idx = 0; + for(idx = 0; idx < value->number_of_subbands; ++idx) + { + if(!(pull8(ppReadPackedMsg, &value->subands[idx].subband_index, end) && + pullarray16(ppReadPackedMsg, value->subands[idx].channel, NFAPI_MAX_NUM_PHYSICAL_ANTENNAS, value->num_atennas, end))) + return 0; + } + + return 1; +} + + +static uint8_t unpack_srs_indication_body_value(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) +{ + nfapi_srs_indication_body_t* value = (nfapi_srs_indication_body_t*)tlv; + uint8_t* srsBodyEnd = *ppReadPackedMsg + value->tl.length; + + if(srsBodyEnd > end) + return 0; + + if(pull8(ppReadPackedMsg, &value->number_of_ues, end) == 0) + return 0; + + if(value->number_of_ues > NFAPI_SRS_IND_MAX_PDU) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s number of srs ind pdu's exceed maxium (count:%d max:%d)\n", __FUNCTION__, value->number_of_ues, NFAPI_SRS_IND_MAX_PDU); + return 0; + } + + if(value->number_of_ues > 0) + { + value->srs_pdu_list = (nfapi_srs_indication_pdu_t*)nfapi_p7_allocate(sizeof(nfapi_srs_indication_pdu_t) * value->number_of_ues, config); + if(value->srs_pdu_list == NULL) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s failed to allocate srs ind pdu list (count:%d)\n", __FUNCTION__, value->number_of_ues); + return 0; + } + } + else + { + value->srs_pdu_list = 0; + } + + + + uint8_t i = 0; + for(i = 0; i < value->number_of_ues; ++i) + { + nfapi_srs_indication_pdu_t* pdu = &(value->srs_pdu_list[i]); + + + if(pull16(ppReadPackedMsg, &pdu->instance_length, end) == 0) + return 0; + + uint8_t* srsPduInstanceEnd = *ppReadPackedMsg + pdu->instance_length; + + + unpack_tlv_t unpack_fns[] = + { + { NFAPI_RX_UE_INFORMATION_TAG, &pdu->rx_ue_information, unpack_rx_ue_information_value }, + { NFAPI_SRS_INDICATION_FDD_REL8_TAG, &pdu->srs_indication_fdd_rel8, unpack_srs_indication_fdd_rel8_value}, + { NFAPI_SRS_INDICATION_FDD_REL9_TAG, &pdu->srs_indication_fdd_rel9, unpack_srs_indication_fdd_rel9_value}, + { NFAPI_SRS_INDICATION_TDD_REL10_TAG, &pdu->srs_indication_tdd_rel10, unpack_srs_indication_tdd_rel10_value}, + { NFAPI_SRS_INDICATION_FDD_REL11_TAG, &pdu->srs_indication_fdd_rel11, unpack_srs_indication_fdd_rel11_value}, + { NFAPI_TDD_CHANNEL_MEASUREMENT_TAG, &pdu->tdd_channel_measurement, unpack_tdd_channel_measurement_value}, + }; + + if(unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, srsPduInstanceEnd, 0, 0) == 0) + return 0; + } + return 1; +} + +static uint8_t unpack_srs_indication(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config) +{ + nfapi_srs_indication_t *pNfapiMsg = (nfapi_srs_indication_t*)msg; + + unpack_p7_tlv_t unpack_fns[] = + { + { NFAPI_SRS_INDICATION_BODY_TAG, &pNfapiMsg->srs_indication_body, &unpack_srs_indication_body_value}, + }; + + return (pull16(ppReadPackedMsg, &pNfapiMsg->sfn_sf, end) && + unpack_p7_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); +} + + +static uint8_t unpack_sr_indication_body_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) +{ + nfapi_sr_indication_body_t* value = (nfapi_sr_indication_body_t*)tlv; + uint8_t* srBodyEnd = *ppReadPackedMsg + value->tl.length; + + if(srBodyEnd > end) + return 0; + + if(pull16(ppReadPackedMsg, &value->number_of_srs, end) == 0) + return 0; + + if(value->number_of_srs > NFAPI_SR_IND_MAX_PDU) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s number of sr ind pdu's exceed maxium (count:%d max:%d)\n", __FUNCTION__, value->number_of_srs, NFAPI_SR_IND_MAX_PDU); + return 0; + } + + if(value->number_of_srs > 0) + { + value->sr_pdu_list = (nfapi_sr_indication_pdu_t*)nfapi_p7_allocate(sizeof(nfapi_sr_indication_pdu_t) * value->number_of_srs, config); + if(value->sr_pdu_list == NULL) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s failed to allocate sr ind pdu list (count:%d)\n", __FUNCTION__, value->number_of_srs); + return 0; + } + } + else + { + value->sr_pdu_list = 0; + } + + uint8_t i = 0; + for(i = 0; i < value->number_of_srs; ++i) + { + nfapi_sr_indication_pdu_t* pdu = &(value->sr_pdu_list[i]); + + if(pull16(ppReadPackedMsg, &pdu->instance_length, end) == 0) + return 0; + + uint8_t* srPduInstanceEnd = *ppReadPackedMsg + pdu->instance_length; + + + unpack_tlv_t unpack_fns[] = + { + { NFAPI_RX_UE_INFORMATION_TAG, &pdu->rx_ue_information, unpack_rx_ue_information_value }, + { NFAPI_UL_CQI_INFORMATION_TAG, &pdu->ul_cqi_information, unpack_ul_cqi_information_value }, + }; + + if(unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, srPduInstanceEnd, 0, 0) == 0) + return 0; + } + + return 1; + +} + +static int unpack_sr_indication(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config) +{ + nfapi_sr_indication_t *pNfapiMsg = (nfapi_sr_indication_t*)msg; + + unpack_p7_tlv_t unpack_fns[] = + { + { NFAPI_SR_INDICATION_BODY_TAG, &pNfapiMsg->sr_indication_body, &unpack_sr_indication_body_value}, + }; + + return (pull16(ppReadPackedMsg, &pNfapiMsg->sfn_sf, end) && + unpack_p7_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); +} +static uint8_t unpack_cqi_indication_rel8_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_cqi_indication_rel8_t* cqi_pdu_rel8 = (nfapi_cqi_indication_rel8_t*)tlv; + + return (pull16(ppReadPackedMsg, &cqi_pdu_rel8->length, end) && + pull16(ppReadPackedMsg, &cqi_pdu_rel8->data_offset, end) && + pull8(ppReadPackedMsg, &cqi_pdu_rel8->ul_cqi, end) && + pull8(ppReadPackedMsg, &cqi_pdu_rel8->ri, end) && + pull16(ppReadPackedMsg, &cqi_pdu_rel8->timing_advance, end)); + +} + +static uint8_t unpack_cqi_indication_rel9_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_cqi_indication_rel9_t* cqi_pdu_rel9 = (nfapi_cqi_indication_rel9_t*)tlv; + + if(!(pull16(ppReadPackedMsg, &cqi_pdu_rel9->length, end) && + pull16(ppReadPackedMsg, &cqi_pdu_rel9->data_offset, end) && + pull8(ppReadPackedMsg, &cqi_pdu_rel9->ul_cqi, end) && + pull8(ppReadPackedMsg, &cqi_pdu_rel9->number_of_cc_reported, end))) + return 0; + + if(cqi_pdu_rel9->number_of_cc_reported > NFAPI_CC_MAX) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "FIXME : out of bound array\n"); + return 0; + } + + if(!(pullarray8(ppReadPackedMsg, cqi_pdu_rel9->ri, NFAPI_CC_MAX, cqi_pdu_rel9->number_of_cc_reported, end) && + pull16(ppReadPackedMsg, &cqi_pdu_rel9->timing_advance, end) && + pull16(ppReadPackedMsg, &cqi_pdu_rel9->timing_advance_r9, end))) + return 0; + + return 1; +} + +static uint8_t unpack_cqi_indication_body_value(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) +{ + nfapi_cqi_indication_body_t* value = (nfapi_cqi_indication_body_t*)tlv; + + // the cqiBodyEnd points to the end of the cqi PDU's + uint8_t* cqiBodyEnd = *ppReadPackedMsg + value->tl.length; + + //uint8_t* cqiPduEnd = cqiBodyEnd; + //uint8_t* numberOfPdusAddress = *ppReadPackedMsg; + + if(cqiBodyEnd > end) + return 0; + + if(pull16(ppReadPackedMsg, &value->number_of_cqis, end) == 0) + return 0; + + if(value->number_of_cqis > NFAPI_CQI_IND_MAX_PDU) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s number of cqi ind pdu's exceed maxium (count:%d max:%d)\n", __FUNCTION__, value->number_of_cqis, NFAPI_CQI_IND_MAX_PDU); + return -1; + } + + if(value->number_of_cqis > 0) + { + value->cqi_pdu_list = (nfapi_cqi_indication_pdu_t*)nfapi_p7_allocate(sizeof(nfapi_cqi_indication_pdu_t) * value->number_of_cqis, config); + if(value->cqi_pdu_list == NULL) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s failed to allocate cqi ind pdu list (count:%d)\n", __FUNCTION__, value->number_of_cqis); + return 0; + } + } + else + { + value->cqi_pdu_list = 0; + } + + if(value->number_of_cqis > 0) + { + value->cqi_raw_pdu_list = (nfapi_cqi_indication_raw_pdu_t*)nfapi_p7_allocate(sizeof(nfapi_cqi_indication_raw_pdu_t) * value->number_of_cqis, config); + if(value->cqi_raw_pdu_list == NULL) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s failed to allocate raw cqi ind pdu list (count:%d)\n", __FUNCTION__, value->number_of_cqis); + return 0; + } + } + else + { + value->cqi_raw_pdu_list = 0; + } + + uint8_t i = 0; + for(i = 0; i < value->number_of_cqis; ++i) + { + nfapi_cqi_indication_pdu_t* pdu = &(value->cqi_pdu_list[i]); + memset(pdu, 0, sizeof(nfapi_cqi_indication_pdu_t)); + + if(pull16(ppReadPackedMsg, &pdu->instance_length, end) == 0) + return 0; + + uint8_t* cqiPduInstanceEnd = *ppReadPackedMsg + pdu->instance_length; + + + while((uint8_t*)(*ppReadPackedMsg) < cqiPduInstanceEnd) + { + nfapi_tl_t generic_tl; + if(unpack_tl(ppReadPackedMsg, &generic_tl, end) == 0) + return 0; + + switch(generic_tl.tag) + { + case NFAPI_RX_UE_INFORMATION_TAG: + pdu->rx_ue_information.tl = generic_tl; + if(unpack_rx_ue_information_value(&pdu->rx_ue_information, ppReadPackedMsg, end) == 0) + return 0; + break; + case NFAPI_CQI_INDICATION_REL8_TAG: + pdu->cqi_indication_rel8.tl = generic_tl; + if(unpack_cqi_indication_rel8_value(&pdu->cqi_indication_rel8, ppReadPackedMsg, end) == 0) + return 0; + + break; + case NFAPI_CQI_INDICATION_REL9_TAG: + pdu->cqi_indication_rel9.tl = generic_tl; + if(unpack_cqi_indication_rel9_value(&pdu->cqi_indication_rel9, ppReadPackedMsg, end) == 0) + return 0; + + break; + case NFAPI_UL_CQI_INFORMATION_TAG: + pdu->ul_cqi_information.tl = generic_tl; + if(unpack_ul_cqi_information_value(&pdu->ul_cqi_information, ppReadPackedMsg, end) == 0) + return 0; + break; + default: + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "RX_CQI.indication Invalid pdu type %d \n", generic_tl.tag ); + } + break; + + }; + } + } + + uint8_t idx = 0; + for(idx = 0; idx < value->number_of_cqis; ++idx) + { + if(value->cqi_pdu_list[idx].cqi_indication_rel8.tl.tag == NFAPI_CQI_INDICATION_REL8_TAG) + { + if(pullarray8(ppReadPackedMsg, &(value->cqi_raw_pdu_list[idx].pdu[0]), NFAPI_CQI_RAW_MAX_LEN, value->cqi_pdu_list[idx].cqi_indication_rel8.length, end) == 0) + return 0; + } + else if(value->cqi_pdu_list[idx].cqi_indication_rel9.tl.tag == NFAPI_CQI_INDICATION_REL9_TAG) + { + if(pullarray8(ppReadPackedMsg, &(value->cqi_raw_pdu_list[idx].pdu[0]), NFAPI_CQI_RAW_MAX_LEN, value->cqi_pdu_list[idx].cqi_indication_rel9.length, end) == 0) + return 0; + } + } + + + return 1; + +} + +static uint8_t unpack_cqi_indication(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config) +{ + nfapi_cqi_indication_t *pNfapiMsg = (nfapi_cqi_indication_t*)msg; + + unpack_p7_tlv_t unpack_fns[] = + { + { NFAPI_CQI_INDICATION_BODY_TAG, &pNfapiMsg->cqi_indication_body, &unpack_cqi_indication_body_value}, + }; + + return (pull16(ppReadPackedMsg, &pNfapiMsg->sfn_sf, end) && + unpack_p7_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); +} +static uint8_t unpack_lbt_pdsch_req_pdu_rel13_value(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_lbt_pdsch_req_pdu_rel13_t* value = (nfapi_lbt_pdsch_req_pdu_rel13_t*)tlv; + + return (pull32(ppReadPackedMsg, &value->handle, end) && + pull32(ppReadPackedMsg, &value->mp_cca, end) && + pull32(ppReadPackedMsg, &value->n_cca, end) && + pull32(ppReadPackedMsg, &value->offset, end) && + pull32(ppReadPackedMsg, &value->lte_txop_sf, end) && + pull16(ppReadPackedMsg, &value->txop_sfn_sf_end, end) && + pull32(ppReadPackedMsg, &value->lbt_mode, end)); +} + +static uint8_t unpack_lbt_drs_req_pdu_rel13_value(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_lbt_drs_req_pdu_rel13_t* value = (nfapi_lbt_drs_req_pdu_rel13_t*)tlv; + + return (pull32(ppReadPackedMsg, &value->handle, end) && + pull32(ppReadPackedMsg, &value->offset, end) && + pull16(ppReadPackedMsg, &value->sfn_sf_end, end) && + pull32(ppReadPackedMsg, &value->lbt_mode, end)); +} + + +static uint8_t unpack_lbt_config_request_body_value(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) +{ + nfapi_lbt_dl_config_request_body_t* value = (nfapi_lbt_dl_config_request_body_t*)tlv; + + if(pull16(ppReadPackedMsg, &value->number_of_pdus, end) == 0) + return 0; + + if(value->number_of_pdus > NFAPI_LBT_DL_CONFIG_REQ_MAX_PDU) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s number of lbt dl config pdu's exceed maxium (count:%d max:%d)\n", __FUNCTION__, value->number_of_pdus, NFAPI_LBT_DL_CONFIG_REQ_MAX_PDU); + return 0; + } + + if(value->number_of_pdus) + { + value->lbt_dl_config_req_pdu_list = (nfapi_lbt_dl_config_request_pdu_t*)nfapi_p7_allocate(sizeof(nfapi_lbt_dl_config_request_pdu_t) * value->number_of_pdus, config); + if(value->lbt_dl_config_req_pdu_list == NULL) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s failed to allocate lbt dl config pdu list (count:%d)\n", __FUNCTION__, value->number_of_pdus); + return 0; + } + } + else + { + value->lbt_dl_config_req_pdu_list = 0; + } + + + uint16_t i; + uint16_t total_number_of_pdus = value->number_of_pdus; + for(i = 0; i < total_number_of_pdus; ++i) + { + nfapi_lbt_dl_config_request_pdu_t* pdu = &(value->lbt_dl_config_req_pdu_list[i]); + + if(!(pull8(ppReadPackedMsg, &pdu->pdu_type, end) && + pull8(ppReadPackedMsg, &pdu->pdu_size, end))) + return 0; + + uint8_t *packedPduEnd = (*ppReadPackedMsg) + pdu->pdu_size - 2; + + if(packedPduEnd > end) + return 0; + + switch(pdu->pdu_type) + { + case NFAPI_LBT_DL_CONFIG_REQUEST_PDSCH_PDU_TYPE: + { + unpack_tlv_t unpack_fns[] = + { + { NFAPI_LBT_PDSCH_REQ_PDU_REL13_TAG, &pdu->lbt_pdsch_req_pdu.lbt_pdsch_req_pdu_rel13, &unpack_lbt_pdsch_req_pdu_rel13_value}, + }; + + unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); + } + break; + case NFAPI_LBT_DL_CONFIG_REQUEST_DRS_PDU_TYPE: + { + unpack_tlv_t unpack_fns[] = + { + { NFAPI_LBT_DRS_REQ_PDU_REL13_TAG, &pdu->lbt_drs_req_pdu.lbt_drs_req_pdu_rel13, &unpack_lbt_drs_req_pdu_rel13_value}, + }; + + unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); + } + break; + default: + NFAPI_TRACE(NFAPI_TRACE_ERROR, "LBT_DL_CONFIG.request body invalid pdu type %d\n", pdu->pdu_type); + return 0; + } + } + + return 1; +} +static uint8_t unpack_lbt_dl_config_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config) +{ + nfapi_lbt_dl_config_request_t *pNfapiMsg = (nfapi_lbt_dl_config_request_t*)msg; + + unpack_p7_tlv_t unpack_fns[] = + { + { NFAPI_LBT_DL_CONFIG_REQUEST_BODY_TAG, &pNfapiMsg->lbt_dl_config_request_body, &unpack_lbt_config_request_body_value}, + }; + + return (pull16(ppReadPackedMsg, &pNfapiMsg->sfn_sf, end) && + unpack_p7_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); +} + +static uint8_t unpack_lbt_pdsch_rsp_pdu_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_lbt_pdsch_rsp_pdu_rel13_t* value = (nfapi_lbt_pdsch_rsp_pdu_rel13_t*)tlv; + + return (pull32(ppReadPackedMsg, &value->handle, end) && + pull32(ppReadPackedMsg, &value->result, end) && + pull32(ppReadPackedMsg, &value->lte_txop_symbols, end) && + pull32(ppReadPackedMsg, &value->initial_partial_sf, end)); + +} +static uint8_t unpack_lbt_drs_rsp_pdu_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_lbt_drs_rsp_pdu_rel13_t* value = (nfapi_lbt_drs_rsp_pdu_rel13_t*)tlv; + + return (pull32(ppReadPackedMsg, &value->handle, end) && + pull32(ppReadPackedMsg, &value->result, end)); +} + +static uint8_t unpack_lbt_indication_body_value(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) +{ + nfapi_lbt_dl_indication_body_t* value = (nfapi_lbt_dl_indication_body_t*)tlv; + + if(pull16(ppReadPackedMsg, &value->number_of_pdus, end) == 0) + return 0; + + if(value->number_of_pdus > NFAPI_LBT_IND_MAX_PDU) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s number of lbt dl ind pdu's exceed maxium (count:%d max:%d)\n", __FUNCTION__, value->number_of_pdus, NFAPI_LBT_IND_MAX_PDU); + return 0; + } + + if(value->number_of_pdus > 0) + { + value->lbt_indication_pdu_list = (nfapi_lbt_dl_indication_pdu_t*)nfapi_p7_allocate(sizeof(nfapi_lbt_dl_indication_pdu_t) * value->number_of_pdus, config); + if(value->lbt_indication_pdu_list == NULL) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s failed to allocate lbt dl ind config pdu list (count:%d)\n", __FUNCTION__, value->number_of_pdus); + return 0; + } + } + else + { + value->lbt_indication_pdu_list = 0; + } + + uint16_t i; + uint16_t total_number_of_pdus = value->number_of_pdus; + for(i = 0; i < total_number_of_pdus; ++i) + { + nfapi_lbt_dl_indication_pdu_t* pdu = &(value->lbt_indication_pdu_list[i]); + + if(!(pull8(ppReadPackedMsg, &pdu->pdu_type, end) && + pull8(ppReadPackedMsg, &pdu->pdu_size, end))) + return 0; + + uint8_t *packedPduEnd = (*ppReadPackedMsg) + pdu->pdu_size - 2; + + if(packedPduEnd > end) + return 0; + + switch(pdu->pdu_type) + { + case NFAPI_LBT_DL_RSP_PDSCH_PDU_TYPE: + { + unpack_tlv_t unpack_fns[] = + { + { NFAPI_LBT_PDSCH_RSP_PDU_REL13_TAG, &pdu->lbt_pdsch_rsp_pdu.lbt_pdsch_rsp_pdu_rel13, &unpack_lbt_pdsch_rsp_pdu_rel13_value}, + }; + + unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); + } + break; + case NFAPI_LBT_DL_RSP_DRS_PDU_TYPE: + { + unpack_tlv_t unpack_fns[] = + { + { NFAPI_LBT_DRS_RSP_PDU_REL13_TAG, &pdu->lbt_drs_rsp_pdu.lbt_drs_rsp_pdu_rel13, &unpack_lbt_drs_rsp_pdu_rel13_value}, + }; + + unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); + } + break; + default: + NFAPI_TRACE(NFAPI_TRACE_ERROR, "LBT_DL.indication body invalid pdu type %d\n", pdu->pdu_type); + return 0; + } + } + + return 1; +} +static uint8_t unpack_lbt_dl_indication(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config) +{ + nfapi_lbt_dl_indication_t *pNfapiMsg = (nfapi_lbt_dl_indication_t*)msg; + + unpack_p7_tlv_t unpack_fns[] = + { + { NFAPI_LBT_DL_INDICATION_BODY_TAG, &pNfapiMsg->lbt_dl_indication_body, &unpack_lbt_indication_body_value}, + }; + + return (pull16(ppReadPackedMsg, &pNfapiMsg->sfn_sf, end) && + unpack_p7_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); +} + +static uint8_t unpack_nb_harq_indication_fdd_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_nb_harq_indication_fdd_rel13_t* value = (nfapi_nb_harq_indication_fdd_rel13_t*)tlv; + return (pull8(ppReadPackedMsg, &value->harq_tb1, end)); +} + + +static uint8_t unpack_nb_harq_indication_body_value(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) +{ + nfapi_nb_harq_indication_body_t* value = (nfapi_nb_harq_indication_body_t*)tlv; + uint8_t* nbharqBodyEnd = *ppReadPackedMsg + value->tl.length; + + if(nbharqBodyEnd > end) + return 0; + + if(pull16(ppReadPackedMsg, &value->number_of_harqs, end) == 0) + return 0; + + if(value->number_of_harqs > NFAPI_HARQ_IND_MAX_PDU) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s number of harq ind pdus exceed maxium (count:%d max:%d)\n", __FUNCTION__, value->number_of_harqs, NFAPI_HARQ_IND_MAX_PDU); + return 0; + } + + value->nb_harq_pdu_list = (nfapi_nb_harq_indication_pdu_t*)nfapi_p7_allocate(sizeof(nfapi_nb_harq_indication_pdu_t) * value->number_of_harqs, config); + if(value->nb_harq_pdu_list == NULL) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s failed to allocate harq ind pdu list (count:%d)\n", __FUNCTION__, value->number_of_harqs); + return 0; + } + + uint8_t i = 0; + for(i = 0; i < value->number_of_harqs; ++i) + { + nfapi_nb_harq_indication_pdu_t* pdu = &(value->nb_harq_pdu_list[i]); + if(pull16(ppReadPackedMsg, &pdu->instance_length, end) == 0) + return 0; + + uint8_t* harqPduInstanceEnd = *ppReadPackedMsg + pdu->instance_length; + + unpack_tlv_t unpack_fns[] = + { + { NFAPI_RX_UE_INFORMATION_TAG, &pdu->rx_ue_information, unpack_rx_ue_information_value }, + { NFAPI_NB_HARQ_INDICATION_FDD_REL13_TAG, &pdu->nb_harq_indication_fdd_rel13, &unpack_nb_harq_indication_fdd_rel13_value}, + { NFAPI_UL_CQI_INFORMATION_TAG, &pdu->ul_cqi_information, &unpack_ul_cqi_information_value} + }; + + if(unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, harqPduInstanceEnd, 0, 0) == 0) + return 0; + + } + + return 1; +} + +static uint8_t unpack_nb_harq_indication(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config) +{ + nfapi_nb_harq_indication_t *pNfapiMsg = (nfapi_nb_harq_indication_t*)msg; + + unpack_p7_tlv_t unpack_fns[] = + { + { NFAPI_NB_HARQ_INDICATION_BODY_TAG, &pNfapiMsg->nb_harq_indication_body, &unpack_nb_harq_indication_body_value}, + }; + + return (pull16(ppReadPackedMsg, &pNfapiMsg->sfn_sf, end) && + unpack_p7_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); +} + +static uint8_t unpack_nrach_indication_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_nrach_indication_pdu_rel13_t* value = (nfapi_nrach_indication_pdu_rel13_t*)tlv; + + return (pull16(ppReadPackedMsg, &value->rnti, end) && + pull8(ppReadPackedMsg, &value->initial_sc, end) && + pull16(ppReadPackedMsg, &value->timing_advance, end) && + pull8(ppReadPackedMsg, &value->nrach_ce_level, end)); +} + +static uint8_t unpack_ue_release_resp(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config) +{ + nfapi_ue_release_response_t *pNfapiMsg = (nfapi_ue_release_response_t*)msg; + if(pull32(ppReadPackedMsg, &pNfapiMsg->error_code, end) == 0){ + return 0; + } + else{ + NFAPI_TRACE(NFAPI_TRACE_INFO, "ue_release_response:error_code = %d\n", pNfapiMsg->error_code); + } + return 1; +} + +static uint8_t unpack_nrach_indication_body_value(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) +{ + nfapi_nrach_indication_body_t* value = (nfapi_nrach_indication_body_t*)tlv; + uint8_t* nrachBodyEnd = *ppReadPackedMsg + value->tl.length; + + if(nrachBodyEnd > end) + return 0; + + if(pull8(ppReadPackedMsg, &value->number_of_initial_scs_detected, end) == 0) + return 0; + + if(value->number_of_initial_scs_detected > NFAPI_PREAMBLE_MAX_PDU) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s number of detected scs ind pdus exceed maxium (count:%d max:%d)\n", __FUNCTION__, value->number_of_initial_scs_detected, NFAPI_PREAMBLE_MAX_PDU); + return 0; + } + + value->nrach_pdu_list = (nfapi_nrach_indication_pdu_t*)nfapi_p7_allocate(sizeof(nfapi_nrach_indication_pdu_t) * value->number_of_initial_scs_detected, config); + if(value->nrach_pdu_list == NULL) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s failed to allocate nrach ind pdu list (count:%d)\n", __FUNCTION__, value->number_of_initial_scs_detected); + return 0; + } + + uint8_t i = 0; + for(i = 0; i < value->number_of_initial_scs_detected; ++i) + { + nfapi_nrach_indication_pdu_t* pdu = &(value->nrach_pdu_list[i]); + + uint8_t* nrachPduInstanceEnd = *ppReadPackedMsg + 4 + 6; + + unpack_tlv_t unpack_fns[] = + { + { NFAPI_NRACH_INDICATION_REL13_TAG, &pdu->nrach_indication_rel13, &unpack_nrach_indication_rel13_value}, + }; + + if(unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, nrachPduInstanceEnd, 0, 0) == 0) + return 0; + + } + + return 1; +} + +static uint8_t unpack_nrach_indication(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config) +{ + nfapi_nrach_indication_t *pNfapiMsg = (nfapi_nrach_indication_t*)msg; + + unpack_p7_tlv_t unpack_fns[] = + { + { NFAPI_NRACH_INDICATION_BODY_TAG, &pNfapiMsg->nrach_indication_body, &unpack_nrach_indication_body_value}, + }; + + return (pull16(ppReadPackedMsg, &pNfapiMsg->sfn_sf, end) && + unpack_p7_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); +} + +static uint8_t unpack_nr_dl_node_sync(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config) +{ + nfapi_nr_dl_node_sync_t *pNfapiMsg = (nfapi_nr_dl_node_sync_t*)msg; + + unpack_p7_tlv_t unpack_fns[] = + { + }; + + return (pull32(ppReadPackedMsg, &pNfapiMsg->t1, end) && + pulls32(ppReadPackedMsg, &pNfapiMsg->delta_sfn_slot, end) && + unpack_p7_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); +} + +static uint8_t unpack_dl_node_sync(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config) +{ + nfapi_dl_node_sync_t *pNfapiMsg = (nfapi_dl_node_sync_t*)msg; + + unpack_p7_tlv_t unpack_fns[] = + { + }; + + return (pull32(ppReadPackedMsg, &pNfapiMsg->t1, end) && + pulls32(ppReadPackedMsg, &pNfapiMsg->delta_sfn_sf, end) && + unpack_p7_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); +} + + +static uint8_t unpack_nr_ul_node_sync(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config) +{ + nfapi_nr_ul_node_sync_t *pNfapiMsg = (nfapi_nr_ul_node_sync_t*)msg; + + unpack_p7_tlv_t unpack_fns[] = + { + }; + + return (pull32(ppReadPackedMsg, &pNfapiMsg->t1, end) && + pull32(ppReadPackedMsg, &pNfapiMsg->t2, end) && + pull32(ppReadPackedMsg, &pNfapiMsg->t3, end) && + unpack_p7_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); +} + + +static uint8_t unpack_ul_node_sync(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config) +{ + nfapi_ul_node_sync_t *pNfapiMsg = (nfapi_ul_node_sync_t*)msg; + + unpack_p7_tlv_t unpack_fns[] = + { + }; + + return (pull32(ppReadPackedMsg, &pNfapiMsg->t1, end) && + pull32(ppReadPackedMsg, &pNfapiMsg->t2, end) && + pull32(ppReadPackedMsg, &pNfapiMsg->t3, end) && + unpack_p7_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); +} + +static uint8_t unpack_timing_info(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config) +{ + nfapi_timing_info_t *pNfapiMsg = (nfapi_timing_info_t*)msg; + + unpack_p7_tlv_t unpack_fns[] = + { + }; + + return (pull32(ppReadPackedMsg, &pNfapiMsg->last_sfn_sf, end) && + pull32(ppReadPackedMsg, &pNfapiMsg->time_since_last_timing_info, end) && + pull32(ppReadPackedMsg, &pNfapiMsg->dl_config_jitter, end) && + pull32(ppReadPackedMsg, &pNfapiMsg->tx_request_jitter, end) && + pull32(ppReadPackedMsg, &pNfapiMsg->ul_config_jitter, end) && + pull32(ppReadPackedMsg, &pNfapiMsg->hi_dci0_jitter, end) && + pulls32(ppReadPackedMsg, &pNfapiMsg->dl_config_latest_delay, end) && + pulls32(ppReadPackedMsg, &pNfapiMsg->tx_request_latest_delay, end) && + pulls32(ppReadPackedMsg, &pNfapiMsg->ul_config_latest_delay, end) && + pulls32(ppReadPackedMsg, &pNfapiMsg->hi_dci0_latest_delay, end) && + pulls32(ppReadPackedMsg, &pNfapiMsg->dl_config_earliest_arrival, end) && + pulls32(ppReadPackedMsg, &pNfapiMsg->tx_request_earliest_arrival, end) && + pulls32(ppReadPackedMsg, &pNfapiMsg->ul_config_earliest_arrival, end) && + pulls32(ppReadPackedMsg, &pNfapiMsg->hi_dci0_earliest_arrival, end) && + unpack_p7_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); +} + + +static uint8_t unpack_nr_timing_info(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config) +{ + nfapi_nr_timing_info_t *pNfapiMsg = (nfapi_nr_timing_info_t*)msg; + + unpack_p7_tlv_t unpack_fns[] = + { + }; + + return (pull32(ppReadPackedMsg, &pNfapiMsg->last_sfn, end) && + pull32(ppReadPackedMsg, &pNfapiMsg->last_slot, end) && + pull32(ppReadPackedMsg, &pNfapiMsg->time_since_last_timing_info, end) && + pull32(ppReadPackedMsg, &pNfapiMsg->dl_tti_jitter, end) && + pull32(ppReadPackedMsg, &pNfapiMsg->tx_data_request_jitter, end) && + pull32(ppReadPackedMsg, &pNfapiMsg->ul_tti_jitter, end) && + pull32(ppReadPackedMsg, &pNfapiMsg->ul_dci_jitter, end) && + pulls32(ppReadPackedMsg, &pNfapiMsg->dl_tti_latest_delay, end) && + pulls32(ppReadPackedMsg, &pNfapiMsg->tx_data_request_latest_delay, end) && + pulls32(ppReadPackedMsg, &pNfapiMsg->ul_tti_latest_delay, end) && + pulls32(ppReadPackedMsg, &pNfapiMsg->ul_dci_latest_delay, end) && + pulls32(ppReadPackedMsg, &pNfapiMsg->dl_tti_earliest_arrival, end) && + pulls32(ppReadPackedMsg, &pNfapiMsg->tx_data_request_earliest_arrival, end) && + pulls32(ppReadPackedMsg, &pNfapiMsg->ul_tti_earliest_arrival, end) && + pulls32(ppReadPackedMsg, &pNfapiMsg->ul_dci_earliest_arrival, end) && + unpack_p7_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); +} + + + +// unpack length check + +static int check_unpack_length(nfapi_message_id_e msgId, uint32_t unpackedBufLen) +{ + int retLen = 0; + + switch (msgId) + { + case NFAPI_DL_CONFIG_REQUEST: + if (unpackedBufLen >= sizeof(nfapi_dl_config_request_t)) + retLen = sizeof(nfapi_dl_config_request_t); + break; + + case NFAPI_UL_CONFIG_REQUEST: + if (unpackedBufLen >= sizeof(nfapi_ul_config_request_t)) + retLen = sizeof(nfapi_ul_config_request_t); + break; + + case NFAPI_SUBFRAME_INDICATION: + if (unpackedBufLen >= sizeof(nfapi_subframe_indication_t)) + retLen = sizeof(nfapi_subframe_indication_t); + break; + + case NFAPI_HI_DCI0_REQUEST: + if (unpackedBufLen >= sizeof(nfapi_hi_dci0_request_t)) + retLen = sizeof(nfapi_hi_dci0_request_t); + break; + + case NFAPI_TX_REQUEST: + if (unpackedBufLen >= sizeof(nfapi_tx_request_t)) + retLen = sizeof(nfapi_tx_request_t); + break; + + case NFAPI_HARQ_INDICATION: + if (unpackedBufLen >= sizeof(nfapi_harq_indication_t)) + retLen = sizeof(nfapi_harq_indication_t); + break; + + case NFAPI_CRC_INDICATION: + if (unpackedBufLen >= sizeof(nfapi_crc_indication_t)) + retLen = sizeof(nfapi_crc_indication_t); + break; + + case NFAPI_RX_ULSCH_INDICATION: + if (unpackedBufLen >= sizeof(nfapi_rx_indication_t)) + retLen = sizeof(nfapi_rx_indication_t); + break; + + case NFAPI_RACH_INDICATION: + if (unpackedBufLen >= sizeof(nfapi_rach_indication_t)) + retLen = sizeof(nfapi_rach_indication_t); + break; + + case NFAPI_SRS_INDICATION: + if (unpackedBufLen >= sizeof(nfapi_srs_indication_t)) + retLen = sizeof(nfapi_srs_indication_t); + break; + + case NFAPI_RX_SR_INDICATION: + if (unpackedBufLen >= sizeof(nfapi_sr_indication_t)) + retLen = sizeof(nfapi_sr_indication_t); + break; + + case NFAPI_RX_CQI_INDICATION: + if (unpackedBufLen >= sizeof(nfapi_cqi_indication_t)) + retLen = sizeof(nfapi_cqi_indication_t); + break; + + case NFAPI_LBT_DL_CONFIG_REQUEST: + if (unpackedBufLen >= sizeof(nfapi_lbt_dl_config_request_t)) + retLen = sizeof(nfapi_lbt_dl_config_request_t); + break; + + case NFAPI_LBT_DL_INDICATION: + if (unpackedBufLen >= sizeof(nfapi_lbt_dl_indication_t)) + retLen = sizeof(nfapi_lbt_dl_indication_t); + break; + + case NFAPI_NB_HARQ_INDICATION: + if (unpackedBufLen >= sizeof(nfapi_nb_harq_indication_t)) + retLen = sizeof(nfapi_nb_harq_indication_t); + break; + + case NFAPI_NRACH_INDICATION: + if (unpackedBufLen >= sizeof(nfapi_nrach_indication_t)) + retLen = sizeof(nfapi_nrach_indication_t); + break; + + case NFAPI_DL_NODE_SYNC: + if (unpackedBufLen >= sizeof(nfapi_dl_node_sync_t)) + retLen = sizeof(nfapi_dl_node_sync_t); + break; + + case NFAPI_UL_NODE_SYNC: + if (unpackedBufLen >= sizeof(nfapi_ul_node_sync_t)) + retLen = sizeof(nfapi_ul_node_sync_t); + break; + + case NFAPI_TIMING_INFO: + if (unpackedBufLen >= sizeof(nfapi_timing_info_t)) + retLen = sizeof(nfapi_timing_info_t); + break; + + case NFAPI_UE_RELEASE_REQUEST: + if (unpackedBufLen >= sizeof(nfapi_ue_release_request_t)) + retLen = sizeof(nfapi_ue_release_request_t); + break; + + case NFAPI_UE_RELEASE_RESPONSE: + if (unpackedBufLen >= sizeof(nfapi_ue_release_response_t)) + retLen = sizeof(nfapi_ue_release_response_t); + break; + + default: + NFAPI_TRACE(NFAPI_TRACE_ERROR, "Unknown message ID %d\n", msgId); + break; + } + + return retLen; +} + +static int check_nr_unpack_length(nfapi_message_id_e msgId, uint32_t unpackedBufLen) +{ + int retLen = 0; + + switch (msgId) + { + case NFAPI_NR_PHY_MSG_TYPE_DL_TTI_REQUEST: + if (unpackedBufLen >= sizeof(nfapi_nr_dl_tti_request_t)) + retLen = sizeof(nfapi_nr_dl_tti_request_t); + break; + + case NFAPI_NR_PHY_MSG_TYPE_UL_TTI_REQUEST: + if (unpackedBufLen >= sizeof(nfapi_nr_ul_tti_request_t)) + retLen = sizeof(nfapi_nr_ul_tti_request_t); + break; + + case NFAPI_SUBFRAME_INDICATION: + if (unpackedBufLen >= sizeof(nfapi_subframe_indication_t)) + retLen = sizeof(nfapi_subframe_indication_t); + break; + + case NFAPI_NR_PHY_MSG_TYPE_UL_DCI_REQUEST: + if (unpackedBufLen >= sizeof(nfapi_nr_ul_dci_request_t)) + retLen = sizeof(nfapi_nr_ul_dci_request_t); + break; + + case NFAPI_NR_PHY_MSG_TYPE_TX_DATA_REQUEST: + if (unpackedBufLen >= sizeof(nfapi_nr_tx_data_request_t)) + retLen = sizeof(nfapi_nr_tx_data_request_t); + break; + + case NFAPI_NR_PHY_MSG_TYPE_RX_DATA_INDICATION: + if (unpackedBufLen >= sizeof(nfapi_nr_rx_data_indication_t)) + retLen = sizeof(nfapi_nr_rx_data_indication_t); + break; + + case NFAPI_NR_PHY_MSG_TYPE_CRC_INDICATION: + if (unpackedBufLen >= sizeof(nfapi_nr_crc_indication_t)) + retLen = sizeof(nfapi_nr_crc_indication_t); + break; + + case NFAPI_NR_PHY_MSG_TYPE_RACH_INDICATION: + if (unpackedBufLen >= sizeof(nfapi_nr_rach_indication_t)) + retLen = sizeof(nfapi_nr_rach_indication_t); + break; + + case NFAPI_NR_PHY_MSG_TYPE_UCI_INDICATION: + if (unpackedBufLen >= sizeof(nfapi_nr_uci_indication_t)) + retLen = sizeof(nfapi_nr_uci_indication_t); + break; + + case NFAPI_NR_PHY_MSG_TYPE_SRS_INDICATION: + if (unpackedBufLen >= sizeof(nfapi_nr_srs_indication_t)) + retLen = sizeof(nfapi_nr_srs_indication_t); + break; + + case NFAPI_NR_PHY_MSG_TYPE_DL_NODE_SYNC: + if (unpackedBufLen >= sizeof(nfapi_nr_dl_node_sync_t)) + retLen = sizeof(nfapi_nr_dl_node_sync_t); + break; + + case NFAPI_NR_PHY_MSG_TYPE_UL_NODE_SYNC: + if (unpackedBufLen >= sizeof(nfapi_nr_ul_node_sync_t)) + retLen = sizeof(nfapi_nr_ul_node_sync_t); + break; + + case NFAPI_TIMING_INFO: + if (unpackedBufLen >= sizeof(nfapi_timing_info_t)) + retLen = sizeof(nfapi_timing_info_t); + break; + + case NFAPI_UE_RELEASE_REQUEST: + if (unpackedBufLen >= sizeof(nfapi_ue_release_request_t)) + retLen = sizeof(nfapi_ue_release_request_t); + break; + + case NFAPI_UE_RELEASE_RESPONSE: + if (unpackedBufLen >= sizeof(nfapi_ue_release_response_t)) + retLen = sizeof(nfapi_ue_release_response_t); + break; + + default: + NFAPI_TRACE(NFAPI_TRACE_ERROR, "Unknown message ID %d\n", msgId); + break; + } + + return retLen; +} + + + +// Main unpack functions - public + +int nfapi_p7_message_header_unpack(void *pMessageBuf, uint32_t messageBufLen, void *pUnpackedBuf, uint32_t unpackedBufLen, nfapi_p7_codec_config_t* config) +{ + nfapi_p7_message_header_t *pMessageHeader = pUnpackedBuf; + uint8_t *pReadPackedMessage = pMessageBuf; + uint8_t *end = pMessageBuf + messageBufLen; + + if (pMessageBuf == NULL || pUnpackedBuf == NULL) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "P7 header unpack supplied pointers are null\n"); + return -1; + } + + if (messageBufLen < NFAPI_P7_HEADER_LENGTH || unpackedBufLen < sizeof(nfapi_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; + } + + // process the header + if(!(pull16(&pReadPackedMessage, &pMessageHeader->phy_id, end) && + pull16(&pReadPackedMessage, &pMessageHeader->message_id, end) && + pull16(&pReadPackedMessage, &pMessageHeader->message_length, end) && + pull16(&pReadPackedMessage, &pMessageHeader->m_segment_sequence, end) && + pull32(&pReadPackedMessage, &pMessageHeader->checksum, end) && + pull32(&pReadPackedMessage, &pMessageHeader->transmit_timestamp, end))) + return -1; + + return 0; +} + +int nfapi_p7_message_unpack(void *pMessageBuf, uint32_t messageBufLen, void *pUnpackedBuf, uint32_t unpackedBufLen, nfapi_p7_codec_config_t* config) +{ + int result = 0; + nfapi_p7_message_header_t *pMessageHeader = (nfapi_p7_message_header_t*)pUnpackedBuf; + uint8_t *pReadPackedMessage = pMessageBuf; + uint8_t *end = pMessageBuf + messageBufLen; + + if (pMessageBuf == NULL || pUnpackedBuf == NULL) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "P7 unpack supplied pointers are null\n"); + return -1; + } + + if (messageBufLen < NFAPI_P7_HEADER_LENGTH || unpackedBufLen < sizeof(nfapi_p7_message_header_t)) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "P7 unpack supplied message buffer is too small %d, %d\n", messageBufLen, unpackedBufLen); + return -1; + } + /* + uint8_t *ptr = pMessageBuf; + printf("\n Read P7 message unpack: "); + while(ptr < end){ + printf(" %d ", *ptr); + ptr++; + } + printf("\n"); +*/ + // clean the supplied buffer for - tag value blanking + (void)memset(pUnpackedBuf, 0, unpackedBufLen); + + // process the header + if(!(pull16(&pReadPackedMessage, &pMessageHeader->phy_id, end) && + pull16(&pReadPackedMessage, &pMessageHeader->message_id, end) && + pull16(&pReadPackedMessage, &pMessageHeader->message_length, end) && + pull16(&pReadPackedMessage, &pMessageHeader->m_segment_sequence, end) && + pull32(&pReadPackedMessage, &pMessageHeader->checksum, end) && + pull32(&pReadPackedMessage, &pMessageHeader->transmit_timestamp, end))) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "P7 unpack header failed\n"); + return -1; + } + + 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; + } + + /* + if(check_unpack_length(pMessageHeader->message_id, unpackedBufLen) == 0) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "P7 unpack unpack buffer is not large enough \n"); + return -1; + } + */ + + // look for the specific message + switch (pMessageHeader->message_id) + { + case NFAPI_DL_CONFIG_REQUEST: + if (check_unpack_length(NFAPI_DL_CONFIG_REQUEST, unpackedBufLen)) + result = unpack_dl_config_request(&pReadPackedMessage, end, pMessageHeader, config); + else + return -1; + break; + + case NFAPI_UL_CONFIG_REQUEST: + if (check_unpack_length(NFAPI_UL_CONFIG_REQUEST, unpackedBufLen)) + result = unpack_ul_config_request(&pReadPackedMessage, end, pMessageHeader, config); + else + return -1; + break; + case NFAPI_TX_REQUEST: + if (check_unpack_length(NFAPI_TX_REQUEST, unpackedBufLen)) + result = unpack_tx_request(&pReadPackedMessage, end, pMessageHeader, config); + else + return -1; + break; + case NFAPI_HI_DCI0_REQUEST: + if (check_unpack_length(NFAPI_HI_DCI0_REQUEST, unpackedBufLen)) + result = unpack_hi_dci0_request(&pReadPackedMessage, end, pMessageHeader, config); + else + return -1; + break; + + case NFAPI_UE_RELEASE_REQUEST: + if (check_unpack_length(NFAPI_UE_RELEASE_REQUEST, unpackedBufLen)) + result = unpack_ue_release_request(&pReadPackedMessage, end, pMessageHeader, config); + else + return -1; + break; + + case NFAPI_HARQ_INDICATION: + if (check_unpack_length(NFAPI_HARQ_INDICATION, unpackedBufLen)) + result = unpack_harq_indication(&pReadPackedMessage, end, pMessageHeader, config); + else + return -1; + break; + + case NFAPI_CRC_INDICATION: + if (check_unpack_length(NFAPI_CRC_INDICATION, unpackedBufLen)) + result = unpack_crc_indication(&pReadPackedMessage,end , pMessageHeader, config); + else + return -1; + break; + + case NFAPI_RX_ULSCH_INDICATION: + if (check_unpack_length(NFAPI_RX_ULSCH_INDICATION, unpackedBufLen)) + result = unpack_rx_indication(&pReadPackedMessage, end, pMessageHeader, config); + else + return -1; + break; + + case NFAPI_RACH_INDICATION: + if (check_unpack_length(NFAPI_RACH_INDICATION, unpackedBufLen)) + result = unpack_rach_indication(&pReadPackedMessage, end, pMessageHeader, config); + else + return -1; + break; + + case NFAPI_SRS_INDICATION: + if (check_unpack_length(NFAPI_SRS_INDICATION, unpackedBufLen)) + result = unpack_srs_indication(&pReadPackedMessage, end, pMessageHeader, config); + else + return -1; + break; + + case NFAPI_RX_SR_INDICATION: + if (check_unpack_length(NFAPI_RX_SR_INDICATION, unpackedBufLen)) + result = unpack_sr_indication(&pReadPackedMessage, end, pMessageHeader, config); + else + return -1; + break; + + case NFAPI_RX_CQI_INDICATION: + if (check_unpack_length(NFAPI_RX_CQI_INDICATION, unpackedBufLen)) + result = unpack_cqi_indication(&pReadPackedMessage, end, pMessageHeader, config); + else + return -1; + break; + + case NFAPI_LBT_DL_CONFIG_REQUEST: + if (check_unpack_length(NFAPI_LBT_DL_CONFIG_REQUEST, unpackedBufLen)) + result = unpack_lbt_dl_config_request(&pReadPackedMessage, end, pMessageHeader, config); + else + return -1; + break; + + case NFAPI_LBT_DL_INDICATION: + if (check_unpack_length(NFAPI_LBT_DL_INDICATION, unpackedBufLen)) + result = unpack_lbt_dl_indication(&pReadPackedMessage, end, pMessageHeader, config); + else + return -1; + break; + + case NFAPI_NB_HARQ_INDICATION: + if (check_unpack_length(NFAPI_NB_HARQ_INDICATION, unpackedBufLen)) + result = unpack_nb_harq_indication(&pReadPackedMessage, end, pMessageHeader, config); + else + return -1; + break; + + case NFAPI_NRACH_INDICATION: + if (check_unpack_length(NFAPI_NRACH_INDICATION, unpackedBufLen)) + result = unpack_nrach_indication(&pReadPackedMessage, end, pMessageHeader, config); + else + return -1; + break; + + case NFAPI_DL_NODE_SYNC: + if (check_unpack_length(NFAPI_DL_NODE_SYNC, unpackedBufLen)) + result = unpack_dl_node_sync(&pReadPackedMessage, end, pMessageHeader, config); + else + return -1; + break; + + case NFAPI_UL_NODE_SYNC: + if (check_unpack_length(NFAPI_UL_NODE_SYNC, unpackedBufLen)) + result = unpack_ul_node_sync(&pReadPackedMessage, end , pMessageHeader, config); + else + return -1; + break; + + case NFAPI_TIMING_INFO: + if (check_unpack_length(NFAPI_TIMING_INFO, unpackedBufLen)) + result = unpack_timing_info(&pReadPackedMessage, end, pMessageHeader, config); + else + return -1; + break; + + case NFAPI_UE_RELEASE_RESPONSE: + if (check_unpack_length(NFAPI_UE_RELEASE_RESPONSE, unpackedBufLen)) + result = unpack_ue_release_resp(&pReadPackedMessage, end, pMessageHeader, config); + else + return -1; + break; + + default: + + if(pMessageHeader->message_id >= NFAPI_VENDOR_EXT_MSG_MIN && + pMessageHeader->message_id <= NFAPI_VENDOR_EXT_MSG_MAX) + { + if(config && config->unpack_p7_vendor_extension) + { + result = (config->unpack_p7_vendor_extension)(pMessageHeader, &pReadPackedMessage, end, config); + } + else + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s VE NFAPI message ID %d. No ve decoder provided\n", __FUNCTION__, pMessageHeader->message_id); + } + } + else + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s NFAPI Unknown message ID %d\n", __FUNCTION__, pMessageHeader->message_id); + } + break; + } + + if(result == 0) + return -1; + else + return 0; +} + +int nfapi_nr_p7_message_unpack(void *pMessageBuf, uint32_t messageBufLen, void *pUnpackedBuf, uint32_t unpackedBufLen, nfapi_p7_codec_config_t* config) +{ + int result = 0; + nfapi_p7_message_header_t *pMessageHeader = (nfapi_p7_message_header_t*)pUnpackedBuf; + uint8_t *pReadPackedMessage = pMessageBuf; + uint8_t *end = pMessageBuf + messageBufLen; + + if (pMessageBuf == NULL || pUnpackedBuf == NULL) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "P7 unpack supplied pointers are null\n"); + return -1; + } + + if (messageBufLen < NFAPI_P7_HEADER_LENGTH || unpackedBufLen < sizeof(nfapi_p7_message_header_t)) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "P7 unpack supplied message buffer is too small %d, %d\n", messageBufLen, unpackedBufLen); + return -1; + } + + // uint8_t *ptr = pMessageBuf; + // printf("\n Read P7 message unpack: "); + // while(ptr < end){ + // printf(" %d ", *ptr); + // ptr++; + // } + // printf("\n"); + + // clean the supplied buffer for - tag value blanking + (void)memset(pUnpackedBuf, 0, unpackedBufLen); + + // process the header + if(!(pull16(&pReadPackedMessage, &pMessageHeader->phy_id, end) && + pull16(&pReadPackedMessage, &pMessageHeader->message_id, end) && + pull16(&pReadPackedMessage, &pMessageHeader->message_length, end) && + pull16(&pReadPackedMessage, &pMessageHeader->m_segment_sequence, end) && + pull32(&pReadPackedMessage, &pMessageHeader->checksum, end) && + pull32(&pReadPackedMessage, &pMessageHeader->transmit_timestamp, end))) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "P7 unpack header failed\n"); + return -1; + } + + 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; + } + + /* + if(check_unpack_length(pMessageHeader->message_id, unpackedBufLen) == 0) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "P7 unpack unpack buffer is not large enough \n"); + return -1; + } + */ + + // look for the specific message + switch (pMessageHeader->message_id) + { + case NFAPI_NR_PHY_MSG_TYPE_DL_TTI_REQUEST: + if (check_nr_unpack_length(NFAPI_NR_PHY_MSG_TYPE_DL_TTI_REQUEST, unpackedBufLen)) + result = unpack_dl_tti_request(&pReadPackedMessage, end, pMessageHeader, config); + else + return -1; + break; + + case NFAPI_NR_PHY_MSG_TYPE_UL_TTI_REQUEST: + if (check_nr_unpack_length(NFAPI_NR_PHY_MSG_TYPE_UL_TTI_REQUEST, unpackedBufLen)) + result = unpack_ul_tti_request(&pReadPackedMessage, end, pMessageHeader, config); + else + return -1; + break; + case NFAPI_NR_PHY_MSG_TYPE_TX_DATA_REQUEST: + if (check_nr_unpack_length(NFAPI_NR_PHY_MSG_TYPE_TX_DATA_REQUEST, unpackedBufLen)) + result = unpack_tx_data_request(&pReadPackedMessage, end, pMessageHeader, config); + else + return -1; + break; + case NFAPI_NR_PHY_MSG_TYPE_UL_DCI_REQUEST: + if (check_nr_unpack_length(NFAPI_NR_PHY_MSG_TYPE_UL_DCI_REQUEST, unpackedBufLen)) + result = unpack_ul_dci_request(&pReadPackedMessage, end, pMessageHeader, config); + else + return -1; + break; + + case NFAPI_UE_RELEASE_REQUEST: + if (check_nr_unpack_length(NFAPI_UE_RELEASE_REQUEST, unpackedBufLen)) + result = unpack_ue_release_request(&pReadPackedMessage, end, pMessageHeader, config); + else + return -1; + break; + + case NFAPI_NR_PHY_MSG_TYPE_RX_DATA_INDICATION: + if (check_nr_unpack_length(NFAPI_NR_PHY_MSG_TYPE_RX_DATA_INDICATION, unpackedBufLen)) + result = unpack_nr_rx_data_indication(&pReadPackedMessage, end, pMessageHeader, config); + else + return -1; + break; + + case NFAPI_NR_PHY_MSG_TYPE_CRC_INDICATION: + if (check_nr_unpack_length(NFAPI_NR_PHY_MSG_TYPE_CRC_INDICATION, unpackedBufLen)) + result = unpack_nr_crc_indication(&pReadPackedMessage,end , pMessageHeader, config); + else + return -1; + break; + + case NFAPI_NR_PHY_MSG_TYPE_UCI_INDICATION: + if (check_nr_unpack_length(NFAPI_NR_PHY_MSG_TYPE_UCI_INDICATION, unpackedBufLen)) + result = unpack_nr_uci_indication(&pReadPackedMessage, end, pMessageHeader, config); + else + return -1; + break; + + case NFAPI_NR_PHY_MSG_TYPE_SRS_INDICATION: + if (check_nr_unpack_length(NFAPI_NR_PHY_MSG_TYPE_SRS_INDICATION, unpackedBufLen)) + result = unpack_nr_srs_indication(&pReadPackedMessage, end, pMessageHeader, config); + else + return -1; + break; + + case NFAPI_NR_PHY_MSG_TYPE_RACH_INDICATION: + if (check_nr_unpack_length(NFAPI_NR_PHY_MSG_TYPE_RACH_INDICATION, unpackedBufLen)) + result = unpack_nr_rach_indication(&pReadPackedMessage, end, pMessageHeader, config); + else + return -1; + break; + + case NFAPI_NR_PHY_MSG_TYPE_DL_NODE_SYNC: + if (check_nr_unpack_length(NFAPI_NR_PHY_MSG_TYPE_DL_NODE_SYNC, unpackedBufLen)) + result = unpack_nr_dl_node_sync(&pReadPackedMessage, end, pMessageHeader, config); + else + return -1; + break; + + case NFAPI_NR_PHY_MSG_TYPE_UL_NODE_SYNC: + if (check_nr_unpack_length(NFAPI_NR_PHY_MSG_TYPE_UL_NODE_SYNC, unpackedBufLen)) + result = unpack_nr_ul_node_sync(&pReadPackedMessage, end , pMessageHeader, config); + else + return -1; + break; + + case NFAPI_TIMING_INFO: + if (check_nr_unpack_length(NFAPI_TIMING_INFO, unpackedBufLen)) + result = unpack_nr_timing_info(&pReadPackedMessage, end, pMessageHeader, config); + else + return -1; + break; + + case NFAPI_UE_RELEASE_RESPONSE: + if (check_nr_unpack_length(NFAPI_UE_RELEASE_RESPONSE, unpackedBufLen)) + result = unpack_ue_release_resp(&pReadPackedMessage, end, pMessageHeader, config); + else + return -1; + break; + + default: + + if(pMessageHeader->message_id >= NFAPI_VENDOR_EXT_MSG_MIN && + pMessageHeader->message_id <= NFAPI_VENDOR_EXT_MSG_MAX) + { + if(config && config->unpack_p7_vendor_extension) + { + result = (config->unpack_p7_vendor_extension)(pMessageHeader, &pReadPackedMessage, end, config); + } + else + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s VE NFAPI message ID %d. No ve decoder provided\n", __FUNCTION__, pMessageHeader->message_id); + } + } + else + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s NFAPI Unknown message ID %d\n", __FUNCTION__, pMessageHeader->message_id); + } + break; + } + + if(result == 0) + return -1; + else + return 0; +} + + 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 8520a5d162..fc9cd66077 100644 --- a/nfapi/open-nFAPI/pnf/public_inc/nfapi_pnf_interface.h +++ b/nfapi/open-nFAPI/pnf/public_inc/nfapi_pnf_interface.h @@ -27,6 +27,7 @@ extern "C" { #include #include "nfapi_nr_interface.h" #include "nfapi_nr_interface_scf.h" + #include #include "openair1/PHY/defs_gNB.h" diff --git a/nfapi/open-nFAPI/pnf/src/pnf_p7.c b/nfapi/open-nFAPI/pnf/src/pnf_p7.c index 3511ed2fb9..ab3b9196f1 100644 --- a/nfapi/open-nFAPI/pnf/src/pnf_p7.c +++ b/nfapi/open-nFAPI/pnf/src/pnf_p7.c @@ -937,7 +937,7 @@ int pnf_p7_slot_ind(pnf_p7_t* pnf_p7, uint16_t phy_id, uint16_t sfn, uint16_t sl pnf_p7->slot_start_time_hr = pnf_get_current_time_hr(); pnf_p7->sfn = sfn; - pnf_p7->slot = slot; + pnf_p7->slot = slot; @@ -1559,6 +1559,9 @@ uint8_t is_nr_p7_request_in_window(uint16_t sfn,uint16_t slot, const char* name, // } // } + struct timespec curr_time; + clock_gettime(CLOCK_MONOTONIC, &curr_time); + printf("PNF SFN:%d, PNF slot:%d, VNF SFN:%d, VNF slot:%d, Curr time;%d.%d. \n",phy->sfn,phy->slot,sfn,slot,curr_time.tv_sec,curr_time.tv_nsec); if(current_sfn_slot_dec <= recv_sfn_slot_dec + timing_window){ in_window = 1; NFAPI_TRACE(NFAPI_TRACE_NOTE, "[%d] %s is in window %d\n", current_sfn_slot_dec, name, recv_sfn_slot_dec); @@ -1571,8 +1574,8 @@ uint8_t is_nr_p7_request_in_window(uint16_t sfn,uint16_t slot, const char* name, else { - NFAPI_TRACE(NFAPI_TRACE_NOTE, "[%d] %s is out of window %d (delta:%d) [max:%d]\n", current_sfn_slot_dec, name, recv_sfn_slot_dec, (current_sfn_slot_dec - recv_sfn_slot_dec), timing_window); - //NFAPI_TRACE(NFAPI_TRACE_NOTE, "[%d] %s is out of window [max:%d]\n", current_sfn_slot_dec, name, recv_sfn_slot_dec, (current_sfn_slot_dec - recv_sfn_slot_dec), timing_window); + //NFAPI_TRACE(NFAPI_TRACE_NOTE, "[%d] %s is out of window %d (delta:%d) [max:%d]\n", current_sfn_slot_dec, name, recv_sfn_slot_dec, (current_sfn_slot_dec - recv_sfn_slot_dec), timing_window); + }//Need to add more cases @@ -3202,6 +3205,8 @@ int pnf_p7_message_pump(pnf_p7_t* pnf_p7) int pnf_nr_p7_message_pump(pnf_p7_t* pnf_p7) { + uint16_t pnf_frame = 0; + uint8_t pnf_slot = 0; // initialize the mutex lock if(pthread_mutex_init(&(pnf_p7->mutex), NULL) != 0) { @@ -3284,8 +3289,8 @@ int pnf_nr_p7_message_pump(pnf_p7_t* pnf_p7) FD_SET(pnf_p7->p7_sock, &rfds); struct timeval timeout; - timeout.tv_sec = 1; - timeout.tv_usec = 0; + timeout.tv_sec = 0; + timeout.tv_usec = 500; selectRetval = select(pnf_p7->p7_sock+1, &rfds, NULL, NULL, &timeout); @@ -3297,7 +3302,15 @@ int pnf_nr_p7_message_pump(pnf_p7_t* pnf_p7) if(selectRetval == 0) { // timeout - continue; + //continue; + if (pnf_slot == 19) + pnf_frame = (pnf_frame + 1) % 1024; + pnf_slot = (pnf_slot + 1) % 20; + pnf_p7->sfn = pnf_frame; + pnf_p7->slot = pnf_slot; + struct timespec curr_time; + clock_gettime(CLOCK_MONOTONIC, &curr_time); + //printf("SFN=%d, slot=%d, Curr_time=%d.%d \n",pnf_p7->sfn,pnf_p7->slot,curr_time.tv_sec,curr_time.tv_nsec); } else if (selectRetval == -1 && (errno == EINTR)) { @@ -3315,7 +3328,7 @@ int pnf_nr_p7_message_pump(pnf_p7_t* pnf_p7) if(FD_ISSET(pnf_p7->p7_sock, &rfds)) { - pnf_nr_nfapi_p7_read_dispatch_message(pnf_p7, now_hr_time); + pnf_nr_nfapi_p7_read_dispatch_message(pnf_p7, now_hr_time); } } NFAPI_TRACE(NFAPI_TRACE_ERROR, "PNF_P7 Terminating..\n"); diff --git a/nfapi/open-nFAPI/pnf/src/pnf_p7_interface.c b/nfapi/open-nFAPI/pnf/src/pnf_p7_interface.c index efcb60ce96..88aa1391cb 100644 --- a/nfapi/open-nFAPI/pnf/src/pnf_p7_interface.c +++ b/nfapi/open-nFAPI/pnf/src/pnf_p7_interface.c @@ -175,17 +175,7 @@ int nfapi_pnf_p7_rach_ind(nfapi_pnf_p7_config_t* config, nfapi_rach_indication_t pnf_p7_t* _this = (pnf_p7_t*)(config); return pnf_p7_pack_and_send_p7_message(_this, (nfapi_p7_message_header_t*)ind, sizeof(nfapi_rach_indication_t)); } -int nfapi_pnf_p7_srs_ind(nfapi_pnf_p7_config_t* config, nfapi_srs_indication_t* ind) -{ - 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); - return pnf_p7_pack_and_send_p7_message(_this, (nfapi_p7_message_header_t*)ind, sizeof(nfapi_srs_indication_t)); -} int nfapi_pnf_p7_sr_ind(nfapi_pnf_p7_config_t* config, nfapi_sr_indication_t* ind) { if(config == NULL || ind == NULL) @@ -265,3 +255,65 @@ int nfapi_pnf_ue_release_resp(nfapi_pnf_p7_config_t* config, nfapi_ue_release_re return pnf_p7_pack_and_send_p7_message(_this, &(resp->header), sizeof(nfapi_ue_release_response_t)); } + +//NR UPLINK INDICATION + +int nfapi_pnf_p7_nr_rx_data_ind(nfapi_pnf_p7_config_t* config, nfapi_nr_rx_data_indication_t* ind) +{ + 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); + return pnf_nr_p7_pack_and_send_p7_message(_this, (nfapi_p7_message_header_t*)ind, sizeof(nfapi_nr_rx_data_indication_t)); +} + +int nfapi_pnf_p7_nr_crc_ind(nfapi_pnf_p7_config_t* config, nfapi_nr_crc_indication_t* ind) +{ + 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); + return pnf_nr_p7_pack_and_send_p7_message(_this, (nfapi_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) +{ + 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); + return pnf_nr_p7_pack_and_send_p7_message(_this, (nfapi_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) +{ + 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); + return pnf_nr_p7_pack_and_send_p7_message(_this, (nfapi_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) +{ + 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); + return pnf_nr_p7_pack_and_send_p7_message(_this, (nfapi_p7_message_header_t*)ind, sizeof(nfapi_nr_rach_indication_t)); +} diff --git a/nfapi/open-nFAPI/pnf_sim/src/fapi_stub.cpp b/nfapi/open-nFAPI/pnf_sim/src/fapi_stub.cpp index 4fe5065cea..1c2f0bef80 100644 --- a/nfapi/open-nFAPI/pnf_sim/src/fapi_stub.cpp +++ b/nfapi/open-nFAPI/pnf_sim/src/fapi_stub.cpp @@ -278,7 +278,7 @@ void *fapi_thread_start(void *ptr) { if(instance->tick == 1000) { if(instance->tx_byte_count > 0) { - printf("[FAPI] Tx rate %u bytes/sec\n", instance->tx_byte_count); + printf("[FAPI] Tx rate %d bytes/sec\n", instance->tx_byte_count); instance->tx_byte_count = 0; } @@ -319,7 +319,7 @@ void *fapi_thread_start(void *ptr) { millisec = now_ts.tv_nsec / 1e6; if(last_millisec != -1 && ((last_millisec + 1 ) % 1000) != millisec) { - printf("*** missing millisec %u %u\n", last_millisec, millisec); + printf("*** missing millisec %d %d\n", last_millisec, millisec); catchup = millisec - last_millisec - 1; } diff --git a/nfapi/open-nFAPI/vnf/inc/vnf_p7.h b/nfapi/open-nFAPI/vnf/inc/vnf_p7.h index 248faf8369..ad1c5e7944 100644 --- a/nfapi/open-nFAPI/vnf/inc/vnf_p7.h +++ b/nfapi/open-nFAPI/vnf/inc/vnf_p7.h @@ -24,6 +24,8 @@ #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)) + + typedef struct { uint8_t* buffer; uint16_t length; diff --git a/nfapi/open-nFAPI/vnf/src/vnf_p7.c b/nfapi/open-nFAPI/vnf/src/vnf_p7.c index 39f7899d77..936c434f44 100644 --- a/nfapi/open-nFAPI/vnf/src/vnf_p7.c +++ b/nfapi/open-nFAPI/vnf/src/vnf_p7.c @@ -461,6 +461,7 @@ int vnf_send_p7_msg(vnf_p7_t* vnf_p7, nfapi_vnf_p7_connection_info_t* p7_info, u { NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() sendto_result %d %d\n", __FUNCTION__, sendto_result, errno); } + return 0; } @@ -676,6 +677,7 @@ int vnf_nr_build_send_dl_node_sync(vnf_p7_t* vnf_p7, nfapi_vnf_p7_connection_inf //dl_node_sync.t1 = calculate_t1(p7_info->sfn_sf, vnf_p7->sf_start_time_hr); dl_node_sync.t1 = calculate_nr_t1(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); } @@ -1451,8 +1453,102 @@ void vnf_handle_ul_node_sync(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vnf_p7) phy->previous_t1 = ind.t1; phy->previous_t2 = ind.t2; } +} +//NR HANDLES FOR UPLINK MESSAGES +void vnf_handle_nr_rx_data_indication(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vnf_p7) +{ + // ensure it's valid + if (pRecvMsg == NULL || vnf_p7 == NULL) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__); + } + 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) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: Failed to unpack message\n", __FUNCTION__); + } + + } +} + +void vnf_handle_nr_crc_indication(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vnf_p7) +{ + // ensure it's valid + if (pRecvMsg == NULL || vnf_p7 == NULL) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__); + } + else + { + nfapi_nr_crc_indication_t ind; + + if(nfapi_nr_p7_message_unpack(pRecvMsg, recvMsgLen, &ind, sizeof(ind), &vnf_p7->_public.codec_config) < 0) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: Failed to unpack message\n", __FUNCTION__); + } + + } +} + +void vnf_handle_nr_srs_indication(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vnf_p7) +{ + // ensure it's valid + if (pRecvMsg == NULL || vnf_p7 == NULL) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__); + } + else + { + nfapi_nr_srs_indication_t ind; + + if(nfapi_nr_p7_message_unpack(pRecvMsg, recvMsgLen, &ind, sizeof(ind), &vnf_p7->_public.codec_config) < 0) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: Failed to unpack message\n", __FUNCTION__); + } + + } +} + +void vnf_handle_nr_uci_indication(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vnf_p7) +{ + // ensure it's valid + if (pRecvMsg == NULL || vnf_p7 == NULL) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__); + } + else + { + nfapi_nr_uci_indication_t ind; + + if(nfapi_nr_p7_message_unpack(pRecvMsg, recvMsgLen, &ind, sizeof(ind), &vnf_p7->_public.codec_config) < 0) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: Failed to unpack message\n", __FUNCTION__); + } + } +} + +void vnf_handle_nr_rach_indication(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vnf_p7) +{ + // ensure it's valid + if (pRecvMsg == NULL || vnf_p7 == NULL) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__); + } + else + { + nfapi_nr_rach_indication_t ind; + + if(nfapi_nr_p7_message_unpack(pRecvMsg, recvMsgLen, &ind, sizeof(ind), &vnf_p7->_public.codec_config) < 0) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: Failed to unpack message\n", __FUNCTION__); + } + + } } void vnf_nr_handle_ul_node_sync(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vnf_p7) @@ -1485,358 +1581,368 @@ void vnf_nr_handle_ul_node_sync(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vnf_p7 // divide by 2 using shift operator uint32_t latency = (tx_2_rx - pnf_proc_time) >> 1; - if(!(phy->filtered_adjust)) + if(phy->in_sync == 0) { - phy->latency[phy->min_sync_cycle_count] = latency; - - //NFAPI_TRACE(NFAPI_TRACE_NOTE, "(%4d/%d) PNF to VNF !sync phy_id:%d (t1/2/3/4:%8u, %8u, %8u, %8u) txrx:%4u procT:%3u latency(us):%4d\n", - // phy->sfn, phy->slot, ind.header.phy_id, ind.t1, ind.t2, ind.t3, t4, - // tx_2_rx, pnf_proc_time, latency); - } - else - { - phy->latency[phy->min_sync_cycle_count] = latency; - - //if(phy->min_sync_cycle_count != SYNC_CYCLE_COUNT) - { - if (ind.t2 < phy->previous_t2 && ind.t1 > phy->previous_t1) - { - // Only t2 wrap has occurred!!! - phy->slot_offset = (NFAPI_MAX_SFNSLOTDEC + ind.t2) - ind.t1 - latency; - } - else if (ind.t2 > phy->previous_t2 && ind.t1 < phy->previous_t1) - { - // Only t1 wrap has occurred - phy->slot_offset = ind.t2 - ( ind.t1 + NFAPI_MAX_SFNSLOTDEC) - latency; - } - else - { - // Either no wrap or both have wrapped - phy->slot_offset = ind.t2 - ind.t1 - latency; - } - - if (phy->slot_offset_filtered == 0) - { - phy->slot_offset_filtered = phy->slot_offset; - } - else - { - int32_t oldFilteredValueShifted = phy->slot_offset_filtered << 5; - int32_t newOffsetShifted = phy->slot_offset << 5; - - // 1/8 of new and 7/8 of old - phy->slot_offset_filtered = ((newOffsetShifted >> 3) + ((oldFilteredValueShifted * 7) >> 3)) >> 5; - } - } - - if(1) - { - struct timespec ts; - clock_gettime(CLOCK_MONOTONIC, &ts); - - //NFAPI_TRACE(NFAPI_TRACE_NOTE, "(%4d/%1d) %d.%d PNF to VNF phy_id:%2d (t1/2/3/4:%8u, %8u, %8u, %8u) txrx:%4u procT:%3u latency(us):%4d(avg:%4d) offset(us):%8d filtered(us):%8d wrap[t1:%u t2:%u]\n", - // phy->sfn, phy->slot, ts.tv_sec, ts.tv_nsec, ind.header.phy_id, - // ind.t1, ind.t2, ind.t3, t4, - // tx_2_rx, pnf_proc_time, latency, phy->average_latency, phy->slot_offset, phy->slot_offset_filtered, - // (ind.t1previous_t1), (ind.t2previous_t2)); - } + NFAPI_TRACE(NFAPI_TRACE_NOTE, "VNF P7 In Sync with phy (phy_id:%d)\n", phy->phy_id); + if(vnf_p7->_public.sync_indication) + (vnf_p7->_public.sync_indication)(&(vnf_p7->_public), 1); } - if (phy->filtered_adjust && (phy->slot_offset_filtered > 1e6 || phy->slot_offset_filtered < -1e6)) - { - phy->filtered_adjust = 0; - phy->zero_count=0; - phy->min_sync_cycle_count = 2; - phy->in_sync = 0; - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s - ADJUST TOO BAD - go out of filtered phy->slot_offset_filtered:%d\n", __FUNCTION__, phy->slot_offset_filtered); - } + phy->in_sync = 1; - if(phy->min_sync_cycle_count) - phy->min_sync_cycle_count--; + // if(!(phy->filtered_adjust)) + // { + // phy->latency[phy->min_sync_cycle_count] = latency; - if(phy->min_sync_cycle_count == 0) - { - uint32_t curr_sfn = phy->sfn; - uint32_t curr_slot = phy->slot; - int32_t sfn_slot_dec = NFAPI_SFNSLOT2DEC(phy->sfn,phy->slot); + // //NFAPI_TRACE(NFAPI_TRACE_NOTE, "(%4d/%d) PNF to VNF !sync phy_id:%d (t1/2/3/4:%8u, %8u, %8u, %8u) txrx:%4u procT:%3u latency(us):%4d\n", + // // phy->sfn, phy->slot, ind.header.phy_id, ind.t1, ind.t2, ind.t3, t4, + // // tx_2_rx, pnf_proc_time, latency); + // } + // else + // { + // phy->latency[phy->min_sync_cycle_count] = latency; - if(!phy->filtered_adjust) - { - int i = 0; - //phy->average_latency = 0; - for(i = 0; i < SYNC_CYCLE_COUNT; ++i) - { - phy->average_latency += phy->latency[i]; + // //if(phy->min_sync_cycle_count != SYNC_CYCLE_COUNT) + // { + // if (ind.t2 < phy->previous_t2 && ind.t1 > phy->previous_t1) + // { + // // Only t2 wrap has occurred!!! + // phy->slot_offset = (NFAPI_MAX_SFNSLOTDEC + ind.t2) - ind.t1 - latency; + // } + // else if (ind.t2 > phy->previous_t2 && ind.t1 < phy->previous_t1) + // { + // // Only t1 wrap has occurred + // phy->slot_offset = ind.t2 - ( ind.t1 + NFAPI_MAX_SFNSLOTDEC) - latency; + // } + // else + // { + // // Either no wrap or both have wrapped + // phy->slot_offset = ind.t2 - ind.t1 - latency; + // } - } - phy->average_latency /= SYNC_CYCLE_COUNT; + // if (phy->slot_offset_filtered == 0) + // { + // phy->slot_offset_filtered = phy->slot_offset; + // } + // else + // { + // int32_t oldFilteredValueShifted = phy->slot_offset_filtered << 5; + // int32_t newOffsetShifted = phy->slot_offset << 5; - phy->slot_offset = ind.t2 - (ind.t1 - phy->average_latency); + // // 1/8 of new and 7/8 of old + // phy->slot_offset_filtered = ((newOffsetShifted >> 3) + ((oldFilteredValueShifted * 7) >> 3)) >> 5; + // } + // } - sfn_slot_dec += (phy->slot_offset / 500); + // if(1) + // { + // struct timespec ts; + // clock_gettime(CLOCK_MONOTONIC, &ts); + + // //NFAPI_TRACE(NFAPI_TRACE_NOTE, "(%4d/%1d) %d.%d PNF to VNF phy_id:%2d (t1/2/3/4:%8u, %8u, %8u, %8u) txrx:%4u procT:%3u latency(us):%4d(avg:%4d) offset(us):%8d filtered(us):%8d wrap[t1:%u t2:%u]\n", + // // phy->sfn, phy->slot, ts.tv_sec, ts.tv_nsec, ind.header.phy_id, + // // ind.t1, ind.t2, ind.t3, t4, + // // tx_2_rx, pnf_proc_time, latency, phy->average_latency, phy->slot_offset, phy->slot_offset_filtered, + // // (ind.t1previous_t1), (ind.t2previous_t2)); + // } + + // } + + // if (phy->filtered_adjust && (phy->slot_offset_filtered > 1e6 || phy->slot_offset_filtered < -1e6)) + // { + // phy->filtered_adjust = 0; + // phy->zero_count=0; + // phy->min_sync_cycle_count = 2; + // phy->in_sync = 0; + // NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s - ADJUST TOO BAD - go out of filtered phy->slot_offset_filtered:%d\n", __FUNCTION__, phy->slot_offset_filtered); + // } + + // if(phy->min_sync_cycle_count) + // phy->min_sync_cycle_count--; + + // if(phy->min_sync_cycle_count == 0) + // { + // uint32_t curr_sfn = phy->sfn; + // uint32_t curr_slot = phy->slot; + // int32_t sfn_slot_dec = NFAPI_SFNSLOT2DEC(phy->sfn,phy->slot); + + // if(!phy->filtered_adjust) + // { + // int i = 0; + // //phy->average_latency = 0; + // for(i = 0; i < SYNC_CYCLE_COUNT; ++i) + // { + // phy->average_latency += phy->latency[i]; + + // } + // phy->average_latency /= SYNC_CYCLE_COUNT; + + // phy->slot_offset = ind.t2 - (ind.t1 - phy->average_latency); + + // sfn_slot_dec += (phy->slot_offset / 500); - NFAPI_TRACE(NFAPI_TRACE_NOTE, "PNF to VNF slot offset:%d sfn :%d slot:%d \n",phy->slot_offset,NFAPI_SFNSLOTDEC2SFN(sfn_slot_dec),NFAPI_SFNSLOTDEC2SLOT(sfn_slot_dec) ); + // //NFAPI_TRACE(NFAPI_TRACE_NOTE, "PNF to VNF slot offset:%d sfn :%d slot:%d \n",phy->slot_offset,NFAPI_SFNSLOTDEC2SFN(sfn_slot_dec),NFAPI_SFNSLOTDEC2SLOT(sfn_slot_dec) ); - } - else - { - sfn_slot_dec += ((phy->slot_offset_filtered + 250) / 500); //Round up to go from microsecond to slot + // } + // else + // { + // sfn_slot_dec += ((phy->slot_offset_filtered + 250) / 500); //Round up to go from microsecond to slot - } + // } - if(sfn_slot_dec < 0) - { - sfn_slot_dec += NFAPI_MAX_SFNSLOTDEC; - } - else if( sfn_slot_dec >= NFAPI_MAX_SFNSLOTDEC) - { - sfn_slot_dec -= NFAPI_MAX_SFNSLOTDEC; - } + // if(sfn_slot_dec < 0) + // { + // sfn_slot_dec += NFAPI_MAX_SFNSLOTDEC; + // } + // else if( sfn_slot_dec >= NFAPI_MAX_SFNSLOTDEC) + // { + // sfn_slot_dec -= NFAPI_MAX_SFNSLOTDEC; + // } - uint16_t new_sfn = NFAPI_SFNSLOTDEC2SFN(sfn_slot_dec); - uint16_t new_slot = NFAPI_SFNSLOTDEC2SLOT(sfn_slot_dec); + // uint16_t new_sfn = NFAPI_SFNSLOTDEC2SFN(sfn_slot_dec); + // uint16_t new_slot = NFAPI_SFNSLOTDEC2SLOT(sfn_slot_dec); - { - phy->adjustment = NFAPI_SFNSLOT2DEC(new_sfn, new_slot) - NFAPI_SFNSLOT2DEC(curr_sfn, curr_slot); + // { + // phy->adjustment = NFAPI_SFNSLOT2DEC(new_sfn, new_slot) - NFAPI_SFNSLOT2DEC(curr_sfn, curr_slot); - //NFAPI_TRACE(NFAPI_TRACE_NOTE, "PNF to VNF phy_id:%d adjustment%d phy->previous_slot_offset_filtered:%d phy->previous_slot_offset_filtered:%d phy->slot_offset_trend:%d\n", ind.header.phy_id, phy->adjustment, phy->previous_slot_offset_filtered, phy->previous_slot_offset_filtered, phy->slot_offset_trend); + // //NFAPI_TRACE(NFAPI_TRACE_NOTE, "PNF to VNF phy_id:%d adjustment%d phy->previous_slot_offset_filtered:%d phy->previous_slot_offset_filtered:%d phy->slot_offset_trend:%d\n", ind.header.phy_id, phy->adjustment, phy->previous_slot_offset_filtered, phy->previous_slot_offset_filtered, phy->slot_offset_trend); - phy->previous_t1 = 0; - phy->previous_t2 = 0; +// phy->previous_t1 = 0; +// phy->previous_t2 = 0; - if(phy->previous_slot_offset_filtered > 0) - { - if( phy->slot_offset_filtered > phy->previous_slot_offset_filtered) - { - // pnf is getting futher ahead of vnf - //phy->sf_offset_trend = phy->sf_offset_filtered - phy->previous_sf_offset_filtered; - phy->slot_offset_trend = (phy->slot_offset_filtered + phy->previous_slot_offset_filtered)/2; - } - else - { - // pnf is getting back in sync - } - } - else if(phy->previous_slot_offset_filtered < 0) - { - if(phy->slot_offset_filtered < phy->previous_slot_offset_filtered) - { - // vnf is getting future ahead of pnf - //phy->sf_offset_trend = -(phy->sf_offset_filtered - phy->previous_sf_offset_filtered); - phy->slot_offset_trend = (-(phy->slot_offset_filtered + phy->previous_slot_offset_filtered)) /2; - } - else - { - // vnf is getting back in sync - } - } +// if(phy->previous_slot_offset_filtered > 0) +// { +// if( phy->slot_offset_filtered > phy->previous_slot_offset_filtered) +// { +// // pnf is getting futher ahead of vnf +// //phy->sf_offset_trend = phy->sf_offset_filtered - phy->previous_sf_offset_filtered; +// phy->slot_offset_trend = (phy->slot_offset_filtered + phy->previous_slot_offset_filtered)/2; +// } +// else +// { +// // pnf is getting back in sync +// } +// } +// else if(phy->previous_slot_offset_filtered < 0) +// { +// if(phy->slot_offset_filtered < phy->previous_slot_offset_filtered) +// { +// // vnf is getting future ahead of pnf +// //phy->sf_offset_trend = -(phy->sf_offset_filtered - phy->previous_sf_offset_filtered); +// phy->slot_offset_trend = (-(phy->slot_offset_filtered + phy->previous_slot_offset_filtered)) /2; +// } +// else +// { +// // vnf is getting back in sync +// } +// } - int insync_minor_adjustment_1 = phy->slot_offset_trend / 6; - int insync_minor_adjustment_2 = phy->slot_offset_trend / 2; +// int insync_minor_adjustment_1 = phy->slot_offset_trend / 6; +// int insync_minor_adjustment_2 = phy->slot_offset_trend / 2; - if(insync_minor_adjustment_1 == 0) - insync_minor_adjustment_1 = 2; +// if(insync_minor_adjustment_1 == 0) +// insync_minor_adjustment_1 = 2; - if(insync_minor_adjustment_2 == 0) - insync_minor_adjustment_2 = 10; +// if(insync_minor_adjustment_2 == 0) +// insync_minor_adjustment_2 = 10; - if(!phy->filtered_adjust) - { - if(phy->adjustment < 10) - { - phy->zero_count++; +// if(!phy->filtered_adjust) +// { +// if(phy->adjustment < 10) +// { +// phy->zero_count++; - if(phy->zero_count >= 10) - { - phy->filtered_adjust = 1; - phy->zero_count = 0; +// if(phy->zero_count >= 10) +// { +// phy->filtered_adjust = 1; +// phy->zero_count = 0; - NFAPI_TRACE(NFAPI_TRACE_NOTE, "***** Adjusting VNF SFN/SF switching to filtered mode\n"); - } - } - else - { - phy->zero_count = 0; - } - } - else - { - // Fine level of adjustment - if (phy->adjustment == 0) - { - if (phy->zero_count >= 10) - { - if(phy->in_sync == 0) - { - NFAPI_TRACE(NFAPI_TRACE_NOTE, "VNF P7 In Sync with phy (phy_id:%d)\n", phy->phy_id); +// NFAPI_TRACE(NFAPI_TRACE_NOTE, "***** Adjusting VNF SFN/SF switching to filtered mode\n"); +// } +// } +// else +// { +// phy->zero_count = 0; +// } +// } +// else +// { +// // Fine level of adjustment +// if (phy->adjustment == 0) +// { +// if (phy->zero_count >= 10) +// { +// if(phy->in_sync == 0) +// { +// NFAPI_TRACE(NFAPI_TRACE_NOTE, "VNF P7 In Sync with phy (phy_id:%d)\n", phy->phy_id); - if(vnf_p7->_public.sync_indication) - (vnf_p7->_public.sync_indication)(&(vnf_p7->_public), 1); - } +// if(vnf_p7->_public.sync_indication) +// (vnf_p7->_public.sync_indication)(&(vnf_p7->_public), 1); +// } - phy->in_sync = 1; - } - else - { - phy->zero_count++; - } +// phy->in_sync = 1; +// } +// else +// { +// phy->zero_count++; +// } - if(phy->in_sync) - { - // in sync - if(phy->slot_offset_filtered > 250) - { - // VNF is slow - phy->insync_minor_adjustment = insync_minor_adjustment_1; //25; - phy->insync_minor_adjustment_duration = ((phy->slot_offset_filtered) / insync_minor_adjustment_1); - } - else if(phy->slot_offset_filtered < -250) - { - // VNF is fast - phy->insync_minor_adjustment = -(insync_minor_adjustment_1); //25; - phy->insync_minor_adjustment_duration = (((phy->slot_offset_filtered) / -(insync_minor_adjustment_1))); - } - else - { - phy->insync_minor_adjustment = 0; - } +// if(phy->in_sync) +// { +// // in sync +// if(phy->slot_offset_filtered > 250) +// { +// // VNF is slow +// phy->insync_minor_adjustment = insync_minor_adjustment_1; //25; +// phy->insync_minor_adjustment_duration = ((phy->slot_offset_filtered) / insync_minor_adjustment_1); +// } +// else if(phy->slot_offset_filtered < -250) +// { +// // VNF is fast +// phy->insync_minor_adjustment = -(insync_minor_adjustment_1); //25; +// phy->insync_minor_adjustment_duration = (((phy->slot_offset_filtered) / -(insync_minor_adjustment_1))); +// } +// else +// { +// phy->insync_minor_adjustment = 0; +// } - if(phy->insync_minor_adjustment != 0) - { - // NFAPI_TRACE(NFAPI_TRACE_NOTE, "(%4d/%d) VNF phy_id:%d Apply minor insync adjustment %dus for %d slots (slot_offset_filtered:%d) %d %d %d NEW:%d CURR:%d adjustment:%d\n", - // phy->sfn, phy->slot, ind.header.phy_id, - // phy->insync_minor_adjustment, phy->insync_minor_adjustment_duration, - // phy->slot_offset_filtered, - // insync_minor_adjustment_1, insync_minor_adjustment_2, phy->slot_offset_trend, - // NFAPI_SFNSLOT2DEC(new_sfn, new_slot), - // NFAPI_SFNSLOT2DEC(curr_sfn, curr_slot), - // phy->adjustment); - } - } - } - else - { - if (phy->in_sync) - { - if(phy->adjustment == 0) - { - } - else if(phy->adjustment > 0) - { - // VNF is slow - //if(phy->adjustment == 1) - { - // - if(phy->slot_offset_filtered > 250) - { - // VNF is slow - phy->insync_minor_adjustment = insync_minor_adjustment_2; - phy->insync_minor_adjustment_duration = 2 * ((phy->slot_offset_filtered - 250) / insync_minor_adjustment_2); - } - else if(phy->slot_offset_filtered < -250) - { - // VNF is fast - phy->insync_minor_adjustment = -(insync_minor_adjustment_2); - phy->insync_minor_adjustment_duration = 2 * ((phy->slot_offset_filtered + 250) / -(insync_minor_adjustment_2)); - } +// if(phy->insync_minor_adjustment != 0) +// { +// // NFAPI_TRACE(NFAPI_TRACE_NOTE, "(%4d/%d) VNF phy_id:%d Apply minor insync adjustment %dus for %d slots (slot_offset_filtered:%d) %d %d %d NEW:%d CURR:%d adjustment:%d\n", +// // phy->sfn, phy->slot, ind.header.phy_id, +// // phy->insync_minor_adjustment, phy->insync_minor_adjustment_duration, +// // phy->slot_offset_filtered, +// // insync_minor_adjustment_1, insync_minor_adjustment_2, phy->slot_offset_trend, +// // NFAPI_SFNSLOT2DEC(new_sfn, new_slot), +// // NFAPI_SFNSLOT2DEC(curr_sfn, curr_slot), +// // phy->adjustment); +// } +// } +// } +// else +// { +// if (phy->in_sync) +// { +// if(phy->adjustment == 0) +// { +// } +// else if(phy->adjustment > 0) +// { +// // VNF is slow +// //if(phy->adjustment == 1) +// { +// // +// if(phy->slot_offset_filtered > 250) +// { +// // VNF is slow +// phy->insync_minor_adjustment = insync_minor_adjustment_2; +// phy->insync_minor_adjustment_duration = 2 * ((phy->slot_offset_filtered - 250) / insync_minor_adjustment_2); +// } +// else if(phy->slot_offset_filtered < -250) +// { +// // VNF is fast +// phy->insync_minor_adjustment = -(insync_minor_adjustment_2); +// phy->insync_minor_adjustment_duration = 2 * ((phy->slot_offset_filtered + 250) / -(insync_minor_adjustment_2)); +// } - } - //else - { - // out of sync? - } +// } +// //else +// { +// // out of sync? +// } - // NFAPI_TRACE(NFAPI_TRACE_NOTE, "(%4d/%d) VNF phy_id:%d Apply minor insync adjustment %dus for %d slots (adjustment:%d slot_offset_filtered:%d) %d %d %d NEW:%d CURR:%d adj:%d\n", - // phy->sfn, phy->slot, ind.header.phy_id, - // phy->insync_minor_adjustment, phy->insync_minor_adjustment_duration, phy->adjustment, phy->slot_offset_filtered, - // insync_minor_adjustment_1, insync_minor_adjustment_2, phy->slot_offset_trend, - // NFAPI_SFNSLOT2DEC(new_sfn, new_slot), - // NFAPI_SFNSLOT2DEC(curr_sfn, curr_slot), - // phy->adjustment); +// // NFAPI_TRACE(NFAPI_TRACE_NOTE, "(%4d/%d) VNF phy_id:%d Apply minor insync adjustment %dus for %d slots (adjustment:%d slot_offset_filtered:%d) %d %d %d NEW:%d CURR:%d adj:%d\n", +// // phy->sfn, phy->slot, ind.header.phy_id, +// // phy->insync_minor_adjustment, phy->insync_minor_adjustment_duration, phy->adjustment, phy->slot_offset_filtered, +// // insync_minor_adjustment_1, insync_minor_adjustment_2, phy->slot_offset_trend, +// // NFAPI_SFNSLOT2DEC(new_sfn, new_slot), +// // NFAPI_SFNSLOT2DEC(curr_sfn, curr_slot), +// // phy->adjustment); - } - else if(phy->adjustment < 0) - { - // VNF is fast - //if(phy->adjustment == -1) - { - // - if(phy->slot_offset_filtered > 250) - { - // VNF is slow - phy->insync_minor_adjustment = insync_minor_adjustment_2; - phy->insync_minor_adjustment_duration = 2 * ((phy->slot_offset_filtered - 250) / insync_minor_adjustment_2); - } - else if(phy->slot_offset_filtered < -250) - { - // VNF is fast - phy->insync_minor_adjustment = -(insync_minor_adjustment_2); - phy->insync_minor_adjustment_duration = 2 * ((phy->slot_offset_filtered + 250) / -(insync_minor_adjustment_2)); - } - } - //else - { - // out of sync? - } +// } +// else if(phy->adjustment < 0) +// { +// // VNF is fast +// //if(phy->adjustment == -1) +// { +// // +// if(phy->slot_offset_filtered > 250) +// { +// // VNF is slow +// phy->insync_minor_adjustment = insync_minor_adjustment_2; +// phy->insync_minor_adjustment_duration = 2 * ((phy->slot_offset_filtered - 250) / insync_minor_adjustment_2); +// } +// else if(phy->slot_offset_filtered < -250) +// { +// // VNF is fast +// phy->insync_minor_adjustment = -(insync_minor_adjustment_2); +// phy->insync_minor_adjustment_duration = 2 * ((phy->slot_offset_filtered + 250) / -(insync_minor_adjustment_2)); +// } +// } +// //else +// { +// // out of sync? +// } - // NFAPI_TRACE(NFAPI_TRACE_NOTE, "(%d/%d) VNF phy_id:%d Apply minor insync adjustment %dus for %d slots (adjustment:%d slot_offset_filtered:%d) %d %d %d\n", - // phy->sfn, phy->slot, ind.header.phy_id, - // phy->insync_minor_adjustment, phy->insync_minor_adjustment_duration, phy->adjustment, phy->slot_offset_filtered, - // insync_minor_adjustment_1, insync_minor_adjustment_2, phy->slot_offset_trend); - } +// // NFAPI_TRACE(NFAPI_TRACE_NOTE, "(%d/%d) VNF phy_id:%d Apply minor insync adjustment %dus for %d slots (adjustment:%d slot_offset_filtered:%d) %d %d %d\n", +// // phy->sfn, phy->slot, ind.header.phy_id, +// // phy->insync_minor_adjustment, phy->insync_minor_adjustment_duration, phy->adjustment, phy->slot_offset_filtered, +// // insync_minor_adjustment_1, insync_minor_adjustment_2, phy->slot_offset_trend); +// } - /* - if (phy->adjustment > 10 || phy->adjustment < -10) - { - phy->zero_count++; // Add one to the getting out of sync counter - } - else - { - phy->zero_count = 0; // Small error - zero the out of sync counter - } +// /* +// if (phy->adjustment > 10 || phy->adjustment < -10) +// { +// phy->zero_count++; // Add one to the getting out of sync counter +// } +// else +// { +// phy->zero_count = 0; // Small error - zero the out of sync counter +// } - if (phy->zero_count >= 10) // If we have had 10 consecutive large errors - drop out of sync - { - NFAPI_TRACE(NFAPI_TRACE_NOTE, "we have fallen out of sync...\n"); - //pP7SockInfo->syncAchieved = 0; - } - */ - } - } - } +// if (phy->zero_count >= 10) // If we have had 10 consecutive large errors - drop out of sync +// { +// NFAPI_TRACE(NFAPI_TRACE_NOTE, "we have fallen out of sync...\n"); +// //pP7SockInfo->syncAchieved = 0; +// } +// */ +// } +// } +// } - if(phy->in_sync == 0) - { - /*NFAPI_TRACE(NFAPI_TRACE_NOTE, "***** Adjusting VNF phy_id:%d SFN/SF (%s) from %d to %d (%d) mode:%s zeroCount:%u sync:%s\n", - ind.header.phy_id, (phy->in_sync ? "via sfn" : "now"), - NFAPI_SFNSF2DEC(curr_sfn_sf), NFAPI_SFNSF2DEC(new_sfn_sf), phy->adjustment, - phy->filtered_adjust ? "FILTERED" : "ABSOLUTE", - phy->zero_count, - phy->in_sync ? "IN_SYNC" : "OUT_OF_SYNC");*/ +// if(phy->in_sync == 0) +// { +// /*NFAPI_TRACE(NFAPI_TRACE_NOTE, "***** Adjusting VNF phy_id:%d SFN/SF (%s) from %d to %d (%d) mode:%s zeroCount:%u sync:%s\n", +// ind.header.phy_id, (phy->in_sync ? "via sfn" : "now"), +// NFAPI_SFNSF2DEC(curr_sfn_sf), NFAPI_SFNSF2DEC(new_sfn_sf), phy->adjustment, +// phy->filtered_adjust ? "FILTERED" : "ABSOLUTE", +// phy->zero_count, +// phy->in_sync ? "IN_SYNC" : "OUT_OF_SYNC");*/ - phy->sfn = new_sfn; - phy->slot = new_slot; - } - } +// phy->sfn = new_sfn; +// phy->slot = new_slot; +// } +// } - // reset for next cycle - phy->previous_slot_offset_filtered = phy->slot_offset_filtered; - phy->min_sync_cycle_count = 2; - phy->slot_offset_filtered = 0; - phy->slot_offset = 0; - } - else - { - phy->previous_t1 = ind.t1; - phy->previous_t2 = ind.t2; - } -} +// // reset for next cycle +// phy->previous_slot_offset_filtered = phy->slot_offset_filtered; +// phy->min_sync_cycle_count = 2; +// phy->slot_offset_filtered = 0; +// phy->slot_offset = 0; +// } +// else +// { +// phy->previous_t1 = ind.t1; +// phy->previous_t2 = ind.t2; +// } + } void vnf_handle_timing_info(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vnf_p7) { @@ -2035,46 +2141,26 @@ void vnf_nr_dispatch_p7_message(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vnf_p7 vnf_nr_handle_timing_info(pRecvMsg, recvMsgLen, vnf_p7); break; - case NFAPI_HARQ_INDICATION: - vnf_handle_harq_indication(pRecvMsg, recvMsgLen, vnf_p7); + case NFAPI_NR_PHY_MSG_TYPE_RX_DATA_INDICATION: + vnf_handle_nr_rx_data_indication(pRecvMsg, recvMsgLen, vnf_p7); break; - case NFAPI_CRC_INDICATION: - vnf_handle_crc_indication(pRecvMsg, recvMsgLen, vnf_p7); + case NFAPI_NR_PHY_MSG_TYPE_CRC_INDICATION: + vnf_handle_nr_crc_indication(pRecvMsg, recvMsgLen, vnf_p7); break; - case NFAPI_RX_ULSCH_INDICATION: - vnf_handle_rx_ulsch_indication(pRecvMsg, recvMsgLen, vnf_p7); + case NFAPI_NR_PHY_MSG_TYPE_UCI_INDICATION: + vnf_handle_nr_uci_indication(pRecvMsg, recvMsgLen, vnf_p7); break; - case NFAPI_RACH_INDICATION: - vnf_handle_rach_indication(pRecvMsg, recvMsgLen, vnf_p7); + case NFAPI_NR_PHY_MSG_TYPE_SRS_INDICATION: + vnf_handle_nr_rach_indication(pRecvMsg, recvMsgLen, vnf_p7); break; - case NFAPI_SRS_INDICATION: - vnf_handle_srs_indication(pRecvMsg, recvMsgLen, vnf_p7); + case NFAPI_NR_PHY_MSG_TYPE_RACH_INDICATION: + vnf_handle_nr_srs_indication(pRecvMsg, recvMsgLen, vnf_p7); break; - case NFAPI_RX_SR_INDICATION: - vnf_handle_rx_sr_indication(pRecvMsg, recvMsgLen, vnf_p7); - break; - - case NFAPI_RX_CQI_INDICATION: - vnf_handle_rx_cqi_indication(pRecvMsg, recvMsgLen, vnf_p7); - break; - - case NFAPI_LBT_DL_INDICATION: - vnf_handle_lbt_dl_indication(pRecvMsg, recvMsgLen, vnf_p7); - break; - - case NFAPI_NB_HARQ_INDICATION: - vnf_handle_nb_harq_indication(pRecvMsg, recvMsgLen, vnf_p7); - break; - - case NFAPI_NRACH_INDICATION: - vnf_handle_nrach_indication(pRecvMsg, recvMsgLen, vnf_p7); - break; - case NFAPI_UE_RELEASE_RESPONSE: vnf_handle_ue_release_resp(pRecvMsg, recvMsgLen, vnf_p7); break; diff --git a/nfapi/open-nFAPI/vnf/src/vnf_p7_interface.c b/nfapi/open-nFAPI/vnf/src/vnf_p7_interface.c index aba91d0d28..f66919434e 100644 --- a/nfapi/open-nFAPI/vnf/src/vnf_p7_interface.c +++ b/nfapi/open-nFAPI/vnf/src/vnf_p7_interface.c @@ -430,18 +430,6 @@ struct timespec current_time; } send_mac_slot_indications(vnf_p7); - - - // // Call the scheduler - // struct PHY_VARS_gNB_s *gNB = RC.gNB[0]; - // pthread_mutex_lock(&gNB->UL_INFO_mutex); - // gNB->UL_INFO.frame = vnf_frame; - // gNB->UL_INFO.slot = vnf_slot; - - // gNB->UL_INFO.module_id = gNB->Mod_id; - // gNB->UL_INFO.CC_id = gNB->CC_id; - // gNB->if_inst->NR_UL_indication(&gNB->UL_INFO); - // pthread_mutex_unlock(&gNB->UL_INFO_mutex); } else if(selectRetval > 0) { diff --git a/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c b/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c index f901bfdded..625519b953 100644 --- a/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c +++ b/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c @@ -61,6 +61,8 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB, debug_ch_est = fopen("debug_ch_est.txt","w"); #endif + //uint16_t Nid_cell = (eNB_offset == 0) ? gNB->frame_parms.Nid_cell : gNB->measurements.adj_cell_id[eNB_offset-1]; + uint8_t nushift; int **ul_ch_estimates = gNB->pusch_vars[ul_id]->ul_ch_estimates; int **rxdataF = gNB->common_vars.rxdataF; diff --git a/openair1/PHY/NR_TRANSPORT/nr_dlsch_tools.c b/openair1/PHY/NR_TRANSPORT/nr_dlsch_tools.c index 3707669769..543002827d 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_dlsch_tools.c +++ b/openair1/PHY/NR_TRANSPORT/nr_dlsch_tools.c @@ -32,7 +32,6 @@ */ #include "nr_dlsch.h" -#include "../../../nfapi/oai_integration/vendor_ext.h" extern void set_taus_seed(unsigned int seed_type); @@ -264,21 +263,13 @@ int16_t find_nr_dlsch(uint16_t rnti, PHY_VARS_gNB *gNB,find_type_t type) { for (i=0; inumber_of_nr_dlsch_max; i++) { AssertFatal(gNB->dlsch[i]!=NULL,"gNB->dlsch[%d] is null\n",i); AssertFatal(gNB->dlsch[i][0]!=NULL,"gNB->dlsch[%d][0] is null\n",i); - //LOG_D(PHY,"searching for rnti %x : dlsch_index %d=> harq_mask %x, rnti %x, first_free_index %d\n", rnti,i, - //gNB->dlsch[i][0]->harq_mask,gNB->dlsch[i][0]->rnti,first_free_index); - LOG_D(PHY,"searching for harq_mask %x, rnti %x, gNB->dlsch[i][0]->rnti %x\n", gNB->dlsch[i][0]->harq_mask, rnti, gNB->dlsch[i][0]->rnti); + LOG_D(PHY,"searching for rnti %x : dlsch_index %d=> harq_mask %x, rnti %x, first_free_index %d\n", rnti,i, + gNB->dlsch[i][0]->harq_mask,gNB->dlsch[i][0]->rnti,first_free_index); if ((gNB->dlsch[i][0]->harq_mask >0) && (gNB->dlsch[i][0]->rnti==rnti)) return i; - else if ((gNB->dlsch[i][0]->harq_mask == 0) && (first_free_index==-1)) { - //printf("gNB->dlsch[i][0]->harq_mask = %d \n", gNB->dlsch[i][0]->harq_mask);; - first_free_index=i; - } - - } - if (type == SEARCH_EXIST) { - printf("type = %d \n", type); - return -1; + else if ((gNB->dlsch[i][0]->harq_mask == 0) && (first_free_index==-1)) first_free_index=i; } + if (type == SEARCH_EXIST) return -1; if (first_free_index != -1) gNB->dlsch[first_free_index][0]->rnti = 0; return first_free_index; @@ -293,10 +284,7 @@ void nr_fill_dlsch(PHY_VARS_gNB *gNB, uint8_t *sdu) { nfapi_nr_dl_tti_pdsch_pdu_rel15_t *rel15 = &pdsch_pdu->pdsch_pdu_rel15; - if (NFAPI_MODE == NFAPI_MODE_PNF) { - gNB->dlsch[0][0]->harq_mask = 1; - gNB->dlsch[0][0]->rnti = 4660; - } + int dlsch_id = find_nr_dlsch(rel15->rnti,gNB,SEARCH_EXIST); AssertFatal( (dlsch_id>=0) && (dlsch_idnumber_of_nr_dlsch_max), "illegal or no dlsch_id found!!! rnti %04x dlsch_id %d\n",rel15->rnti,dlsch_id); diff --git a/openair1/PHY/NR_TRANSPORT/nr_ulsch_decoding.c b/openair1/PHY/NR_TRANSPORT/nr_ulsch_decoding.c index 3fee7e5dff..13c7510833 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_ulsch_decoding.c +++ b/openair1/PHY/NR_TRANSPORT/nr_ulsch_decoding.c @@ -430,22 +430,20 @@ void nr_processULSegment(void* arg) { p_procTime); if (check_crc((uint8_t*)llrProcBuf,length_dec,ulsch_harq->F,crc_type)) { -// #ifdef PRINT_CRC_CHECK - LOG_I(PHY, "Segment %d CRC OK\n",r); -// #endif +#ifdef PRINT_CRC_CHECK + LOG_D(PHY, "Segment %d CRC OK\n",r); +#endif rdata->decodeIterations = no_iteration_ldpc; } else { -// #ifdef PRINT_CRC_CHECK +#ifdef PRINT_CRC_CHECK LOG_I(PHY, "CRC NOK\n"); -// #endif +#endif rdata->decodeIterations = max_ldpc_iterations + 1; } for (int m=0; m < Kr>>3; m ++) { ulsch_harq->c[r][m]= (uint8_t) llrProcBuf[m]; - //printf("%x ", ulsch_harq->c[r][m]); } - //printf("\n"); //stop_meas(&phy_vars_gNB->ulsch_ldpc_decoding_stats); } @@ -512,7 +510,6 @@ uint32_t nr_ulsch_decoding(PHY_VARS_gNB *phy_vars_gNB, A = (harq_process->TBS)<<3; LOG_D(PHY,"ULSCH Decoding, harq_pid %d TBS %d G %d mcs %d Nl %d nb_rb %d, Qm %d, n_layers %d\n",harq_pid,A,G, mcs, n_layers, nb_rb, Qm, n_layers); - //printf("ULSCH in %d.%d \n", frame, nr_tti_rx); if (R<1024) Coderate = (float) R /(float) 1024; diff --git a/openair1/PHY/NR_TRANSPORT/pucch_rx.c b/openair1/PHY/NR_TRANSPORT/pucch_rx.c index 3b5fd2e04a..9159627286 100644 --- a/openair1/PHY/NR_TRANSPORT/pucch_rx.c +++ b/openair1/PHY/NR_TRANSPORT/pucch_rx.c @@ -166,15 +166,9 @@ void nr_decode_pucch0(PHY_VARS_gNB *gNB, int slot, nfapi_nr_uci_pucch_pdu_format_0_1_t* uci_pdu, nfapi_nr_pucch_pdu_t* pucch_pdu) { - printf("Inside nr_decode_pucch0. \n"); + int32_t **rxdataF = gNB->common_vars.rxdataF; NR_DL_FRAME_PARMS *frame_parms = &gNB->frame_parms; - //Gokul - // printf("rxdataf buff: \n"); - // for(int i = 1;i<=5*7*14*512;++i){ - // if(gNB->RU_list[0]->common.rxdataF[0][i] != 0) - // printf("%d ",gNB->RU_list[0]->common.rxdataF[0][i]); - // } int nr_sequences; const uint8_t *mcs; @@ -1092,8 +1086,7 @@ void init_pucch2_luts() { void nr_decode_pucch2(PHY_VARS_gNB *gNB, int slot, nfapi_nr_uci_pucch_pdu_format_2_3_4_t* uci_pdu, - nfapi_nr_pucch_pdu_t* pucch_pdu) { - printf("Inside nr_decode_pucch2. \n"); + nfapi_nr_pucch_pdu_t* pucch_pdu) { int32_t **rxdataF = gNB->common_vars.rxdataF; NR_DL_FRAME_PARMS *frame_parms = &gNB->frame_parms; //pucch_GroupHopping_t pucch_GroupHopping = pucch_pdu->group_hop_flag + (pucch_pdu->sequence_hop_flag<<1); diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_decoding.c b/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_decoding.c index 9bf00a6f4a..d5c0245fdc 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_decoding.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_decoding.c @@ -577,7 +577,7 @@ uint32_t nr_dlsch_decoding(PHY_VARS_NR_UE *phy_vars_ue, // Fixme: correct type is unsigned, but nrLDPC_decoder and all called behind use signed int if (check_crc((uint8_t*)llrProcBuf,length_dec,harq_process->F,crc_type)) { - LOG_I(PHY,"Segment %u CRC OK\n\033[0m",r); + LOG_D(PHY,"Segment %u CRC OK\n\033[0m",r); if (r==0) { for (int i=0;i<10;i++) LOG_D(PHY,"byte %d : %x\n",i,((uint8_t*)llrProcBuf)[i]); } @@ -587,7 +587,7 @@ uint32_t nr_dlsch_decoding(PHY_VARS_NR_UE *phy_vars_ue, ret = no_iteration_ldpc; } else { - LOG_I(PHY,"CRC NOT OK\n\033[0m"); + LOG_D(PHY,"CRC NOT OK\n\033[0m"); ret = 1 + dlsch->max_ldpc_iterations; } diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_llr_computation.c b/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_llr_computation.c index 853a3f61cf..68a206e7c7 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_llr_computation.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_llr_computation.c @@ -38,31 +38,6 @@ //#define DEBUG_LLR_SIC -void PrintIntrinsics(char *s, char *dtype, void *x) { - if (strcmp(dtype,"int") == 0) { - int *tempb = (int *)x; - printf("%s: [%d, %d, %d, %d]\n", s, tempb[0], tempb[1], tempb[2], tempb[3]); - } - if (strcmp(dtype,"short") == 0) { - short *tempb = (short *)x; - printf("%s: [%d, %d, %d, %d, %d, %d, %d, %d]\n", s, tempb[0], tempb[1], tempb[2], tempb[3], - tempb[4], tempb[5], tempb[6], tempb[7]); - } - if (strcmp(dtype,"char") == 0) { - char *tempb = (char *)x; - printf("%s: [%d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d]\n", s, - tempb[0], tempb[1], tempb[2], tempb[3], tempb[4], tempb[5], tempb[6], tempb[7], - tempb[8], tempb[9],tempb[10],tempb[11],tempb[12],tempb[13],tempb[14],tempb[15]); - } - if (strcmp(dtype,"float") == 0) { - float *tempb = (float *)x; - printf("%s: [%f, %f, %f, %f]\n", s, tempb[0], tempb[1], tempb[2], tempb[3]); - } - if (strcmp(dtype,"double") == 0) { - double *tempb = (double *)x; - printf("%s: [%f, %f]\n", s, tempb[0], tempb[1]); - } -} int16_t nr_zeros[8] __attribute__ ((aligned(16))) = {0,0,0,0,0,0,0,0}; int16_t nr_ones[8] __attribute__ ((aligned(16))) = {0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff}; @@ -759,45 +734,20 @@ void nr_dlsch_16qam_llr(NR_DL_FRAME_PARMS *frame_parms, for (i=0; i| add CRC |---->b ///////////////////////// /////////// - - // int i; - // printf("ulsch (tx): \n"); - // for (i=0;i<(A>>3);i++) - // printf("%x ",harq_process->a[i]); - // printf("\n"); - + /* + int i; + printf("ulsch (tx): \n"); + for (i=0;i<(A>>3);i++) + printf("%02x.",a[i]); + printf("\n"); + */ if (A > 3824) { // Add 24-bit crc (polynomial A) to payload diff --git a/openair1/SCHED_NR/fapi_nr_l1.c b/openair1/SCHED_NR/fapi_nr_l1.c index 3b9573bcbc..012e088dff 100644 --- a/openair1/SCHED_NR/fapi_nr_l1.c +++ b/openair1/SCHED_NR/fapi_nr_l1.c @@ -111,6 +111,8 @@ void handle_nfapi_nr_pdcch_pdu(PHY_VARS_gNB *gNB, nr_fill_dci(gNB,frame,slot,pdcch_pdu); + + } void handle_nfapi_nr_ul_dci_pdu(PHY_VARS_gNB *gNB, @@ -138,7 +140,6 @@ void handle_nr_nfapi_pdsch_pdu(PHY_VARS_gNB *gNB,int frame,int slot, void nr_schedule_response(NR_Sched_Rsp_t *Sched_INFO){ - //if(NFAPI_MODE == NFAPI_MODE_VNF) PHY_VARS_gNB *gNB; // copy data from L2 interface into L1 structures module_id_t Mod_id = Sched_INFO->module_id; @@ -185,30 +186,26 @@ void nr_schedule_response(NR_Sched_Rsp_t *Sched_INFO){ break; case NFAPI_NR_DL_TTI_PDCCH_PDU_TYPE: - AssertFatal(pdcch_received == 0, "pdcch_received is not 0, we can only handle one PDCCH PDU per slot\n"); - if(NFAPI_MODE != NFAPI_MODE_VNF){ - LOG_D(PHY,"frame %d, slot %d, Got NFAPI_NR_DL_TTI_PDCCH_PDU_TYPE for %d.%d\n",frame,slot,DL_req->SFN,DL_req->Slot); + if(NFAPI_MODE != NFAPI_MODE_VNF) handle_nfapi_nr_pdcch_pdu(gNB, frame, slot, &dl_tti_pdu->pdcch_pdu); - } + pdcch_received = 1; break; case NFAPI_NR_DL_TTI_PDSCH_PDU_TYPE: { - LOG_I(PHY,"frame %d, slot %d, Got NFAPI_NR_DL_TTI_PDSCH_PDU_TYPE for %d.%d\n",frame,slot,DL_req->SFN,DL_req->Slot); + LOG_D(PHY,"frame %d, slot %d, Got NFAPI_NR_DL_TTI_PDSCH_PDU_TYPE for %d.%d\n",frame,slot,DL_req->SFN,DL_req->Slot); nfapi_nr_dl_tti_pdsch_pdu_rel15_t *pdsch_pdu_rel15 = &dl_tti_pdu->pdsch_pdu.pdsch_pdu_rel15; uint16_t pduIndex = pdsch_pdu_rel15->pduIndex; AssertFatal(TX_req->pdu_list[pduIndex].num_TLV == 1, "TX_req->pdu_list[%d].num_TLV %d != 1\n", pduIndex,TX_req->pdu_list[pduIndex].num_TLV); uint8_t *sdu = (uint8_t *)TX_req->pdu_list[pduIndex].TLVs[0].value.direct; - if(NFAPI_MODE != NFAPI_MODE_VNF){ - LOG_D(PHY,"frame %d, slot %d, Got NFAPI_NR_DL_TTI_PDSCH_PDU_TYPE for %d.%d\n",frame,slot,DL_req->SFN,DL_req->Slot); + if(NFAPI_MODE != NFAPI_MODE_VNF) handle_nr_nfapi_pdsch_pdu(gNB,frame,slot,&dl_tti_pdu->pdsch_pdu, sdu); - } } } } @@ -255,7 +252,6 @@ void nr_schedule_response(NR_Sched_Rsp_t *Sched_INFO){ { Sched_INFO->DL_req->SFN = frame; Sched_INFO->DL_req->Slot = slot; - //printf("DL tti Frame = %d, slot = %d. \n",frame,slot); oai_nfapi_dl_tti_req(Sched_INFO->DL_req); } if (Sched_INFO->TX_req->Number_of_PDUs > 0) diff --git a/openair1/SCHED_NR/phy_procedures_nr_gNB.c b/openair1/SCHED_NR/phy_procedures_nr_gNB.c index 2d3aec5137..4a99b311db 100644 --- a/openair1/SCHED_NR/phy_procedures_nr_gNB.c +++ b/openair1/SCHED_NR/phy_procedures_nr_gNB.c @@ -623,7 +623,7 @@ int phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx) { (ulsch_harq->slot == slot_rx) && (ulsch_harq->handled == 0)){ - LOG_I(PHY, "PUSCH detection started in frame %d slot %d\n", + LOG_D(PHY, "PUSCH detection started in frame %d slot %d\n", frame_rx,slot_rx); #ifdef DEBUG_RXDATA @@ -683,10 +683,6 @@ int phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx) { T(T_GNB_PHY_PUCCH_PUSCH_IQ, T_INT(frame_rx), T_INT(slot_rx), T_BUFFER(&gNB->common_vars.rxdataF[0][0], gNB->frame_parms.symbols_per_slot * gNB->frame_parms.ofdm_symbol_size * 4)); } - if (pucch_decode_done || pusch_decode_done) { - T(T_GNB_PHY_PUCCH_PUSCH_IQ, T_INT(frame_rx), T_INT(slot_rx), T_BUFFER(&gNB->common_vars.rxdataF[0][0], gNB->frame_parms.symbols_per_slot * gNB->frame_parms.ofdm_symbol_size * 4)); - } - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_gNB_UESPEC_RX,0); return 0; } diff --git a/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c b/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c index 56efbdbad4..3417bf7653 100644 --- a/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c +++ b/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c @@ -123,7 +123,7 @@ int8_t nr_ue_scheduled_response(nr_scheduled_response_t *scheduled_response){ dlsch0_harq->Nl=1; dlsch0_harq->mcs_table=dlsch_config_pdu->mcs_table; dlsch0_harq->harq_ack.rx_status = downlink_harq_process(dlsch0_harq, dlsch0->current_harq_pid, dlsch_config_pdu->ndi, dlsch0->rnti_type); - dlsch0_harq->status = ACTIVE; //Gokul + dlsch0_harq->status = ACTIVE; if (dlsch0_harq->status != ACTIVE) { // dlsch0_harq->status not ACTIVE may be due to false retransmission. Reset the // following flag to skip PDSCH procedures in that case. diff --git a/openair1/SCHED_NR_UE/harq_nr.c b/openair1/SCHED_NR_UE/harq_nr.c index 0dcc057867..85f6d90bbe 100644 --- a/openair1/SCHED_NR_UE/harq_nr.c +++ b/openair1/SCHED_NR_UE/harq_nr.c @@ -472,7 +472,7 @@ harq_result_t downlink_harq_process(NR_DL_UE_HARQ_t *dl_harq, int harq_pid, int dl_harq->round = 0; dl_harq->status = ACTIVE; dl_harq->DCINdi = ndi; - //dl_harq->first_tx = 0; + dl_harq->first_tx = 0; result_harq = NEW_TRANSMISSION_HARQ; diff --git a/openair1/SIMULATION/NR_PHY/dlsim.c b/openair1/SIMULATION/NR_PHY/dlsim.c index 21bc041f52..730e78c162 100644 --- a/openair1/SIMULATION/NR_PHY/dlsim.c +++ b/openair1/SIMULATION/NR_PHY/dlsim.c @@ -121,21 +121,6 @@ int8_t nr_mac_rrc_data_req_ue(const module_id_t Mod_idP, return 0; } -void nr_rrc_ue_generate_RRCSetupRequest(module_id_t module_id, const uint8_t gNB_index) -{ - return; -} - -int8_t nr_mac_rrc_data_req_ue(const module_id_t Mod_idP, - const int CC_id, - const uint8_t gNB_id, - const frame_t frameP, - const rb_id_t Srb_id, - uint8_t *buffer_pP) -{ - return 0; -} - void rrc_data_ind( const protocol_ctxt_t *const ctxt_pP, diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c index 94f3931424..eacf4f54a9 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c @@ -324,12 +324,12 @@ bool is_xlsch_in_slot(uint64_t bitmap, sub_frame_t slot) { void gNB_dlsch_ulsch_scheduler(module_id_t module_idP, frame_t frame, sub_frame_t slot){ - gNB_MAC_INST *mac = RC.nrmac[module_idP]; - nfapi_nr_config_request_scf_t *cfg = &mac->config[0]; + protocol_ctxt_t ctxt; PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, module_idP, ENB_FLAG_YES, NOT_A_RNTI, frame, slot,module_idP); const int bwp_id = 1; + gNB_MAC_INST *gNB = RC.nrmac[module_idP]; NR_COMMON_channels_t *cc = gNB->common_channels; NR_ServingCellConfigCommon_t *scc = cc->ServingCellConfigCommon; @@ -374,6 +374,7 @@ void gNB_dlsch_ulsch_scheduler(module_id_t module_idP, const int last_slot = (slot + num_slots - 1) % num_slots; uint16_t *vrb_map_UL = cc[CC_id].vrb_map_UL; memset(&vrb_map_UL[last_slot * MAX_BWP_SIZE], 0, sizeof(uint16_t) * MAX_BWP_SIZE); + clear_nr_nfapi_information(RC.nrmac[module_idP], CC_id, frame, slot); } diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c index 02e0e42139..b428805882 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c @@ -851,15 +851,7 @@ void nr_schedule_ue_spec(module_id_t module_id, const int bwpid = sched_ctrl->active_bwp->bwp_Id; const int coresetid = sched_ctrl->coreset->controlResourceSetId; nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu = gNB_mac->pdcch_pdu_idx[CC_id][bwpid][coresetid]; - //nfapi_nr_dl_tti_pdcch_pdu_rel15_t temp; - // if(NFAPI_MODE == NFAPI_MODE_VNF){ - // memcpy(temp,gNB_mac->pdcch_pdu_idx[CC_id][bwpid][coresetid],sizeof(nfapi_nr_dl_tti_pdcch_pdu_rel15_t)); - // pdcch_pdu = temp; - - // } - if (!pdcch_pdu) { - printf("creating pdcch pdu, pdcch_pdu = NULL. \n"); 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(nfapi_nr_dl_tti_request_pdu_t)); dl_tti_pdcch_pdu->PDUType = NFAPI_NR_DL_TTI_PDCCH_PDU_TYPE; @@ -902,14 +894,6 @@ void nr_schedule_ue_spec(module_id_t module_id, pdsch_pdu->mcsTable[0] = ps->mcsTableIdx; AssertFatal(harq->round<4,"%d",harq->round); pdsch_pdu->rvIndex[0] = nr_rv_round_map[harq->round]; - // if (NFAPI_MODE == NFAPI_MODE_VNF){ // done since uplink isnt operational yet which means harq structures dont get filled properly - // pdsch_pdu->rvIndex[0] = nr_rv_round_map[harq_rounds]; - // if (harq_rounds % 5 == 0 && harq_rounds!=0){ - // harq_rounds = 0; - // harq_pid = (harq_pid + 1) % 16; - // } - // harq_rounds++; - // } pdsch_pdu->TBSize[0] = TBS; pdsch_pdu->dataScramblingId = *scc->physCellId; @@ -1018,10 +1002,6 @@ void nr_schedule_ue_spec(module_id_t module_id, const int dci_format = f ? NR_DL_DCI_FORMAT_1_1 : NR_DL_DCI_FORMAT_1_0; const int rnti_type = NR_RNTI_C; - // if (NFAPI_MODE == NFAPI_MODE_VNF){ - // dci_payload.harq_pid = harq_pid; - // dci_payload.tpc = 2; - // } fill_dci_pdu_rel15(scc, UE_info->secondaryCellGroup[UE_id], dci_pdu, diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c index 9a50297dd1..b3d2ecb0b2 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c @@ -62,7 +62,6 @@ #include "common/ran_context.h" extern RAN_CONTEXT_t RC; -uint8_t count = 0; uint8_t harq_pid_ul = -1; int flag = 0; // Note the 2 scs values in the table names represent resp. scs_common and pdcch_scs /// LUT for the number of symbols in the coreset indexed by coreset index (4 MSB rmsi_pdcch_config) @@ -1365,11 +1364,6 @@ void fill_dci_pdu_rel15(const NR_ServingCellConfigCommon_t *scc, case NR_UL_DCI_FORMAT_0_1: switch (rnti_type) { case NR_RNTI_C: - harq_pid_ul = (harq_pid_ul + 1) % 16; - if (harq_pid_ul == 0) - flag = !flag; - dci_pdu_rel15->ndi = flag; - // Indicating a DL DCI format 1bit pos = 1; *dci_pdu |= ((uint64_t)dci_pdu_rel15->format_indicator & 0x1) << (dci_size - pos); @@ -1402,7 +1396,6 @@ void fill_dci_pdu_rel15(const NR_ServingCellConfigCommon_t *scc, *dci_pdu |= ((uint64_t)dci_pdu_rel15->rv & 0x3) << (dci_size - pos); // HARQ process number 4bit pos += 4; - dci_pdu_rel15->harq_pid = harq_pid_ul; *dci_pdu |= ((uint64_t)dci_pdu_rel15->harq_pid & 0xf) << (dci_size - pos); // 1st Downlink assignment index pos += dci_pdu_rel15->dai[0].nbits; @@ -1816,7 +1809,6 @@ int add_new_nr_ue(module_id_t mod_idP, rnti_t rntiP, NR_CellGroupConfig_t *secon const NR_PDSCH_ServingCellConfig_t *pdsch = servingCellConfig->pdsch_ServingCellConfig->choice.setup; const int nrofHARQ = pdsch->nrofHARQ_ProcessesForPDSCH ? get_nrofHARQ_ProcessesForPDSCH(*pdsch->nrofHARQ_ProcessesForPDSCH) : 8; - printf("nrofHARQ = %d\n", nrofHARQ); // add all available DL HARQ processes for this UE create_nr_list(&sched_ctrl->available_dl_harq, nrofHARQ); for (int harq = 0; harq < nrofHARQ; harq++) diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c index 6f5946fe27..b667c8d977 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c @@ -45,6 +45,11 @@ void nr_fill_nfapi_pucch(module_id_t mod_id, nfapi_nr_ul_tti_request_t *future_ul_tti_req = &RC.nrmac[mod_id]->UL_tti_req_ahead[0][pucch->ul_slot]; + if (NFAPI_MODE == NFAPI_MODE_VNF){ + future_ul_tti_req->SFN = pucch->frame; + future_ul_tti_req->Slot = pucch->ul_slot; + } + AssertFatal(future_ul_tti_req->SFN == pucch->frame && future_ul_tti_req->Slot == pucch->ul_slot, "future UL_tti_req's frame.slot %d.%d does not match PUCCH %d.%d\n", @@ -507,9 +512,10 @@ void nr_csi_meas_reporting(int Mod_idP, // find free PUCCH that is in order with possibly existing PUCCH // schedulings (other CSI, SR) - NR_sched_pucch_t *curr_pucch = &sched_ctrl->sched_pucch[2]; - if(NFAPI_MODE == NFAPI_MODE_VNF) - curr_pucch->csi_bits = 0; + NR_sched_pucch_t *curr_pucch = &sched_ctrl->sched_pucch[1]; + if(NFAPI_MODE == NFAPI_MODE_VNF){ + curr_pucch->csi_bits = 0; curr_pucch->sr_flag = 0; curr_pucch->dai_c = 0; + } AssertFatal(curr_pucch->csi_bits == 0 && !curr_pucch->sr_flag && curr_pucch->dai_c == 0, @@ -1000,63 +1006,51 @@ void handle_nr_uci_pucch_0_1(module_id_t mod_id, frame_t frame, sub_frame_t slot, const nfapi_nr_uci_pucch_pdu_format_0_1_t *uci_01) -{ NR_UE_info_t *UE_info = &RC.nrmac[mod_id]->UE_info; - UE_info->active[0] = 1; - UE_info->rnti[0] = uci_01->rnti; +{ int UE_id = find_nr_UE_id(mod_id, uci_01->rnti); if (UE_id < 0) { LOG_E(MAC, "%s(): unknown RNTI %04x in PUCCH UCI\n", __func__, uci_01->rnti); return; } - //NR_UE_info_t *UE_info = &RC.nrmac[mod_id]->UE_info; + NR_UE_info_t *UE_info = &RC.nrmac[mod_id]->UE_info; NR_UE_sched_ctrl_t *sched_ctrl = &UE_info->UE_sched_ctrl[UE_id]; - // tpc (power control) - sched_ctrl->tpc1 = nr_get_tpc(RC.nrmac[mod_id]->pucch_target_snrx10, - uci_01->ul_cqi, - 30); + if (((uci_01->pduBitmap >> 1) & 0x01)) { + // iterate over received harq bits + for (int harq_bit = 0; harq_bit < uci_01->harq->num_harq; harq_bit++) { + const uint8_t harq_value = uci_01->harq->harq_list[harq_bit].harq_value; + const uint8_t harq_confidence = uci_01->harq->harq_confidence_level; + NR_UE_harq_t *harq = find_harq(mod_id, frame, slot, UE_id); + if (!harq) + break; + DevAssert(harq->is_waiting); + const int8_t pid = sched_ctrl->feedback_dl_harq.head; + remove_front_nr_list(&sched_ctrl->feedback_dl_harq); + handle_dl_harq(mod_id, UE_id, pid, harq_value == 1 && harq_confidence == 0); + } + } - // NR_ServingCellConfigCommon_t *scc = RC.nrmac[mod_id]->common_channels->ServingCellConfigCommon; - // const int num_slots = nr_slots_per_frame[*scc->ssbSubcarrierSpacing]; - const int num_slots = 20; - - // if (((uci_01->pduBitmap >> 1) & 0x01)) { - // // iterate over received harq bits - // for (int harq_bit = 0; harq_bit < uci_01->harq->num_harq; harq_bit++) { - // const uint8_t harq_value = uci_01->harq->harq_list[harq_bit].harq_value; - // const uint8_t harq_confidence = uci_01->harq->harq_confidence_level; - // const int feedback_slot = (slot - 1 + num_slots) % num_slots; - // /* In case of realtime problems: we can only identify a HARQ process by - // * timing. If the HARQ process's feedback_slot is not the one we - // * expected, we assume that processing has been aborted and we need to - // * skip this HARQ process, which is what happens in the loop below. If - // * you don't experience real-time problems, you might simply revert the - // * commit that introduced these changes. */ - // int8_t pid = sched_ctrl->feedback_dl_harq.head; - // DevAssert(pid >= 0); - // while (sched_ctrl->harq_processes[pid].feedback_slot != feedback_slot) { - // LOG_W(MAC, - // "expected feedback slot %d, but found %d instead\n", - // sched_ctrl->harq_processes[pid].feedback_slot, - // feedback_slot); - // remove_front_nr_list(&sched_ctrl->feedback_dl_harq); - // handle_dl_harq(mod_id, UE_id, pid, 0); - // pid = sched_ctrl->feedback_dl_harq.head; - // DevAssert(pid >= 0); - // } - // remove_front_nr_list(&sched_ctrl->feedback_dl_harq); - // NR_UE_harq_t *harq = &sched_ctrl->harq_processes[pid]; - // DevAssert(harq->is_waiting); - // handle_dl_harq(mod_id, UE_id, pid, harq_value == 1 && harq_confidence == 0); - // } - // } + // check scheduling request result, confidence_level == 0 is good + if (uci_01->pduBitmap & 0x1 && uci_01->sr->sr_indication && uci_01->sr->sr_confidence_level == 0 && uci_01->ul_cqi >= 148) { + // SR detected with SNR >= 10dB + sched_ctrl->SR |= true; + LOG_D(MAC, "SR UE %04x ul_cqi %d\n", uci_01->rnti, uci_01->ul_cqi); + } + + // tpc (power control) only if we received AckNack or positive SR. For a + // negative SR, the UE won't have sent anything, and the SNR is not valid + if (((uci_01->pduBitmap >> 1) & 0x1) || sched_ctrl->SR) { + sched_ctrl->tpc1 = nr_get_tpc(RC.nrmac[mod_id]->pucch_target_snrx10, uci_01->ul_cqi, 30); + sched_ctrl->pucch_snrx10 = uci_01->ul_cqi * 5 - 640; + } } void handle_nr_uci_pucch_2_3_4(module_id_t mod_id, frame_t frame, sub_frame_t slot, const nfapi_nr_uci_pucch_pdu_format_2_3_4_t *uci_234) -{ int UE_id = find_nr_UE_id(mod_id, uci_234->rnti); +{ + int UE_id = find_nr_UE_id(mod_id, uci_234->rnti); if (UE_id < 0) { LOG_E(MAC, "%s(): unknown RNTI %04x in PUCCH UCI\n", __func__, uci_234->rnti); return; @@ -1064,57 +1058,25 @@ void handle_nr_uci_pucch_2_3_4(module_id_t mod_id, NR_CSI_MeasConfig_t *csi_MeasConfig = RC.nrmac[mod_id]->UE_info.secondaryCellGroup[UE_id]->spCellConfig->spCellConfigDedicated->csi_MeasConfig->choice.setup; NR_UE_info_t *UE_info = &RC.nrmac[mod_id]->UE_info; NR_UE_sched_ctrl_t *sched_ctrl = &UE_info->UE_sched_ctrl[UE_id]; - if (NFAPI_MODE == NFAPI_MODE_PNF){ - UE_info->active[0] = 1; - UE_info->rnti[0] = uci_234->rnti; - } - + // tpc (power control) sched_ctrl->tpc1 = nr_get_tpc(RC.nrmac[mod_id]->pucch_target_snrx10, uci_234->ul_cqi, 30); sched_ctrl->pucch_snrx10 = uci_234->ul_cqi * 5 - 640; - // NR_ServingCellConfigCommon_t *scc = RC.nrmac[mod_id]->common_channels->ServingCellConfigCommon; - // const int num_slots = nr_slots_per_frame[*scc->ssbSubcarrierSpacing]; - const int num_slots = 20; - // if ((uci_234->pduBitmap >> 1) & 0x01) { - // // iterate over received harq bits - // for (int harq_bit = 0; harq_bit < uci_234->harq.harq_bit_len; harq_bit++) { - // const int acknack = ((uci_234->harq.harq_payload[harq_bit >> 3]) >> harq_bit) & 0x01; - // const int feedback_slot = (slot - 1 + num_slots) % num_slots; - // /* In case of realtime problems: we can only identify a HARQ process by - // * timing. If the HARQ process's feedback_slot is not the one we - // * expected, we assume that processing has been aborted and we need to - // * skip this HARQ process, which is what happens in the loop below. If - // * you don't experience real-time problems, you might simply revert the - // * commit that introduced these changes. */ - // int8_t pid = sched_ctrl->feedback_dl_harq.head; - // DevAssert(pid >= 0); - // while (sched_ctrl->harq_processes[pid].feedback_slot != feedback_slot) { - // LOG_W(MAC, - // "expected feedback slot %d, but found %d instead\n", - // sched_ctrl->harq_processes[pid].feedback_slot, - // feedback_slot); - // remove_front_nr_list(&sched_ctrl->feedback_dl_harq); - // handle_dl_harq(mod_id, UE_id, pid, 0); - // pid = sched_ctrl->feedback_dl_harq.head; - // DevAssert(pid >= 0); - // } - // remove_front_nr_list(&sched_ctrl->feedback_dl_harq); - // NR_UE_harq_t *harq = &sched_ctrl->harq_processes[pid]; - // DevAssert(harq->is_waiting); - // handle_dl_harq(mod_id, UE_id, pid, uci_234->harq.harq_crc != 1 && acknack); - // } - // } - if ((uci_234->pduBitmap >> 2) & 0x01) { - //API to parse the csi report and store it into sched_ctrl - extract_pucch_csi_report (csi_MeasConfig, uci_234, frame, slot, UE_id, mod_id); - //TCI handling function - tci_handling(mod_id, UE_id,frame, slot); - } - if ((uci_234->pduBitmap >> 3) & 0x01) { - //@TODO:Handle CSI Report 2 + if ((uci_234->pduBitmap >> 1) & 0x01) { + // iterate over received harq bits + for (int harq_bit = 0; harq_bit < uci_234->harq.harq_bit_len; harq_bit++) { + const int acknack = ((uci_234->harq.harq_payload[harq_bit >> 3]) >> harq_bit) & 0x01; + NR_UE_harq_t *harq = find_harq(mod_id, frame, slot, UE_id); + if (!harq) + break; + DevAssert(harq->is_waiting); + const int8_t pid = sched_ctrl->feedback_dl_harq.head; + remove_front_nr_list(&sched_ctrl->feedback_dl_harq); + handle_dl_harq(mod_id, UE_id, pid, uci_234->harq.harq_crc != 1 && acknack); + } } if ((uci_234->pduBitmap >> 2) & 0x01) { //API to parse the csi report and store it into sched_ctrl @@ -1127,7 +1089,6 @@ void handle_nr_uci_pucch_2_3_4(module_id_t mod_id, } } - // function to update pucch scheduling parameters in UE list when a USS DL is scheduled // this function returns an index to NR_sched_pucch structure // currently this structure contains PUCCH0 at index 0 and PUCCH2 at index 1 @@ -1197,7 +1158,6 @@ int nr_acknack_scheduling(int mod_id, nr_fill_nfapi_pucch(mod_id, frame, slot, csi_pucch, UE_id); memset(csi_pucch, 0, sizeof(*csi_pucch)); pucch->frame = s >= n_slots_frame - 2 ? (f + 1) % 1024 : f; - printf("pucch frame filled. \n"); pucch->ul_slot = (s + 2) % n_slots_frame; } } @@ -1205,6 +1165,7 @@ int nr_acknack_scheduling(int mod_id, /* if the UE's next PUCCH occasion is after the possible UL slots (within the * same frame) or wrapped around to the next frame, then we assume there is * no possible PUCCH allocation anymore */ + if(NFAPI_MODE == NFAPI_MONOLITHIC) if ((pucch->frame == frame && (pucch->ul_slot >= first_ul_slot_tdd + nr_ulmix_slots)) || (pucch->frame == frame + 1)) @@ -1216,6 +1177,8 @@ int nr_acknack_scheduling(int mod_id, get_pdsch_to_harq_feedback(mod_id, UE_id, ss_type, pdsch_to_harq_feedback); /* there is a HARQ. Check whether we can use it for this ACKNACK */ + if(NFAPI_MODE == NFAPI_MODE_VNF) + return 0; if (pucch->dai_c > 0) { /* this UE already has a PUCCH occasion */ DevAssert(pucch->frame == frame); diff --git a/openair2/NR_PHY_INTERFACE/NR_IF_Module.c b/openair2/NR_PHY_INTERFACE/NR_IF_Module.c index 2190886226..1481865128 100644 --- a/openair2/NR_PHY_INTERFACE/NR_IF_Module.c +++ b/openair2/NR_PHY_INTERFACE/NR_IF_Module.c @@ -105,10 +105,6 @@ void handle_nr_uci(NR_UL_IND_t *UL_info) } UL_info->uci_ind.num_ucis = 0; - // if(NFAPI_MODE != NFAPI_MODE_PNF) - // // mark corresponding PUCCH resources as free - // // NOTE: we just assume it is BWP ID 1, to be revised for multiple BWPs - // RC.nrmac[mod_id]->pucch_index_used[1][slot] = 0; } @@ -139,18 +135,18 @@ void handle_nr_ulsch(NR_UL_IND_t *UL_info) crc->tb_crc_status); /* if CRC passes, pass PDU, otherwise pass NULL as error indication */ - //Gokul - // nr_rx_sdu(UL_info->module_id, - // UL_info->CC_id, - // UL_info->rx_ind.sfn, - // UL_info->rx_ind.slot, - // rx->rnti, - // crc->tb_crc_status ? NULL : rx->pdu, - // rx->pdu_length, - // rx->timing_advance, - // rx->ul_cqi, - // rx->rssi); - //handle_nr_ul_harq(UL_info->module_id, UL_info->frame, UL_info->slot, crc); + + nr_rx_sdu(UL_info->module_id, + UL_info->CC_id, + UL_info->rx_ind.sfn, + UL_info->rx_ind.slot, + rx->rnti, + crc->tb_crc_status ? NULL : rx->pdu, + rx->pdu_length, + rx->timing_advance, + rx->ul_cqi, + rx->rssi); + handle_nr_ul_harq(UL_info->module_id, UL_info->frame, UL_info->slot, crc); break; } // for (j=0;jcrc_ind.number_crcs;j++) } // for (i=0;irx_ind.number_of_pdus;i++) @@ -173,7 +169,6 @@ void handle_nr_ulsch(NR_UL_IND_t *UL_info) } void NR_UL_indication(NR_UL_IND_t *UL_info) { - //printf("Inside NR UL Indication. \n"); AssertFatal(UL_info!=NULL,"UL_INFO is null\n"); #ifdef DUMP_FAPI dump_ul(UL_info); @@ -183,7 +178,6 @@ void NR_UL_indication(NR_UL_IND_t *UL_info) { NR_Sched_Rsp_t *sched_info = &NR_Sched_INFO[module_id][CC_id]; NR_IF_Module_t *ifi = nr_if_inst[module_id]; gNB_MAC_INST *mac = RC.nrmac[module_id]; - nfapi_nr_config_request_scf_t *cfg = &mac->config[CC_id]; LOG_D(PHY,"SFN/SF:%d%d module_id:%d CC_id:%d UL_info[rach_pdus:%d rx_ind:%d crcs:%d]\n", UL_info->frame,UL_info->slot, module_id,CC_id, UL_info->rach_ind.number_of_pdus, @@ -216,7 +210,7 @@ void NR_UL_indication(NR_UL_IND_t *UL_info) { (UL_info->frame+((UL_info->slot>(9-sl_ahead))?1:0)) % 1024, (UL_info->slot+sl_ahead)%10); */ - + nfapi_nr_config_request_scf_t *cfg = &mac->config[CC_id]; int spf = get_spf(cfg); gNB_dlsch_ulsch_scheduler(module_id, (UL_info->frame+((UL_info->slot>(spf-1-sl_ahead))?1:0)) % 1024, @@ -245,7 +239,10 @@ void NR_UL_indication(NR_UL_IND_t *UL_info) { ifi->NR_Schedule_response(sched_info); } - + LOG_D(PHY,"NR_Schedule_response: SFN_SF:%d%d dl_pdus:%d\n", + sched_info->frame, + sched_info->slot, + sched_info->DL_req->dl_tti_request_body.nPDUs); } } } diff --git a/targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp b/targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp index 1de76bb257..83a6207eec 100644 --- a/targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp +++ b/targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp @@ -1144,7 +1144,7 @@ extern "C" { case 46080000: //openair0_cfg[0].samples_per_packet = 2048; - openair0_cfg[0].tx_sample_advance = 65; + openair0_cfg[0].tx_sample_advance = 15; openair0_cfg[0].tx_bw = 40e6; openair0_cfg[0].rx_bw = 40e6; break; @@ -1159,7 +1159,7 @@ extern "C" { case 15360000: //openair0_cfg[0].samples_per_packet = 2048; - openair0_cfg[0].tx_sample_advance = 40; + openair0_cfg[0].tx_sample_advance = 45; openair0_cfg[0].tx_bw = 10e6; openair0_cfg[0].rx_bw = 10e6; break; From 8889d6d8089c415f9fd3dabb757704ef1de92e66 Mon Sep 17 00:00:00 2001 From: Gokul Srinivasan Date: Sun, 30 May 2021 21:05:12 +0000 Subject: [PATCH 22/91] Add .gitlab-ci.yml --- .gitlab-ci.yml | 1 + 1 file changed, 1 insertion(+) create mode 100644 .gitlab-ci.yml diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml new file mode 100644 index 0000000000..8b13789179 --- /dev/null +++ b/.gitlab-ci.yml @@ -0,0 +1 @@ + From 4dc9d22f166c73f0f678033f1d6326ee6847b6d9 Mon Sep 17 00:00:00 2001 From: Gokul Srinivasan Date: Mon, 7 Jun 2021 22:41:08 +0000 Subject: [PATCH 23/91] bugfix in gNB_scheduler_uci.c --- openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c index b667c8d977..46ccc8ac53 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c @@ -1128,8 +1128,10 @@ int nr_acknack_scheduling(int mod_id, __func__, pucch->csi_bits); /* if the currently allocated PUCCH of this UE is full, allocate it */ - if (NFAPI_MODE == NFAPI_MODE_VNF) - pucch->sr_flag = 1; pucch->dai_c = 1; + if (NFAPI_MODE == NFAPI_MODE_VNF){ + pucch->sr_flag = 1; + pucch->dai_c = 1; + } if (pucch->dai_c == 2) { /* advance the UL slot information in PUCCH by one so we won't schedule in From e93df00434d6e7f6d155c78281dcc249a16fe97b Mon Sep 17 00:00:00 2001 From: Gokul Srinivasan Date: Tue, 8 Jun 2021 12:46:34 +0000 Subject: [PATCH 24/91] Update nfapi/open-nFAPI/nfapi/public_inc/fapi_nr_ue_interface.h, openair1/SCHED_NR_UE/fapi_nr_ue_l1.c, nfapi/oai_integration/nfapi_pnf.h, nfapi/oai_integration/nfapi_pnf.c files --- nfapi/oai_integration/nfapi_pnf.c | 1 - nfapi/oai_integration/nfapi_pnf.h | 1 + nfapi/open-nFAPI/nfapi/public_inc/fapi_nr_ue_interface.h | 8 +------- openair1/SCHED_NR_UE/fapi_nr_ue_l1.c | 1 - 4 files changed, 2 insertions(+), 9 deletions(-) diff --git a/nfapi/oai_integration/nfapi_pnf.c b/nfapi/oai_integration/nfapi_pnf.c index 98757b09d0..ed0bafa300 100644 --- a/nfapi/oai_integration/nfapi_pnf.c +++ b/nfapi/oai_integration/nfapi_pnf.c @@ -73,7 +73,6 @@ extern pthread_mutex_t nfapi_sync_mutex; extern int nfapi_sync_var; extern int sync_var; -char uecap_xer_in; extern void init_eNB_afterRU(void); extern void init_UE_stub(int nb_inst,int,int); diff --git a/nfapi/oai_integration/nfapi_pnf.h b/nfapi/oai_integration/nfapi_pnf.h index b3ab7cbdbc..61d4847eba 100644 --- a/nfapi/oai_integration/nfapi_pnf.h +++ b/nfapi/oai_integration/nfapi_pnf.h @@ -21,6 +21,7 @@ #if !defined(NFAPI_PNF_H__) #define NFAPI_PNF_H__ +extern nfapi_ue_release_request_body_t release_rntis; int oai_nfapi_rach_ind(nfapi_rach_indication_t *rach_ind); void configure_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_pnf(char *vnf_ip_addr, int vnf_p5_port, char *pnf_ip_addr, int pnf_p7_port, int vnf_p7_port); 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 9df9be4cbd..0436f92a8d 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 @@ -972,7 +972,7 @@ typedef struct typedef struct { - uint32_t ss_pbch_power;//SSB Block Power Value: TBD (-60..50 dBm) + int ss_pbch_power;//SSB Block Power Value: TBD (-60..50 dBm) uint8_t bch_payload;//Defines option selected for generation of BCH payload, see Table 3-13 (v0.0.011 Value: 0: MAC generates the full PBCH payload 1: PHY generates the timing PBCH bits 2: PHY generates the full PBCH payload uint8_t scs_common;//subcarrierSpacing for common, used for initial access and broadcast message. [38.211 sec 4.2] Value:0->3 @@ -1058,12 +1058,6 @@ typedef struct { fapi_nr_tdd_table_t tdd_table; fapi_nr_prach_config_t prach_config; - fapi_nr_dl_bwp_common_config_t dl_bwp_common; - fapi_nr_dl_bwp_dedicated_config_t dl_bwp_dedicated; - - fapi_nr_ul_bwp_common_config_t ul_bwp_common; - fapi_nr_ul_bwp_dedicated_config_t ul_bwp_dedicated; - } fapi_nr_config_request_t; #endif diff --git a/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c b/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c index 3417bf7653..c8ac871bbf 100644 --- a/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c +++ b/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c @@ -123,7 +123,6 @@ int8_t nr_ue_scheduled_response(nr_scheduled_response_t *scheduled_response){ dlsch0_harq->Nl=1; dlsch0_harq->mcs_table=dlsch_config_pdu->mcs_table; dlsch0_harq->harq_ack.rx_status = downlink_harq_process(dlsch0_harq, dlsch0->current_harq_pid, dlsch_config_pdu->ndi, dlsch0->rnti_type); - dlsch0_harq->status = ACTIVE; if (dlsch0_harq->status != ACTIVE) { // dlsch0_harq->status not ACTIVE may be due to false retransmission. Reset the // following flag to skip PDSCH procedures in that case. From f879260bf9888065fc2bed8a42c20b9e463f825e Mon Sep 17 00:00:00 2001 From: francescomani Date: Fri, 11 Jun 2021 18:11:09 +0200 Subject: [PATCH 25/91] removing unused fapi structures at UE --- .../nfapi/public_inc/fapi_nr_ue_interface.h | 431 ------------------ .../NR_ESTIMATION/nr_ul_channel_estimation.c | 5 +- .../PHY/NR_TRANSPORT/nr_ulsch_demodulation.c | 2 +- openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c | 19 +- openair1/SIMULATION/NR_PHY/ulsim.c | 12 +- openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c | 10 +- 6 files changed, 25 insertions(+), 454 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 c48af917b1..809d90191a 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 @@ -456,437 +456,6 @@ typedef struct { } fapi_nr_dl_config_request_t; -// -// P5 -// - - - -typedef struct { - fapi_nr_coreset_t coreset; - - uint8_t monitoring_slot_peridicity; - uint8_t monitoring_slot_offset; - uint16_t duration; - uint16_t monitoring_symbols_within_slot; - uint8_t number_of_candidates[5]; // aggregation level 1, 2, 4, 8, 16 - - uint8_t dci_2_0_number_of_candidates[5]; // aggregation level 1, 2, 4, 8, 16 - uint8_t dci_2_3_monitorying_periodicity; - uint8_t dci_2_3_number_of_candidates; - -} fapi_nr_search_space_t; - -typedef struct { - fapi_nr_search_space_t search_space_sib1; - fapi_nr_search_space_t search_space_others_sib; - fapi_nr_search_space_t search_space_paging; - //fapi_nr_coreset_t coreset_ra; // common coreset - fapi_nr_search_space_t search_space_ra; -} fapi_nr_pdcch_config_common_t; - -typedef struct { - uint8_t k0; - uint8_t mapping_type; - uint8_t symbol_starting; - uint8_t symbol_length; -} fapi_nr_pdsch_time_domain_resource_allocation_t; - -typedef struct { - fapi_nr_pdsch_time_domain_resource_allocation_t allocation_list[FAPI_NR_MAX_NUM_DL_ALLOCATIONS]; -} fapi_nr_pdsch_config_common_t; - -typedef struct { - uint8_t prach_configuration_index; - uint8_t msg1_fdm; - uint8_t msg1_frequency_start; - uint8_t zero_correlation_zone_config; - uint8_t preamble_received_target_power; - uint8_t preamble_transmission_max; - uint8_t power_ramping_step; - uint8_t ra_window_size; - - uint8_t total_number_of_preamble; - uint8_t ssb_occasion_per_rach; - uint8_t cb_preamble_per_ssb; - - uint8_t group_a_msg3_size; - uint8_t group_a_number_of_preamble; - uint8_t group_b_power_offset; - uint8_t contention_resolution_timer; - uint8_t rsrp_threshold_ssb; - uint8_t rsrp_threshold_ssb_sul; - uint8_t prach_length; // l839, l139 - uint8_t prach_root_sequence_index; // 0 - 837 for l839, 0 - 137 for l139 - uint8_t msg1_subcarrier_spacing; - uint8_t restrictedset_config; - uint8_t msg3_transform_precoding; -} fapi_nr_rach_config_common_t; - -typedef struct { - uint8_t k2; - uint8_t mapping_type; - uint8_t symbol_starting; - uint8_t symbol_length; -} fapi_nr_pusch_time_domain_resource_allocation_t; - -typedef struct { - uint8_t group_hopping_enabled_transform_precoding; - fapi_nr_pusch_time_domain_resource_allocation_t allocation_list[FAPI_NR_MAX_NUM_UL_ALLOCATIONS]; - uint8_t msg3_delta_preamble; - uint8_t p0_nominal_with_grant; -} fapi_nr_pusch_config_common_t; - -typedef struct { - uint8_t pucch_resource_common; - uint8_t pucch_group_hopping; - uint8_t hopping_id; - uint8_t p0_nominal; -} fapi_nr_pucch_config_common_t; - -typedef struct { - - fapi_nr_pdcch_config_common_t pdcch_config_common; - fapi_nr_pdsch_config_common_t pdsch_config_common; - -} fapi_nr_dl_bwp_common_config_t; - - - -typedef struct { - uint16_t int_rnti; - uint8_t time_frequency_set; - uint8_t dci_payload_size; - uint8_t serving_cell_id[FAPI_NR_MAX_NUM_SERVING_CELLS]; // interrupt configuration per serving cell - uint8_t position_in_dci[FAPI_NR_MAX_NUM_SERVING_CELLS]; // interrupt configuration per serving cell -} fapi_nr_downlink_preemption_t; - -typedef struct { - uint8_t tpc_index; - uint8_t tpc_index_sul; - uint8_t target_cell; -} fapi_nr_pusch_tpc_command_config_t; - -typedef struct { - uint8_t tpc_index_pcell; - uint8_t tpc_index_pucch_scell; -} fapi_nr_pucch_tpc_command_config_t; - -typedef struct { - uint8_t starting_bit_of_format_2_3; - uint8_t feild_type_format_2_3; -} fapi_nr_srs_tpc_command_config_t; - -typedef struct { - fapi_nr_downlink_preemption_t downlink_preemption; - fapi_nr_pusch_tpc_command_config_t tpc_pusch; - fapi_nr_pucch_tpc_command_config_t tpc_pucch; - fapi_nr_srs_tpc_command_config_t tpc_srs; -} fapi_nr_pdcch_config_dedicated_t; - -typedef struct { - uint8_t dmrs_type; - uint8_t dmrs_addition_position; - uint8_t max_length; - uint16_t scrambling_id0; - uint16_t scrambling_id1; - uint8_t ptrs_frequency_density[2]; // phase tracking rs - uint8_t ptrs_time_density[3]; // phase tracking rs - uint8_t ptrs_epre_ratio; // phase tracking rs - uint8_t ptrs_resource_element_offset; // phase tracking rs -} fapi_nr_dmrs_downlink_config_t; - -typedef struct { - uint8_t bwp_or_cell_level; - uint8_t pattern_type; - uint32_t resource_blocks[9]; // bitmaps type 275 bits - uint8_t slot_type; // bitmaps type one/two slot(s) - uint32_t symbols_in_resouece_block; // bitmaps type 14/28 bits - uint8_t periodic; // bitmaps type - uint32_t pattern[2]; // bitmaps type 2/4/5/8/10/20/40 bits - - fapi_nr_coreset_t coreset; // coreset - - uint8_t subcarrier_spacing; - uint8_t mode; -} fapi_nr_rate_matching_pattern_group_t; - -typedef struct { - // resource mapping - uint8_t row; // row1/row2/row4/other - uint16_t frequency_domain_allocation; // 4/12/3/6 bits - uint8_t number_of_ports; - uint8_t first_ofdm_symbol_in_time_domain; - uint8_t first_ofdm_symbol_in_time_domain2; - uint8_t cdm_type; - uint8_t density; // .5/1/3 - uint8_t density_dot5_type; // even/odd PRBs - - uint8_t frequency_band_starting_rb; // freqBand - uint8_t frequency_band_number_of_rb; // freqBand - - // periodicityAndOffset - uint8_t periodicity; // slot4/5/8/10/16/20/32/40/64/80/160/320/640 - uint32_t offset; // 0..639 bits -} fapi_nr_zp_csi_rs_resource_t; - -typedef struct { - uint16_t data_scrambling_id_pdsch; - fapi_nr_dmrs_downlink_config_t dmrs_dl_for_pdsch_mapping_type_a; - fapi_nr_dmrs_downlink_config_t dmrs_dl_for_pdsch_mapping_type_b; - uint8_t vrb_to_prb_interleaver; - uint8_t resource_allocation; - fapi_nr_pdsch_time_domain_resource_allocation_t allocation_list[FAPI_NR_MAX_NUM_DL_ALLOCATIONS]; - uint8_t pdsch_aggregation_factor; - fapi_nr_rate_matching_pattern_group_t rate_matching_pattern_group1; - fapi_nr_rate_matching_pattern_group_t rate_matching_pattern_group2; - uint8_t rbg_size; - uint8_t mcs_table; - uint8_t max_num_of_code_word_scheduled_by_dci; - uint8_t bundle_size; // prb_bundling static - uint8_t bundle_size_set1; // prb_bundling dynamic - uint8_t bundle_size_set2; // prb_bundling dynamic - fapi_nr_zp_csi_rs_resource_t periodically_zp_csi_rs_resource_set[FAPI_NR_MAX_NUM_ZP_CSI_RS_RESOURCE_PER_SET]; -} fapi_nr_pdsch_config_dedicated_t; - -typedef struct { - uint16_t starting_prb; - uint8_t intra_slot_frequency_hopping; - uint16_t second_hop_prb; - uint8_t format; // pucch format 0..4 - uint8_t initial_cyclic_shift; - uint8_t number_of_symbols; - uint8_t starting_symbol_index; - uint8_t time_domain_occ; - uint8_t number_of_prbs; - uint8_t occ_length; - uint8_t occ_index; -} fapi_nr_pucch_resource_t; - -typedef struct { - uint8_t periodicity; - uint8_t number_of_harq_process; - fapi_nr_pucch_resource_t n1_pucch_an; -} fapi_nr_sps_config_t; - -typedef struct { - uint8_t beam_failure_instance_max_count; - uint8_t beam_failure_detection_timer; -} fapi_nr_radio_link_monitoring_config_t; - -typedef struct { - fapi_nr_pdcch_config_dedicated_t pdcch_config_dedicated; - fapi_nr_pdsch_config_dedicated_t pdsch_config_dedicated; - fapi_nr_sps_config_t sps_config; - fapi_nr_radio_link_monitoring_config_t radio_link_monitoring_config; - -} fapi_nr_dl_bwp_dedicated_config_t; - -typedef struct { - fapi_nr_rach_config_common_t rach_config_common; - fapi_nr_pusch_config_common_t pusch_config_common; - fapi_nr_pucch_config_common_t pucch_config_common; - -} fapi_nr_ul_bwp_common_config_t; - -typedef struct { - uint8_t inter_slot_frequency_hopping; - uint8_t additional_dmrs; - uint8_t max_code_rate; - uint8_t number_of_slots; - uint8_t pi2bpsk; - uint8_t simultaneous_harq_ack_csi; -} fapi_nr_pucch_format_config_t; - -typedef struct { - fapi_nr_pucch_format_config_t format1; - fapi_nr_pucch_format_config_t format2; - fapi_nr_pucch_format_config_t format3; - fapi_nr_pucch_format_config_t format4; - fapi_nr_pucch_resource_t multi_csi_pucch_resources[2]; - uint8_t dl_data_to_ul_ack[8]; - // pucch power control - uint8_t deltaF_pucch_f0; - uint8_t deltaF_pucch_f1; - uint8_t deltaF_pucch_f2; - uint8_t deltaF_pucch_f3; - uint8_t deltaF_pucch_f4; - uint8_t two_pucch_pc_adjusment_states; -} fapi_nr_pucch_config_dedicated_t; - -typedef struct { - uint8_t dmrs_type; - uint8_t dmrs_addition_position; - uint8_t ptrs_uplink_config; // to indicate if PTRS Uplink is configured of not - uint8_t ptrs_type; //cp-OFDM, dft-S-OFDM - uint16_t ptrs_frequency_density[2]; - uint8_t ptrs_time_density[3]; - uint8_t ptrs_max_number_of_ports; - uint8_t ptrs_resource_element_offset; - uint8_t ptrs_power; - uint16_t ptrs_sample_density[5]; - uint8_t ptrs_time_density_transform_precoding; - - uint8_t max_length; - uint16_t scrambling_id0; - uint16_t scrambling_id1; - uint8_t npusch_identity; - uint8_t disable_sequence_group_hopping; - uint8_t sequence_hopping_enable; -} fapi_nr_dmrs_uplink_config_t; - -typedef struct { - uint8_t tpc_accmulation; - uint8_t msg3_alpha; - uint8_t p0_nominal_with_grant; - uint8_t two_pusch_pc_adjustments_states; - uint8_t delta_mcs; -} fapi_nr_pusch_power_control_t; - -typedef enum {tx_config_codebook = 1, tx_config_nonCodebook = 2} tx_config_t; -typedef enum {transform_precoder_enabled = 0, transform_precoder_disabled = 1} transform_precoder_t; -typedef enum { - codebook_subset_fullyAndPartialAndNonCoherent = 1, - codebook_subset_partialAndNonCoherent = 2, - codebook_subset_nonCoherent = 3} codebook_subset_t; -typedef struct { - uint16_t data_scrambling_identity; - tx_config_t tx_config; - fapi_nr_dmrs_uplink_config_t dmrs_ul_for_pusch_mapping_type_a; - fapi_nr_dmrs_uplink_config_t dmrs_ul_for_pusch_mapping_type_b; - fapi_nr_pusch_power_control_t pusch_power_control; - uint8_t frequency_hopping; - uint16_t frequency_hopping_offset_lists[4]; - uint8_t resource_allocation; - fapi_nr_pusch_time_domain_resource_allocation_t allocation_list[FAPI_NR_MAX_NUM_UL_ALLOCATIONS]; - uint8_t pusch_aggregation_factor; - uint8_t mcs_table; - uint8_t mcs_table_transform_precoder; - transform_precoder_t transform_precoder; - codebook_subset_t codebook_subset; - uint8_t max_rank; - uint8_t rbg_size; - - //uci-OnPUSCH - uint8_t uci_on_pusch_type; //dynamic, semi-static - uint8_t beta_offset_ack_index1[4]; - uint8_t beta_offset_ack_index2[4]; - uint8_t beta_offset_ack_index3[4]; - uint8_t beta_offset_csi_part1_index1[4]; - uint8_t beta_offset_csi_part1_index2[4]; - uint8_t beta_offset_csi_part2_index1[4]; - uint8_t beta_offset_csi_part2_index2[4]; - - uint8_t tp_pi2BPSK; -} fapi_nr_pusch_config_dedicated_t; - -typedef struct { - uint8_t frequency_hopping; - fapi_nr_dmrs_uplink_config_t cg_dmrs_configuration; - uint8_t mcs_table; - uint8_t mcs_table_transform_precoder; - - //uci-OnPUSCH - uint8_t uci_on_pusch_type; //dynamic, semi-static - uint8_t beta_offset_ack_index1[4]; - uint8_t beta_offset_ack_index2[4]; - uint8_t beta_offset_ack_index3[4]; - uint8_t beta_offset_csi_part1_index1[4]; - uint8_t beta_offset_csi_part1_index2[4]; - uint8_t beta_offset_csi_part2_index1[4]; - uint8_t beta_offset_csi_part2_index2[4]; - - uint8_t resource_allocation; - // rgb-Size structure missing in spec. - uint8_t power_control_loop_to_use; - // p0-PUSCH-Alpha - uint8_t p0; - uint8_t alpha; - - uint8_t transform_precoder; - uint8_t number_of_harq_process; - uint8_t rep_k; - uint8_t rep_k_rv; - uint8_t periodicity; - uint8_t configured_grant_timer; - // rrc-ConfiguredUplinkGrant - uint16_t time_domain_offset; - uint8_t time_domain_allocation; - uint32_t frequency_domain_allocation; - uint8_t antenna_ports; - uint8_t dmrs_seq_initialization; - uint8_t precoding_and_number_of_layers; - uint8_t srs_resource_indicator; - uint8_t mcs_and_tbs; - uint8_t frequency_hopping_offset; - uint8_t path_loss_reference_index; - -} fapi_nr_configured_grant_config_t; - -typedef struct { - uint8_t qcl_type1_serving_cell_index; - uint8_t qcl_type1_bwp_id; - uint8_t qcl_type1_rs_type; // csi-rs or ssb - uint8_t qcl_type1_nzp_csi_rs_resource_id; - uint8_t qcl_type1_ssb_index; - uint8_t qcl_type1_type; - - uint8_t qcl_type2_serving_cell_index; - uint8_t qcl_type2_bwp_id; - uint8_t qcl_type2_rs_type; // csi-rs or ssb - uint8_t qcl_type2_nzp_csi_rs_resource_id; - uint8_t qcl_type2_ssb_index; - uint8_t qcl_type2_type; - -} fapi_nr_tci_state_t; - -typedef struct { - uint8_t root_sequence_index; - // rach genertic - uint8_t prach_configuration_index; - uint8_t msg1_fdm; - uint8_t msg1_frequency_start; - uint8_t zero_correlation_zone_config; - uint8_t preamble_received_target_power; - uint8_t preamble_transmission_max; - uint8_t power_ramping_step; - uint8_t ra_window_size; - - uint8_t rsrp_threshold_ssb; - // PRACH-ResourceDedicatedBFR - uint8_t bfr_ssb_index[FAPI_NR_MAX_NUM_CANDIDATE_BEAMS]; - uint8_t bfr_ssb_ra_preamble_index[FAPI_NR_MAX_NUM_CANDIDATE_BEAMS]; - // NZP-CSI-RS-Resource - uint8_t bfr_csi_rs_nzp_resource_mapping[FAPI_NR_MAX_NUM_CANDIDATE_BEAMS]; - uint8_t bfr_csi_rs_power_control_offset[FAPI_NR_MAX_NUM_CANDIDATE_BEAMS]; - uint8_t bfr_csi_rs_power_control_offset_ss[FAPI_NR_MAX_NUM_CANDIDATE_BEAMS]; - uint16_t bfr_csi_rs_scrambling_id[FAPI_NR_MAX_NUM_CANDIDATE_BEAMS]; - uint8_t bfr_csi_rs_resource_periodicity[FAPI_NR_MAX_NUM_CANDIDATE_BEAMS]; - uint16_t bfr_csi_rs_resource_offset[FAPI_NR_MAX_NUM_CANDIDATE_BEAMS]; - fapi_nr_tci_state_t qcl_infomation_periodic_csi_rs[FAPI_NR_MAX_NUM_CANDIDATE_BEAMS]; - - uint8_t bfr_csirs_ra_occasions[FAPI_NR_MAX_NUM_CANDIDATE_BEAMS]; - uint8_t bfr_csirs_ra_preamble_index[FAPI_NR_MAX_NUM_CANDIDATE_BEAMS][FAPI_NR_MAX_RA_OCCASION_PER_CSIRS]; - - uint8_t ssb_per_rach_occasion; - uint8_t ra_ssb_occasion_mask_index; - fapi_nr_search_space_t recovery_search_space; - // RA-Prioritization - uint8_t power_ramping_step_high_priority; - uint8_t scaling_factor_bi; - uint8_t beam_failure_recovery_timer; -} fapi_nr_beam_failure_recovery_config_t; - -typedef struct { - fapi_nr_pucch_config_dedicated_t pucch_config_dedicated; - fapi_nr_pusch_config_dedicated_t pusch_config_dedicated; - fapi_nr_configured_grant_config_t configured_grant_config; - // SRS-Config - uint8_t srs_tpc_accumulation; - fapi_nr_beam_failure_recovery_config_t beam_failure_recovery_config; - -} fapi_nr_ul_bwp_dedicated_config_t; - #define FAPI_NR_CONFIG_REQUEST_MASK_PBCH 0x01 #define FAPI_NR_CONFIG_REQUEST_MASK_DL_BWP_COMMON 0x02 #define FAPI_NR_CONFIG_REQUEST_MASK_UL_BWP_COMMON 0x04 diff --git a/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c b/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c index 5e1528c922..fac5ad46ac 100644 --- a/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c +++ b/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c @@ -129,8 +129,9 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB, //------------------generate DMRS------------------// - if (pusch_pdu->transform_precoding == transform_precoder_disabled) { - nr_pusch_dmrs_rx(gNB, Ns, gNB->nr_gold_pusch_dmrs[pusch_pdu->scid][Ns][symbol], &pilot[0], 1000, 0, nb_rb_pusch, (pusch_pdu->bwp_start + pusch_pdu->rb_start)*NR_NB_SC_PER_RB, pusch_pdu->dmrs_config_type); + if (pusch_pdu->transform_precoding == 1) { + nr_pusch_dmrs_rx(gNB, Ns, gNB->nr_gold_pusch_dmrs[pusch_pdu->scid][Ns][symbol], &pilot[0], 1000, 0, nb_rb_pusch, + (pusch_pdu->bwp_start + pusch_pdu->rb_start)*NR_NB_SC_PER_RB, pusch_pdu->dmrs_config_type); } else { // if transform precoding or SC-FDMA is enabled in Uplink diff --git a/openair1/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c b/openair1/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c index 1c13f5a20b..e358985c12 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c +++ b/openair1/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c @@ -1311,7 +1311,7 @@ int nr_rx_pusch(PHY_VARS_gNB *gNB, stop_meas(&gNB->ulsch_mrc_stats); - if (rel15_ul->transform_precoding == transform_precoder_enabled) { + if (rel15_ul->transform_precoding == 0) { #ifdef __AVX2__ // For odd number of resource blocks need byte alignment to multiple of 8 diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c b/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c index 18fe11d40a..e92dc7476f 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c @@ -254,14 +254,15 @@ void nr_ue_ulsch_procedures(PHY_VARS_NR_UE *UE, uint8_t u = 0, v = 0; int16_t *dmrs_seq = NULL; - if (pusch_pdu->transform_precoding == transform_precoder_enabled) { + // enbaled + if (pusch_pdu->transform_precoding == 0) { uint32_t nb_re_pusch=nb_rb * NR_NB_SC_PER_RB; uint32_t y_offset = 0; uint16_t num_dmrs_res_per_symbol = nb_rb*(NR_NB_SC_PER_RB/2); // Calculate index to dmrs seq array based on number of DMRS Subcarriers on this symbol - index = get_index_for_dmrs_lowpapr_seq(num_dmrs_res_per_symbol); + index = get_index_for_dmrs_lowpapr_seq(num_dmrs_res_per_symbol); u = pusch_pdu->dfts_ofdm.low_papr_group_number; v = pusch_pdu->dfts_ofdm.low_papr_sequence_number; dmrs_seq = dmrs_lowpaprtype1_ul_ref_sig[u][v][index]; @@ -299,7 +300,7 @@ void nr_ue_ulsch_procedures(PHY_VARS_NR_UE *UE, } printf("NR_ULSCH_UE: numSym: %d, num_dmrs_sym: %d", number_of_symbols,number_dmrs_symbols); - for (int ll = 0; ll < (number_of_symbols-number_dmrs_symbols); ll++) { + for (int ll = 0; ll < (number_of_symbols-number_dmrs_symbols); ll++) { nr_idft(&debug_symbols[offset], nb_re_pusch); @@ -355,8 +356,8 @@ void nr_ue_ulsch_procedures(PHY_VARS_NR_UE *UE, if ((ul_dmrs_symb_pos >> l) & 0x01) { is_dmrs_sym = 1; - - if (pusch_pdu->transform_precoding == transform_precoder_disabled){ + // disabled + if (pusch_pdu->transform_precoding == 1){ if (dmrs_type == pusch_dmrs_type1) dmrs_idx = (pusch_pdu->bwp_start + start_rb)*6; @@ -373,9 +374,9 @@ void nr_ue_ulsch_procedures(PHY_VARS_NR_UE *UE, } - } else if (pusch_pdu->pdu_bit_map & PUSCH_PDU_BITMAP_PUSCH_PTRS) { + } else if (pusch_pdu->pdu_bit_map & PUSCH_PDU_BITMAP_PUSCH_PTRS) { - AssertFatal(pusch_pdu->transform_precoding == transform_precoder_disabled, "PTRS NOT SUPPORTED IF TRANSFORM PRECODING IS ENABLED\n"); + AssertFatal(pusch_pdu->transform_precoding == 1, "PTRS NOT SUPPORTED IF TRANSFORM PRECODING IS ENABLED\n"); if(is_ptrs_symbol(l, ulsch_ue->ptrs_symbols)) { is_ptrs_sym = 1; @@ -406,8 +407,8 @@ void nr_ue_ulsch_procedures(PHY_VARS_NR_UE *UE, } if (is_dmrs == 1) { - - if (pusch_pdu->transform_precoding == transform_precoder_enabled) { + // if enabled + if (pusch_pdu->transform_precoding == 0) { ((int16_t*)txdataF[ap])[(sample_offsetF)<<1] = (Wt[l_prime[0]]*Wf[k_prime]*AMP*dmrs_seq[2*dmrs_idx]) >> 15; ((int16_t*)txdataF[ap])[((sample_offsetF)<<1) + 1] = (Wt[l_prime[0]]*Wf[k_prime]*AMP*dmrs_seq[(2*dmrs_idx) + 1]) >> 15; diff --git a/openair1/SIMULATION/NR_PHY/ulsim.c b/openair1/SIMULATION/NR_PHY/ulsim.c index a99a47dc54..8aa5e3ab20 100644 --- a/openair1/SIMULATION/NR_PHY/ulsim.c +++ b/openair1/SIMULATION/NR_PHY/ulsim.c @@ -304,7 +304,7 @@ int main(int argc, char **argv) uint16_t ptrsSymbPerSlot = 0; uint16_t ptrsRePerSymb = 0; - uint8_t transform_precoding = transform_precoder_disabled; // 0 - ENABLE, 1 - DISABLE + uint8_t transform_precoding = 1; // 0 - ENABLE, 1 - DISABLE uint8_t num_dmrs_cdm_grps_no_data = 1; uint8_t mcs_table = 0; @@ -561,7 +561,7 @@ int main(int argc, char **argv) case 'Z': - transform_precoding = transform_precoder_enabled; + transform_precoding = 0; num_dmrs_cdm_grps_no_data = 2; mcs_table = 3; @@ -835,7 +835,7 @@ int main(int argc, char **argv) uint16_t number_dmrs_symbols = get_dmrs_symbols_in_slot(l_prime_mask, nb_symb_sch); uint8_t nb_re_dmrs = (dmrs_config_type == pusch_dmrs_type1) ? 6 : 4; - if (transform_precoding == transform_precoder_enabled) { + if (transform_precoding == 0) { AssertFatal(enable_ptrs == 0, "PTRS NOT SUPPORTED IF TRANSFORM PRECODING IS ENABLED\n"); @@ -1040,7 +1040,7 @@ int main(int argc, char **argv) pusch_pdu->pusch_ptrs.ptrs_ports_list = (nfapi_nr_ptrs_ports_t *) malloc(2*sizeof(nfapi_nr_ptrs_ports_t)); pusch_pdu->pusch_ptrs.ptrs_ports_list[0].ptrs_re_offset = 0; - if (transform_precoding == transform_precoder_enabled) { + if (transform_precoding == 0) { pusch_pdu->dfts_ofdm.low_papr_group_number = *scc->physCellId % 30; // U as defined in 38.211 section 6.4.1.1.1.2 pusch_pdu->dfts_ofdm.low_papr_sequence_number = 0; // V as defined in 38.211 section 6.4.1.1.1.2 @@ -1100,7 +1100,7 @@ int main(int argc, char **argv) ul_config.ul_config_list[0].pusch_config_pdu.transform_precoding = transform_precoding; - if (transform_precoding == transform_precoder_enabled) { + if (transform_precoding == 0) { ul_config.ul_config_list[0].pusch_config_pdu.dfts_ofdm.low_papr_group_number = *scc->physCellId % 30;// U as defined in 38.211 section 6.4.1.1.1.2 ul_config.ul_config_list[0].pusch_config_pdu.dfts_ofdm.low_papr_sequence_number = 0;// V as defined in 38.211 section 6.4.1.1.1.2 @@ -1205,7 +1205,7 @@ int main(int argc, char **argv) } - if (n_trials == 1 && round==0) { + if (n_trials == 1 && round==0) { #ifdef __AVX2__ int off = ((nb_rb&1) == 1)? 4:0; #else diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c index 1c89f866d2..b8a8ead294 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c @@ -671,7 +671,7 @@ int nr_config_pusch_pdu(NR_UE_MAC_INST_t *mac, /* TRANSFORM PRECODING ------------------------------------------------------------------------------------------*/ - if (pusch_config_pdu->transform_precoding == transform_precoder_enabled) { + if (pusch_config_pdu->transform_precoding == NR_PUSCH_Config__transformPrecoder_enabled) { pusch_config_pdu->num_dmrs_cdm_grps_no_data = 2; @@ -722,7 +722,7 @@ int nr_config_pusch_pdu(NR_UE_MAC_INST_t *mac, pusch_config_pdu->mcs_index = dci->mcs; /* MCS TABLE */ - if (pusch_config_pdu->transform_precoding == transform_precoder_disabled) { + if (pusch_config_pdu->transform_precoding == NR_PUSCH_Config__transformPrecoder_disabled) { pusch_config_pdu->mcs_table = get_pusch_mcs_table(pusch_Config ? pusch_Config->mcs_Table : NULL, 0, *dci_format, rnti_type, target_ss, false); } else { pusch_config_pdu->mcs_table = get_pusch_mcs_table(pusch_Config ? pusch_Config->mcs_TableTransformPrecoder : NULL, 1, *dci_format, rnti_type, target_ss, false); @@ -752,9 +752,9 @@ int nr_config_pusch_pdu(NR_UE_MAC_INST_t *mac, /* DMRS */ l_prime_mask = get_l_prime(pusch_config_pdu->nr_of_symbols, typeB, (*dci_format == NR_UL_DCI_FORMAT_0_1) ? pusch_dmrs_pos0 : pusch_dmrs_pos2, pusch_len1); - if ((mac->ULbwp[0] && pusch_config_pdu->transform_precoding == transform_precoder_disabled)) + if ((mac->ULbwp[0] && pusch_config_pdu->transform_precoding == NR_PUSCH_Config__transformPrecoder_disabled)) pusch_config_pdu->num_dmrs_cdm_grps_no_data = 1; - else if (*dci_format == NR_UL_DCI_FORMAT_0_0 || (mac->ULbwp[0] && pusch_config_pdu->transform_precoding == transform_precoder_enabled)) + else if (*dci_format == NR_UL_DCI_FORMAT_0_0 || (mac->ULbwp[0] && pusch_config_pdu->transform_precoding == NR_PUSCH_Config__transformPrecoder_enabled)) pusch_config_pdu->num_dmrs_cdm_grps_no_data = 2; // Num PRB Overhead from PUSCH-ServingCellConfig @@ -775,7 +775,7 @@ int nr_config_pusch_pdu(NR_UE_MAC_INST_t *mac, mac->ULbwp[0]->bwp_Dedicated->pusch_Config->choice.setup && mac->ULbwp[0]->bwp_Dedicated->pusch_Config->choice.setup->dmrs_UplinkForPUSCH_MappingTypeB && mac->ULbwp[0]->bwp_Dedicated->pusch_Config->choice.setup->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup->phaseTrackingRS) { - if (pusch_config_pdu->transform_precoding == transform_precoder_disabled) { + if (pusch_config_pdu->transform_precoding == NR_PUSCH_Config__transformPrecoder_disabled) { nfapi_nr_ue_ptrs_ports_t ptrs_ports_list; pusch_config_pdu->pusch_ptrs.ptrs_ports_list = &ptrs_ports_list; valid_ptrs_setup = set_ul_ptrs_values(mac->ULbwp[0]->bwp_Dedicated->pusch_Config->choice.setup->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup->phaseTrackingRS->choice.setup, From 6210519d519caffd5915e38bd42c51e07b2d90a9 Mon Sep 17 00:00:00 2001 From: Mahesh Date: Tue, 15 Jun 2021 18:35:46 +0530 Subject: [PATCH 26/91] Bugfix - UL info filling --- nfapi/oai_integration/nfapi_vnf.c | 99 ++- nfapi/open-nFAPI/nfapi/src/nfapi_p7.c | 198 +++--- .../vnf/public_inc/nfapi_vnf_interface.h | 10 +- nfapi/open-nFAPI/vnf/src/vnf_p7.c | 655 +++++++++--------- nfapi/open-nFAPI/vnf/src/vnf_p7_interface.c | 2 +- 5 files changed, 560 insertions(+), 404 deletions(-) diff --git a/nfapi/oai_integration/nfapi_vnf.c b/nfapi/oai_integration/nfapi_vnf.c index 12dda62eaf..8f30a091ab 100644 --- a/nfapi/oai_integration/nfapi_vnf.c +++ b/nfapi/oai_integration/nfapi_vnf.c @@ -596,7 +596,7 @@ extern pthread_mutex_t nfapi_sync_mutex; extern int nfapi_sync_var; int phy_sync_indication(struct nfapi_vnf_p7_config *config, uint8_t sync) { - printf("[VNF] SYNC %s\n", sync==1 ? "ACHIEVED" : "LOST"); + //printf("[VNF] SYNC %s\n", sync==1 ? "ACHIEVED" : "LOST"); if (sync==1 && nfapi_sync_var!=0) { @@ -1014,6 +1014,98 @@ int phy_cqi_indication(struct nfapi_vnf_p7_config *config, nfapi_cqi_indication_ return 1; } +//NR phy indication + +int phy_nr_crc_indication(nfapi_nr_crc_indication_t *ind) { + struct PHY_VARS_gNB_s *gNB = RC.gNB[0]; + pthread_mutex_lock(&gNB->UL_INFO_mutex); + ind->number_crcs = 1; + if (ind->number_crcs > 0) + gNB->UL_INFO.crc_ind.crc_list = malloc(sizeof(nfapi_nr_crc_t)*ind->number_crcs); + + for (int i=0; inumber_crcs; i++) + memcpy(&gNB->UL_INFO.crc_ind.crc_list[i], &ind->crc_list[i], sizeof(ind->crc_list[0])); + + pthread_mutex_unlock(&gNB->UL_INFO_mutex); + + return 1; +} + +int phy_nr_rx_data_indication(nfapi_nr_rx_data_indication_t *ind) { + struct PHY_VARS_gNB_s *gNB = RC.gNB[0]; + pthread_mutex_lock(&gNB->UL_INFO_mutex); + + if (ind->number_of_pdus > 0) + gNB->UL_INFO.rx_ind.pdu_list = malloc(sizeof(nfapi_nr_rx_data_pdu_t)*ind->number_of_pdus); + + for (int i=0; inumber_of_pdus; i++) + memcpy(&gNB->UL_INFO.rx_ind.pdu_list[i], &ind->pdu_list[i], sizeof(ind->pdu_list[0])); + + + pthread_mutex_unlock(&gNB->UL_INFO_mutex); + + return 1; +} + +int phy_nr_uci_indication(nfapi_nr_uci_indication_t *ind) { + struct PHY_VARS_gNB_s *gNB = RC.gNB[0]; + pthread_mutex_lock(&gNB->UL_INFO_mutex); + + if (ind->num_ucis > 0) + gNB->UL_INFO.uci_ind.uci_list = malloc(sizeof(nfapi_nr_uci_t)*ind->num_ucis); + + for (int i=0; inum_ucis; i++) + memcpy(&gNB->UL_INFO.uci_ind.uci_list[i], &ind->uci_list[i], sizeof(ind->uci_list[0])); + + pthread_mutex_unlock(&gNB->UL_INFO_mutex); + + return 1; +} + +int phy_nr_srs_indication(nfapi_nr_srs_indication_t *ind) { + struct PHY_VARS_gNB_s *gNB = RC.gNB[0]; + pthread_mutex_lock(&gNB->UL_INFO_mutex); + + if (ind->number_of_pdus > 0) + gNB->UL_INFO.srs_ind.pdu_list = malloc(sizeof(nfapi_nr_srs_indication_pdu_t)*ind->number_of_pdus); + + for (int i=0; inumber_of_pdus; i++) { + memcpy(&gNB->UL_INFO.srs_ind.pdu_list[i], &ind->pdu_list[i], sizeof(ind->pdu_list[0])); + + LOG_D(MAC, "%s() NFAPI SFN/Slot:%d.%d SRS_IND:number_of_pdus:%d UL_INFO:pdus:%d\n", + __FUNCTION__, + ind->sfn,ind->slot, ind->number_of_pdus, gNB->UL_INFO.srs_ind.number_of_pdus + ); + } + + pthread_mutex_unlock(&gNB->UL_INFO_mutex); + + return 1; +} + +int phy_nr_rach_indication(nfapi_nr_rach_indication_t *ind) { + struct PHY_VARS_gNB_s *gNB = RC.gNB[0]; + pthread_mutex_lock(&gNB->UL_INFO_mutex); + + if (ind->number_of_pdus > 0) + gNB->UL_INFO.rach_ind.pdu_list = malloc(sizeof(nfapi_nr_prach_indication_pdu_t)*ind->number_of_pdus); + + for (int i=0; inumber_of_pdus; i++) { + memcpy(&gNB->UL_INFO.rach_ind.pdu_list[i], &ind->pdu_list[i], sizeof(ind->pdu_list[0])); + + LOG_D(MAC, "%s() NFAPI SFN/Slot:%d.%d RACH_IND:number_of_pdus:%d UL_INFO:pdus:%d\n", + __FUNCTION__, + ind->sfn,ind->slot, ind->number_of_pdus, gNB->UL_INFO.rach_ind.number_of_pdus + ); + } + + pthread_mutex_unlock(&gNB->UL_INFO_mutex); + + return 1; +} + +//end NR phy indication + int phy_lbt_dl_indication(struct nfapi_vnf_p7_config *config, nfapi_lbt_dl_indication_t *ind) { // vnf_p7_info* p7_vnf = (vnf_p7_info*)(config->user_data); //mac_lbt_dl_ind(p7_vnf->mac, ind); @@ -1179,6 +1271,11 @@ void *vnf_nr_p7_thread_start(void *ptr) { 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; + 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_uci_indication = &phy_nr_uci_indication; + p7_vnf->config->nr_rach_indication = &phy_nr_rach_indication; + p7_vnf->config->nr_srs_indication = &phy_nr_srs_indication; p7_vnf->config->malloc = &vnf_allocate; p7_vnf->config->free = &vnf_deallocate; p7_vnf->config->trace = &vnf_trace; diff --git a/nfapi/open-nFAPI/nfapi/src/nfapi_p7.c b/nfapi/open-nFAPI/nfapi/src/nfapi_p7.c index 4097217f99..3a90ca4363 100755 --- a/nfapi/open-nFAPI/nfapi/src/nfapi_p7.c +++ b/nfapi/open-nFAPI/nfapi/src/nfapi_p7.c @@ -361,7 +361,7 @@ static uint8_t pack_dl_tti_pdsch_pdu_rel15_value(void* tlv, uint8_t **ppWritePac static uint8_t pack_dl_tti_ssb_pdu_rel15_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { - printf("Packing ssb. \n"); + //printf("Packing ssb. \n"); nfapi_nr_dl_tti_ssb_pdu_rel15_t* value = (nfapi_nr_dl_tti_ssb_pdu_rel15_t*)tlv; return( @@ -3625,7 +3625,7 @@ static uint8_t pack_nr_uci_indication_body(void* tlv, uint8_t **ppWritePackedMsg case NFAPI_NR_UCI_FORMAT_0_1_PDU_TYPE: { nfapi_nr_uci_pucch_pdu_format_0_1_t *uci_pdu = &value->pucch_pdu_format_0_1; - pack_nr_uci_pucch_0_1(uci_pdu, ppWritePackedMsg, end); + pack_nr_uci_pucch_0_1(&value->pucch_pdu_format_0_1, ppWritePackedMsg, end); break; } case NFAPI_NR_UCI_FORMAT_2_3_4_PDU_TYPE: { @@ -3650,7 +3650,7 @@ static uint8_t pack_nr_uci_indication(void *msg, uint8_t **ppWritePackedMsg, uin for(int i=0; inum_ucis;i++) { - if(!pack_nr_uci_indication_body(&(pNfapiMsg->uci_list[i]),ppWritePackedMsg,end)) + if(!pack_nr_uci_indication_body(pNfapiMsg->uci_list,ppWritePackedMsg,end)) return 0; } @@ -3700,7 +3700,7 @@ int nfapi_nr_p7_message_pack(void *pMessageBuf, void *pPackedBuf, uint32_t packe { case NFAPI_NR_PHY_MSG_TYPE_DL_TTI_REQUEST: result = pack_dl_tti_request(pMessageHeader, &pWritePackedMessage, end, config); - printf("result of pack dl_tti_req is %d. \n",result); + //printf("result of pack dl_tti_req is %d. \n",result); break; case NFAPI_NR_PHY_MSG_TYPE_UL_TTI_REQUEST: @@ -6370,15 +6370,8 @@ static uint8_t unpack_nr_rx_data_indication_body(void* tlv, uint8_t **ppReadPack } -static uint8_t unpack_nr_rx_data_indication(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config) +static uint8_t unpack_nr_rx_data_indication(uint8_t **ppReadPackedMsg, uint8_t *end, nfapi_nr_rx_data_indication_t *msg, nfapi_p7_codec_config_t* config) { - // uint8_t *ptr = *ppReadPackedMsg; - // printf("\n Read P7 message rx data indication unpack: "); - // while(ptr < end){ - // printf(" %d ", *ptr); - // ptr++; - // } - // printf("\n"); nfapi_nr_rx_data_indication_t *pNfapiMsg = (nfapi_nr_rx_data_indication_t*)msg; printf("\n"); @@ -6390,7 +6383,7 @@ static uint8_t unpack_nr_rx_data_indication(uint8_t **ppReadPackedMsg, uint8_t * for(int i=0; inumber_of_pdus;i++) { - if(!unpack_nr_rx_data_indication_body(&pNfapiMsg->pdu_list, ppReadPackedMsg, end)) + if(!unpack_nr_rx_data_indication_body(pNfapiMsg->pdu_list, ppReadPackedMsg, end)) return 0; } @@ -6399,10 +6392,8 @@ return 1; //NR CRC INDICATION -static uint8_t unpack_nr_crc_indication_body(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +static uint8_t unpack_nr_crc_indication_body(nfapi_nr_crc_t* value, uint8_t **ppReadPackedMsg, uint8_t *end) { - nfapi_nr_crc_t* value = (nfapi_nr_crc_t*)tlv; - if(!(pull32(ppReadPackedMsg, &value->handle, end) && pull16(ppReadPackedMsg, &value->rnti, end) && pull8(ppReadPackedMsg, &value->harq_id, end) && @@ -6415,32 +6406,31 @@ static uint8_t unpack_nr_crc_indication_body(void* tlv, uint8_t **ppReadPackedMs )) return 0; + //memcpy((nfapi_nr_crc_t *)tlv,value,sizeof(nfapi_nr_crc_t)); + return 1; } -static uint8_t unpack_nr_crc_indication(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config) +static uint8_t unpack_nr_crc_indication(uint8_t **ppReadPackedMsg, uint8_t *end, nfapi_nr_crc_indication_t *msg, nfapi_p7_codec_config_t* config) { - uint8_t *ptr = *ppReadPackedMsg; - // printf("\n Read P7 message indication unpack: "); - // while(ptr < end){ - // printf(" %d ", *ptr); - // ptr++; - // } - // printf("\n"); - nfapi_nr_crc_indication_t *pNfapiMsg = (nfapi_nr_crc_indication_t*)msg; - - if (!(pull16(ppReadPackedMsg, &pNfapiMsg->sfn , end) && - pull16(ppReadPackedMsg, &pNfapiMsg->slot , end) && + nfapi_nr_crc_indication_t *pNfapiMsg = (nfapi_nr_crc_indication_t *) msg; + // pNfapiMsg = (nfapi_nr_crc_indication_t *) malloc(sizeof(nfapi_nr_crc_indication_t)); + // pNfapiMsg->crc_list = (nfapi_nr_crc_t *) malloc(sizeof(nfapi_nr_crc_t)); + + if (!(pull16(ppReadPackedMsg, &pNfapiMsg->sfn, end) && + pull16(ppReadPackedMsg, &pNfapiMsg->slot, end) && pull16(ppReadPackedMsg, &pNfapiMsg->number_crcs, end) )) - return 0; + return 0; for(int i=0; inumber_crcs;i++) { - if(!unpack_nr_crc_indication_body(&pNfapiMsg->crc_list,ppReadPackedMsg,end)) + if(!unpack_nr_crc_indication_body(pNfapiMsg->crc_list,ppReadPackedMsg,end)) + //if(!unpack_nr_crc_indication_body(value,ppReadPackedMsg,end)) return 0; } + printf("Done \n"); return 1; } @@ -6489,7 +6479,7 @@ return 1; //NR RACH -static uint8_t unpack_nr_rach_indication_body(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +static uint8_t unpack_nr_rach_indication_body(nfapi_nr_prach_indication_pdu_t* tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { nfapi_nr_prach_indication_pdu_t* value = (nfapi_nr_prach_indication_pdu_t*)tlv; @@ -6502,6 +6492,7 @@ static uint8_t unpack_nr_rach_indication_body(void* tlv, uint8_t **ppReadPackedM pull8(ppReadPackedMsg, &value->num_preamble, end) )) return 0; + value->preamble_list = (nfapi_nr_prach_indication_preamble_t*) malloc(sizeof(nfapi_nr_prach_indication_preamble_t) * value->num_preamble); for(int i = 0; i < value->num_preamble; i++) { if(!(pull8(ppReadPackedMsg, &value->preamble_list->preamble_index, end) && @@ -6513,7 +6504,7 @@ static uint8_t unpack_nr_rach_indication_body(void* tlv, uint8_t **ppReadPackedM return 1; } -static uint8_t unpack_nr_rach_indication(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config) { +static uint8_t unpack_nr_rach_indication(uint8_t **ppReadPackedMsg, uint8_t *end, nfapi_nr_rach_indication_t* msg, nfapi_p7_codec_config_t* config) { nfapi_nr_rach_indication_t *pNfapiMsg = (nfapi_nr_rach_indication_t*)msg; if (!(pull16(ppReadPackedMsg, &pNfapiMsg->sfn , end) && @@ -6521,10 +6512,10 @@ static uint8_t unpack_nr_rach_indication(uint8_t **ppReadPackedMsg, uint8_t *end pull8(ppReadPackedMsg, &pNfapiMsg->number_of_pdus, end) )) return 0; - + pNfapiMsg->pdu_list = (nfapi_nr_prach_indication_pdu_t*) malloc(sizeof(nfapi_nr_prach_indication_pdu_t) * pNfapiMsg->number_of_pdus); for(int i=0; i< pNfapiMsg->number_of_pdus;i++) { - if(!unpack_nr_rach_indication_body(&pNfapiMsg->pdu_list,ppReadPackedMsg,end)) + if(!unpack_nr_rach_indication_body(pNfapiMsg->pdu_list,ppReadPackedMsg,end)) return 0; } @@ -6533,16 +6524,16 @@ return 1; //NR UCI -static uint8_t unpack_nr_uci_pucch_0_1(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { +static uint8_t unpack_nr_uci_pucch_0_1(nfapi_nr_uci_pucch_pdu_format_0_1_t* tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { nfapi_nr_uci_pucch_pdu_format_0_1_t* value = (nfapi_nr_uci_pucch_pdu_format_0_1_t*)tlv; uint8_t *ptr = *ppReadPackedMsg; - printf("\n Read P7 message uci_0_1 indication unpack: "); - while(ptr < end){ - printf(" %d ", *ptr); - ptr++; - } - printf("\n"); + // printf("\n Read P7 message uci_0_1 indication unpack: "); + // while(ptr < end){ + // printf(" %d ", *ptr); + // ptr++; + // } + // printf("\n"); if(!(pull8(ppReadPackedMsg, &value->pduBitmap, end) && pull32(ppReadPackedMsg, &value->handle, end) && @@ -6554,34 +6545,33 @@ static uint8_t unpack_nr_uci_pucch_0_1(void* tlv, uint8_t **ppReadPackedMsg, uin )) return 0; if (value->pduBitmap & 0x01) { //SR + value->sr = (nfapi_nr_sr_pdu_0_1_t*) malloc(sizeof(nfapi_nr_sr_pdu_0_1_t)); if(!(pull8(ppReadPackedMsg, &value->sr->sr_indication, end) && pull8(ppReadPackedMsg, &value->sr->sr_confidence_level, end) )) return 0; } - // if (((value->pduBitmap >> 1) & 0x01)) { //HARQ - // uint8_t* temp; //&value->harq->num_harq &value->harq->harq_confidence_level &value->harq->harq_list[0].harq_value - // temp = (uint8_t*) malloc(sizeof(uint8_t)); - // //printf("value->harq->num_harq = %d \n", value->harq->num_harq); - // // if(!(pull8(ppReadPackedMsg, temp, end) && - // // pull8(ppReadPackedMsg, temp, end) - // // )) - // // return 0; - - // // for(int i=0; i<1;i++) - // // { - // // if(!(pull8(ppReadPackedMsg, temp, end) - // // )) - // // return 0; - // // } - // } + if (((value->pduBitmap >> 1) & 0x01)) { //HARQ + value->harq = (nfapi_nr_harq_pdu_0_1_t*) malloc(sizeof(nfapi_nr_harq_pdu_0_1_t)); + if(!(pull8(ppReadPackedMsg, &value->harq->num_harq, end) && + pull8(ppReadPackedMsg, &value->harq->harq_confidence_level, end) + )) + return 0; + value->harq->harq_list = (nfapi_nr_harq_t*) malloc(sizeof(nfapi_nr_harq_t*) * value->harq->num_harq); + for(int i=0; iharq->num_harq;i++) + { + if(!(pull8(ppReadPackedMsg, &value->harq->harq_list->harq_value, end) + )) + return 0; + } + } return 1; } -static uint8_t unpack_nr_uci_pucch_2_3_4(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { +static uint8_t unpack_nr_uci_pucch_2_3_4(nfapi_nr_uci_pucch_pdu_format_2_3_4_t* tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { nfapi_nr_uci_pucch_pdu_format_2_3_4_t* value = (nfapi_nr_uci_pucch_pdu_format_2_3_4_t*) tlv; if(!(pull8(ppReadPackedMsg, &value->pduBitmap, end) && @@ -6594,43 +6584,53 @@ static uint8_t unpack_nr_uci_pucch_2_3_4(void* tlv, uint8_t **ppReadPackedMsg, u )) return 0; if (value->pduBitmap & 0x01) { //SR - if(!(pull16(ppReadPackedMsg, &value->sr.sr_bit_len, end) && - pullarray8(ppReadPackedMsg, value->sr.sr_payload, (int)(value->sr.sr_bit_len / 8) + 1, (int)(value->sr.sr_bit_len / 8) + 1, end) - )) - return 0; + if(!(pull16(ppReadPackedMsg, &value->sr.sr_bit_len, end))) + return 0; + + value->sr.sr_payload = (uint8_t*) malloc(sizeof(uint8_t) * ((value->sr.sr_bit_len/8))); + + if(!(pullarray8(ppReadPackedMsg, &value->sr.sr_payload[0], (int)(value->sr.sr_bit_len / 8), (int)(value->sr.sr_bit_len / 8), end))) + return 0; } if (((value->pduBitmap >> 1) & 0x01)) { //HARQ - if(!(pull8(ppReadPackedMsg, &value->harq.harq_crc, end) && - pull16(ppReadPackedMsg, &value->harq.harq_bit_len, end) && - pullarray8(ppReadPackedMsg, value->harq.harq_payload, (int)(value->harq.harq_bit_len / 8) + 1, (int)(value->harq.harq_bit_len / 8) + 1, end) - )) + if(!(pull8(ppReadPackedMsg, &value->harq.harq_crc, end)) && + (pull16(ppReadPackedMsg, &value->harq.harq_bit_len, end))) + return 0; + + value->harq.harq_payload = (uint8_t*) malloc(sizeof(uint8_t) * ((value->harq.harq_bit_len/8 ))); + + if(!(pullarray8(ppReadPackedMsg, value->harq.harq_payload, (int)(value->harq.harq_bit_len / 8), (int)(value->harq.harq_bit_len / 8), end))) return 0; } if (((value->pduBitmap >> 2) & 0x01)) { //CSI-1 - if(!(pull8(ppReadPackedMsg, &value->csi_part1.csi_part1_crc, end) && - pull16(ppReadPackedMsg, &value->csi_part1.csi_part1_bit_len, end) && - pullarray8(ppReadPackedMsg, value->csi_part1.csi_part1_payload, (int)(value->csi_part1.csi_part1_bit_len / 8) + 1, (int)(value->csi_part1.csi_part1_bit_len / 8) + 1, end) - )) - return 0; + if(!(pull8(ppReadPackedMsg, &value->csi_part1.csi_part1_crc, end)) && + (pull16(ppReadPackedMsg, &value->csi_part1.csi_part1_bit_len, end))) + return 0; + + value->csi_part1.csi_part1_payload = (uint8_t*) malloc(sizeof(uint8_t) * ((value->csi_part1.csi_part1_bit_len/8))); + +// if(!(pullarray8(ppReadPackedMsg, value->csi_part1.csi_part1_payload, (int)(value->csi_part1.csi_part1_bit_len / 8), (int)(value->csi_part1.csi_part1_bit_len / 8), end))) +// return 0; } if (((value->pduBitmap >> 3) & 0x01)) { //CSI-2 - if(!(pull8(ppReadPackedMsg, &value->csi_part2.csi_part2_crc, end) && - pull16(ppReadPackedMsg, &value->csi_part2.csi_part2_bit_len, end) && - pullarray8(ppReadPackedMsg, value->csi_part2.csi_part2_payload, (int)(value->csi_part2.csi_part2_bit_len / 8) + 1, (int)(value->csi_part2.csi_part2_bit_len / 8) + 1, end) - )) + if(!(pull8(ppReadPackedMsg, &value->csi_part2.csi_part2_crc, end)) && + (pull16(ppReadPackedMsg, &value->csi_part2.csi_part2_bit_len, end))) + return 0; + + value->csi_part2.csi_part2_payload = (uint8_t*) malloc(sizeof(uint8_t) * ((value->csi_part2.csi_part2_bit_len/8 ))); + + if(!(pullarray8(ppReadPackedMsg, value->csi_part2.csi_part2_payload, (int)(value->csi_part2.csi_part2_bit_len / 8) , (int)(value->csi_part2.csi_part2_bit_len / 8) , end))) return 0; } return 1; } -static uint8_t unpack_nr_uci_indication_body(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +static uint8_t unpack_nr_uci_indication_body(nfapi_nr_uci_t* value, uint8_t **ppReadPackedMsg, uint8_t *end) { - nfapi_nr_uci_t* value = (nfapi_nr_uci_t*)tlv; - if(!(pull16(ppReadPackedMsg, &value->pdu_type, end) && pull16(ppReadPackedMsg, &value->pdu_size, end) )) @@ -6643,12 +6643,12 @@ static uint8_t unpack_nr_uci_indication_body(void* tlv, uint8_t **ppReadPackedMs case NFAPI_NR_UCI_FORMAT_0_1_PDU_TYPE: { nfapi_nr_uci_pucch_pdu_format_0_1_t* uci_pdu = &value->pucch_pdu_format_0_1; - unpack_nr_uci_pucch_0_1(&uci_pdu, ppReadPackedMsg, end); + unpack_nr_uci_pucch_0_1(uci_pdu, ppReadPackedMsg, end); break; } case NFAPI_NR_UCI_FORMAT_2_3_4_PDU_TYPE: { nfapi_nr_uci_pucch_pdu_format_2_3_4_t *uci_pdu = &value->pucch_pdu_format_2_3_4; - unpack_nr_uci_pucch_2_3_4(&uci_pdu, ppReadPackedMsg, end); + unpack_nr_uci_pucch_2_3_4(uci_pdu, ppReadPackedMsg, end); break; } } @@ -6668,7 +6668,7 @@ static uint8_t unpack_nr_uci_indication(uint8_t **ppReadPackedMsg, uint8_t *end, for(int i=0; inum_ucis;i++) { - if(!unpack_nr_uci_indication_body(&pNfapiMsg->uci_list,ppReadPackedMsg,end)) + if(!unpack_nr_uci_indication_body(pNfapiMsg->uci_list,ppReadPackedMsg,end)) return 0; } @@ -8711,36 +8711,52 @@ int nfapi_nr_p7_message_unpack(void *pMessageBuf, uint32_t messageBufLen, void * break; case NFAPI_NR_PHY_MSG_TYPE_RX_DATA_INDICATION: - if (check_nr_unpack_length(NFAPI_NR_PHY_MSG_TYPE_RX_DATA_INDICATION, unpackedBufLen)) - result = unpack_nr_rx_data_indication(&pReadPackedMessage, end, pMessageHeader, config); + if (check_nr_unpack_length(NFAPI_NR_PHY_MSG_TYPE_RX_DATA_INDICATION, unpackedBufLen)){ + nfapi_nr_rx_data_indication_t* msg = (nfapi_nr_rx_data_indication_t*) pMessageHeader; + msg->pdu_list = (nfapi_nr_rx_data_pdu_t*) malloc(sizeof(nfapi_nr_rx_data_pdu_t)); + msg->pdu_list->pdu = (uint8_t *) malloc(sizeof(uint8_t)); + result = unpack_nr_rx_data_indication(&pReadPackedMessage, end, msg, config); + } else return -1; break; case NFAPI_NR_PHY_MSG_TYPE_CRC_INDICATION: - if (check_nr_unpack_length(NFAPI_NR_PHY_MSG_TYPE_CRC_INDICATION, unpackedBufLen)) - result = unpack_nr_crc_indication(&pReadPackedMessage,end , pMessageHeader, config); + if (check_nr_unpack_length(NFAPI_NR_PHY_MSG_TYPE_CRC_INDICATION, unpackedBufLen)){ + + nfapi_nr_crc_indication_t* msg = (nfapi_nr_crc_indication_t*) pMessageHeader; + msg->crc_list = (nfapi_nr_crc_t*) malloc(sizeof(nfapi_nr_crc_t)); + result = unpack_nr_crc_indication(&pReadPackedMessage,end , msg, config); + } else return -1; break; case NFAPI_NR_PHY_MSG_TYPE_UCI_INDICATION: - if (check_nr_unpack_length(NFAPI_NR_PHY_MSG_TYPE_UCI_INDICATION, unpackedBufLen)) - result = unpack_nr_uci_indication(&pReadPackedMessage, end, pMessageHeader, config); + if (check_nr_unpack_length(NFAPI_NR_PHY_MSG_TYPE_UCI_INDICATION, unpackedBufLen)){ + nfapi_nr_uci_indication_t* msg = (nfapi_nr_uci_indication_t*) pMessageHeader; + msg->uci_list = (nfapi_nr_uci_t*) malloc(sizeof(nfapi_nr_uci_t)); + result = unpack_nr_uci_indication(&pReadPackedMessage, end, msg, config); + } else return -1; break; case NFAPI_NR_PHY_MSG_TYPE_SRS_INDICATION: - if (check_nr_unpack_length(NFAPI_NR_PHY_MSG_TYPE_SRS_INDICATION, unpackedBufLen)) - result = unpack_nr_srs_indication(&pReadPackedMessage, end, pMessageHeader, config); + if (check_nr_unpack_length(NFAPI_NR_PHY_MSG_TYPE_SRS_INDICATION, unpackedBufLen)){ + nfapi_nr_srs_indication_t* msg = (nfapi_nr_srs_indication_t*) pMessageHeader; + msg->pdu_list = (nfapi_nr_srs_indication_pdu_t*) malloc(sizeof(nfapi_nr_srs_indication_pdu_t)); + result = unpack_nr_srs_indication(&pReadPackedMessage, end, msg, config); + } else return -1; break; case NFAPI_NR_PHY_MSG_TYPE_RACH_INDICATION: - if (check_nr_unpack_length(NFAPI_NR_PHY_MSG_TYPE_RACH_INDICATION, unpackedBufLen)) - result = unpack_nr_rach_indication(&pReadPackedMessage, end, pMessageHeader, config); + if (check_nr_unpack_length(NFAPI_NR_PHY_MSG_TYPE_RACH_INDICATION, unpackedBufLen)){ + nfapi_nr_rach_indication_t* msg = (nfapi_nr_rach_indication_t*) pMessageHeader; + result = unpack_nr_rach_indication(&pReadPackedMessage, end, msg, config); + } else return -1; break; 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 518b01864e..14c53b870b 100644 --- a/nfapi/open-nFAPI/vnf/public_inc/nfapi_vnf_interface.h +++ b/nfapi/open-nFAPI/vnf/public_inc/nfapi_vnf_interface.h @@ -852,7 +852,15 @@ typedef struct nfapi_vnf_p7_config * use the codec_config.deallocate function to release it at a future point */ int (*nrach_indication)(struct nfapi_vnf_p7_config* config, nfapi_nrach_indication_t* ind); - + + //The NR indication functions below copy uplink information received at the VNF into the UL info struct + + int (*nr_crc_indication)(nfapi_nr_crc_indication_t* ind); + int (*nr_rx_data_indication)(nfapi_nr_rx_data_indication_t* ind); + int (*nr_uci_indication)(nfapi_nr_uci_indication_t* ind); + int (*nr_rach_indication)(nfapi_nr_rach_indication_t* ind); + int (*nr_srs_indication)(nfapi_nr_srs_indication_t* ind); + /*! A callback for any vendor extension messages * \param config A pointer to the vnf p7 configuration * \param msg A data structure for the decoded vendor extention message allocated diff --git a/nfapi/open-nFAPI/vnf/src/vnf_p7.c b/nfapi/open-nFAPI/vnf/src/vnf_p7.c index 936c434f44..d8d487aba2 100644 --- a/nfapi/open-nFAPI/vnf/src/vnf_p7.c +++ b/nfapi/open-nFAPI/vnf/src/vnf_p7.c @@ -22,6 +22,7 @@ #include #include #include +#include #include "vnf_p7.h" @@ -668,7 +669,6 @@ 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_nr_dl_node_sync_t dl_node_sync; memset(&dl_node_sync, 0, sizeof(dl_node_sync)); @@ -1291,7 +1291,7 @@ void vnf_handle_ul_node_sync(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vnf_p7) { if(phy->in_sync == 0) { - NFAPI_TRACE(NFAPI_TRACE_NOTE, "VNF P7 In Sync with phy (phy_id:%d)\n", phy->phy_id); + //NFAPI_TRACE(NFAPI_TRACE_NOTE, "VNF P7 In Sync with phy (phy_id:%d)\n", phy->phy_id); if(vnf_p7->_public.sync_indication) (vnf_p7->_public.sync_indication)(&(vnf_p7->_public), 1); @@ -1472,6 +1472,13 @@ void vnf_handle_nr_rx_data_indication(void *pRecvMsg, int recvMsgLen, vnf_p7_t* { NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: Failed to unpack message\n", __FUNCTION__); } + else + { + if(vnf_p7->_public.nr_rx_data_indication) + { + (vnf_p7->_public.nr_rx_data_indication)(&ind); + } + } } } @@ -1491,6 +1498,13 @@ void vnf_handle_nr_crc_indication(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vnf_ { NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: Failed to unpack message\n", __FUNCTION__); } + else + { + if(vnf_p7->_public.nr_crc_indication) + { + (vnf_p7->_public.nr_crc_indication)(&ind); + } + } } } @@ -1510,7 +1524,13 @@ void vnf_handle_nr_srs_indication(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vnf_ { NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: Failed to unpack message\n", __FUNCTION__); } - + else + { + if(vnf_p7->_public.nr_srs_indication) + { + (vnf_p7->_public.nr_srs_indication)(&ind); + } + } } } @@ -1529,6 +1549,14 @@ void vnf_handle_nr_uci_indication(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vnf_ { NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: Failed to unpack message\n", __FUNCTION__); } + else + { + if(vnf_p7->_public.nr_uci_indication) + { + (vnf_p7->_public.nr_uci_indication)(&ind); + } + } + } } @@ -1547,6 +1575,13 @@ void vnf_handle_nr_rach_indication(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vnf { NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: Failed to unpack message\n", __FUNCTION__); } + else + { + if(vnf_p7->_public.nr_rach_indication) + { + (vnf_p7->_public.nr_rach_indication)(&ind); + } + } } } @@ -1583,365 +1618,365 @@ void vnf_nr_handle_ul_node_sync(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vnf_p7 if(phy->in_sync == 0) { - NFAPI_TRACE(NFAPI_TRACE_NOTE, "VNF P7 In Sync with phy (phy_id:%d)\n", phy->phy_id); + //NFAPI_TRACE(NFAPI_TRACE_NOTE, "VNF P7 In Sync with phy (phy_id:%d)\n", phy->phy_id); if(vnf_p7->_public.sync_indication) (vnf_p7->_public.sync_indication)(&(vnf_p7->_public), 1); } + printf("t1 = %d,t2 = %d, t3 = %d, t4 = %d. \n",ind.t1, ind.t2, ind.t3, t4); + //phy->in_sync = 1; - phy->in_sync = 1; + if(!(phy->filtered_adjust)) + { + phy->latency[phy->min_sync_cycle_count] = latency; - // if(!(phy->filtered_adjust)) - // { - // phy->latency[phy->min_sync_cycle_count] = latency; + //NFAPI_TRACE(NFAPI_TRACE_NOTE, "(%4d/%d) PNF to VNF !sync phy_id:%d (t1/2/3/4:%8u, %8u, %8u, %8u) txrx:%4u procT:%3u latency(us):%4d\n", + // phy->sfn, phy->slot, ind.header.phy_id, ind.t1, ind.t2, ind.t3, t4, + // tx_2_rx, pnf_proc_time, latency); + } + else + { + phy->latency[phy->min_sync_cycle_count] = latency; - // //NFAPI_TRACE(NFAPI_TRACE_NOTE, "(%4d/%d) PNF to VNF !sync phy_id:%d (t1/2/3/4:%8u, %8u, %8u, %8u) txrx:%4u procT:%3u latency(us):%4d\n", - // // phy->sfn, phy->slot, ind.header.phy_id, ind.t1, ind.t2, ind.t3, t4, - // // tx_2_rx, pnf_proc_time, latency); - // } - // else - // { - // phy->latency[phy->min_sync_cycle_count] = latency; + //if(phy->min_sync_cycle_count != SYNC_CYCLE_COUNT) + { + if (ind.t2 < phy->previous_t2 && ind.t1 > phy->previous_t1) + { + // Only t2 wrap has occurred!!! + phy->slot_offset = (NFAPI_MAX_SFNSLOTDEC + ind.t2) - ind.t1 - latency; + } + else if (ind.t2 > phy->previous_t2 && ind.t1 < phy->previous_t1) + { + // Only t1 wrap has occurred + phy->slot_offset = ind.t2 - ( ind.t1 + NFAPI_MAX_SFNSLOTDEC) - latency; + } + else + { + // Either no wrap or both have wrapped + phy->slot_offset = ind.t2 - ind.t1 - latency; + } - // //if(phy->min_sync_cycle_count != SYNC_CYCLE_COUNT) - // { - // if (ind.t2 < phy->previous_t2 && ind.t1 > phy->previous_t1) - // { - // // Only t2 wrap has occurred!!! - // phy->slot_offset = (NFAPI_MAX_SFNSLOTDEC + ind.t2) - ind.t1 - latency; - // } - // else if (ind.t2 > phy->previous_t2 && ind.t1 < phy->previous_t1) - // { - // // Only t1 wrap has occurred - // phy->slot_offset = ind.t2 - ( ind.t1 + NFAPI_MAX_SFNSLOTDEC) - latency; - // } - // else - // { - // // Either no wrap or both have wrapped - // phy->slot_offset = ind.t2 - ind.t1 - latency; - // } + if (phy->slot_offset_filtered == 0) + { + phy->slot_offset_filtered = phy->slot_offset; + } + else + { + int32_t oldFilteredValueShifted = phy->slot_offset_filtered << 5; + int32_t newOffsetShifted = phy->slot_offset << 5; - // if (phy->slot_offset_filtered == 0) - // { - // phy->slot_offset_filtered = phy->slot_offset; - // } - // else - // { - // int32_t oldFilteredValueShifted = phy->slot_offset_filtered << 5; - // int32_t newOffsetShifted = phy->slot_offset << 5; + // 1/8 of new and 7/8 of old + phy->slot_offset_filtered = ((newOffsetShifted >> 3) + ((oldFilteredValueShifted * 7) >> 3)) >> 5; + } + } - // // 1/8 of new and 7/8 of old - // phy->slot_offset_filtered = ((newOffsetShifted >> 3) + ((oldFilteredValueShifted * 7) >> 3)) >> 5; - // } - // } + if(1) + { + struct timespec ts; + clock_gettime(CLOCK_MONOTONIC, &ts); - // if(1) - // { - // struct timespec ts; - // clock_gettime(CLOCK_MONOTONIC, &ts); + //NFAPI_TRACE(NFAPI_TRACE_NOTE, "(%4d/%1d) %d.%d PNF to VNF phy_id:%2d (t1/2/3/4:%8u, %8u, %8u, %8u) txrx:%4u procT:%3u latency(us):%4d(avg:%4d) offset(us):%8d filtered(us):%8d wrap[t1:%u t2:%u]\n", + // phy->sfn, phy->slot, ts.tv_sec, ts.tv_nsec, ind.header.phy_id, + // ind.t1, ind.t2, ind.t3, t4, + // tx_2_rx, pnf_proc_time, latency, phy->average_latency, phy->slot_offset, phy->slot_offset_filtered, + // (ind.t1previous_t1), (ind.t2previous_t2)); + } - // //NFAPI_TRACE(NFAPI_TRACE_NOTE, "(%4d/%1d) %d.%d PNF to VNF phy_id:%2d (t1/2/3/4:%8u, %8u, %8u, %8u) txrx:%4u procT:%3u latency(us):%4d(avg:%4d) offset(us):%8d filtered(us):%8d wrap[t1:%u t2:%u]\n", - // // phy->sfn, phy->slot, ts.tv_sec, ts.tv_nsec, ind.header.phy_id, - // // ind.t1, ind.t2, ind.t3, t4, - // // tx_2_rx, pnf_proc_time, latency, phy->average_latency, phy->slot_offset, phy->slot_offset_filtered, - // // (ind.t1previous_t1), (ind.t2previous_t2)); - // } + } - // } + if (phy->filtered_adjust && (phy->slot_offset_filtered > 1e6 || phy->slot_offset_filtered < -1e6)) + { + phy->filtered_adjust = 0; + phy->zero_count=0; + phy->min_sync_cycle_count = 2; + phy->in_sync = 0; + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s - ADJUST TOO BAD - go out of filtered phy->slot_offset_filtered:%d\n", __FUNCTION__, phy->slot_offset_filtered); + } - // if (phy->filtered_adjust && (phy->slot_offset_filtered > 1e6 || phy->slot_offset_filtered < -1e6)) - // { - // phy->filtered_adjust = 0; - // phy->zero_count=0; - // phy->min_sync_cycle_count = 2; - // phy->in_sync = 0; - // NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s - ADJUST TOO BAD - go out of filtered phy->slot_offset_filtered:%d\n", __FUNCTION__, phy->slot_offset_filtered); - // } + if(phy->min_sync_cycle_count) + phy->min_sync_cycle_count--; - // if(phy->min_sync_cycle_count) - // phy->min_sync_cycle_count--; + if(phy->min_sync_cycle_count == 0) + { + uint32_t curr_sfn = phy->sfn; + uint32_t curr_slot = phy->slot; + int32_t sfn_slot_dec = NFAPI_SFNSLOT2DEC(phy->sfn,phy->slot); - // if(phy->min_sync_cycle_count == 0) - // { - // uint32_t curr_sfn = phy->sfn; - // uint32_t curr_slot = phy->slot; - // int32_t sfn_slot_dec = NFAPI_SFNSLOT2DEC(phy->sfn,phy->slot); + if(!phy->filtered_adjust) + { + int i = 0; + //phy->average_latency = 0; + for(i = 0; i < SYNC_CYCLE_COUNT; ++i) + { + phy->average_latency += phy->latency[i]; - // if(!phy->filtered_adjust) - // { - // int i = 0; - // //phy->average_latency = 0; - // for(i = 0; i < SYNC_CYCLE_COUNT; ++i) - // { - // phy->average_latency += phy->latency[i]; + } + phy->average_latency /= SYNC_CYCLE_COUNT; - // } - // phy->average_latency /= SYNC_CYCLE_COUNT; + phy->slot_offset = ind.t2 - (ind.t1 - phy->average_latency); - // phy->slot_offset = ind.t2 - (ind.t1 - phy->average_latency); - - // sfn_slot_dec += (phy->slot_offset / 500); + sfn_slot_dec += (phy->slot_offset / 500); - // //NFAPI_TRACE(NFAPI_TRACE_NOTE, "PNF to VNF slot offset:%d sfn :%d slot:%d \n",phy->slot_offset,NFAPI_SFNSLOTDEC2SFN(sfn_slot_dec),NFAPI_SFNSLOTDEC2SLOT(sfn_slot_dec) ); + //NFAPI_TRACE(NFAPI_TRACE_NOTE, "PNF to VNF slot offset:%d sfn :%d slot:%d \n",phy->slot_offset,NFAPI_SFNSLOTDEC2SFN(sfn_slot_dec),NFAPI_SFNSLOTDEC2SLOT(sfn_slot_dec) ); - // } - // else - // { - // sfn_slot_dec += ((phy->slot_offset_filtered + 250) / 500); //Round up to go from microsecond to slot + } + else + { + sfn_slot_dec += ((phy->slot_offset_filtered + 250) / 500); //Round up to go from microsecond to slot - // } + } - // if(sfn_slot_dec < 0) - // { - // sfn_slot_dec += NFAPI_MAX_SFNSLOTDEC; - // } - // else if( sfn_slot_dec >= NFAPI_MAX_SFNSLOTDEC) - // { - // sfn_slot_dec -= NFAPI_MAX_SFNSLOTDEC; - // } + if(sfn_slot_dec < 0) + { + sfn_slot_dec += NFAPI_MAX_SFNSLOTDEC; + } + else if( sfn_slot_dec >= NFAPI_MAX_SFNSLOTDEC) + { + sfn_slot_dec -= NFAPI_MAX_SFNSLOTDEC; + } - // uint16_t new_sfn = NFAPI_SFNSLOTDEC2SFN(sfn_slot_dec); - // uint16_t new_slot = NFAPI_SFNSLOTDEC2SLOT(sfn_slot_dec); + uint16_t new_sfn = NFAPI_SFNSLOTDEC2SFN(sfn_slot_dec); + uint16_t new_slot = NFAPI_SFNSLOTDEC2SLOT(sfn_slot_dec); - // { - // phy->adjustment = NFAPI_SFNSLOT2DEC(new_sfn, new_slot) - NFAPI_SFNSLOT2DEC(curr_sfn, curr_slot); + { + phy->adjustment = NFAPI_SFNSLOT2DEC(new_sfn, new_slot) - NFAPI_SFNSLOT2DEC(curr_sfn, curr_slot); - // //NFAPI_TRACE(NFAPI_TRACE_NOTE, "PNF to VNF phy_id:%d adjustment%d phy->previous_slot_offset_filtered:%d phy->previous_slot_offset_filtered:%d phy->slot_offset_trend:%d\n", ind.header.phy_id, phy->adjustment, phy->previous_slot_offset_filtered, phy->previous_slot_offset_filtered, phy->slot_offset_trend); + //NFAPI_TRACE(NFAPI_TRACE_NOTE, "PNF to VNF phy_id:%d adjustment%d phy->previous_slot_offset_filtered:%d phy->previous_slot_offset_filtered:%d phy->slot_offset_trend:%d\n", ind.header.phy_id, phy->adjustment, phy->previous_slot_offset_filtered, phy->previous_slot_offset_filtered, phy->slot_offset_trend); -// phy->previous_t1 = 0; -// phy->previous_t2 = 0; + phy->previous_t1 = 0; + phy->previous_t2 = 0; -// if(phy->previous_slot_offset_filtered > 0) -// { -// if( phy->slot_offset_filtered > phy->previous_slot_offset_filtered) -// { -// // pnf is getting futher ahead of vnf -// //phy->sf_offset_trend = phy->sf_offset_filtered - phy->previous_sf_offset_filtered; -// phy->slot_offset_trend = (phy->slot_offset_filtered + phy->previous_slot_offset_filtered)/2; -// } -// else -// { -// // pnf is getting back in sync -// } -// } -// else if(phy->previous_slot_offset_filtered < 0) -// { -// if(phy->slot_offset_filtered < phy->previous_slot_offset_filtered) -// { -// // vnf is getting future ahead of pnf -// //phy->sf_offset_trend = -(phy->sf_offset_filtered - phy->previous_sf_offset_filtered); -// phy->slot_offset_trend = (-(phy->slot_offset_filtered + phy->previous_slot_offset_filtered)) /2; -// } -// else -// { -// // vnf is getting back in sync -// } -// } + if(phy->previous_slot_offset_filtered > 0) + { + if( phy->slot_offset_filtered > phy->previous_slot_offset_filtered) + { + // pnf is getting futher ahead of vnf + //phy->sf_offset_trend = phy->sf_offset_filtered - phy->previous_sf_offset_filtered; + phy->slot_offset_trend = (phy->slot_offset_filtered + phy->previous_slot_offset_filtered)/2; + } + else + { + // pnf is getting back in sync + } + } + else if(phy->previous_slot_offset_filtered < 0) + { + if(phy->slot_offset_filtered < phy->previous_slot_offset_filtered) + { + // vnf is getting future ahead of pnf + //phy->sf_offset_trend = -(phy->sf_offset_filtered - phy->previous_sf_offset_filtered); + phy->slot_offset_trend = (-(phy->slot_offset_filtered + phy->previous_slot_offset_filtered)) /2; + } + else + { + // vnf is getting back in sync + } + } -// int insync_minor_adjustment_1 = phy->slot_offset_trend / 6; -// int insync_minor_adjustment_2 = phy->slot_offset_trend / 2; + int insync_minor_adjustment_1 = phy->slot_offset_trend / 6; + int insync_minor_adjustment_2 = phy->slot_offset_trend / 2; -// if(insync_minor_adjustment_1 == 0) -// insync_minor_adjustment_1 = 2; + if(insync_minor_adjustment_1 == 0) + insync_minor_adjustment_1 = 2; -// if(insync_minor_adjustment_2 == 0) -// insync_minor_adjustment_2 = 10; + if(insync_minor_adjustment_2 == 0) + insync_minor_adjustment_2 = 10; -// if(!phy->filtered_adjust) -// { -// if(phy->adjustment < 10) -// { -// phy->zero_count++; + if(!phy->filtered_adjust) + { + if(phy->adjustment < 10) + { + phy->zero_count++; -// if(phy->zero_count >= 10) -// { -// phy->filtered_adjust = 1; -// phy->zero_count = 0; + if(phy->zero_count >= 10) + { + phy->filtered_adjust = 1; + phy->zero_count = 0; -// NFAPI_TRACE(NFAPI_TRACE_NOTE, "***** Adjusting VNF SFN/SF switching to filtered mode\n"); -// } -// } -// else -// { -// phy->zero_count = 0; -// } -// } -// else -// { -// // Fine level of adjustment -// if (phy->adjustment == 0) -// { -// if (phy->zero_count >= 10) -// { -// if(phy->in_sync == 0) -// { -// NFAPI_TRACE(NFAPI_TRACE_NOTE, "VNF P7 In Sync with phy (phy_id:%d)\n", phy->phy_id); + NFAPI_TRACE(NFAPI_TRACE_NOTE, "***** Adjusting VNF SFN/SF switching to filtered mode\n"); + } + } + else + { + phy->zero_count = 0; + } + } + else + { + // Fine level of adjustment + if (phy->adjustment == 0) + { + if (phy->zero_count >= 10) + { + if(phy->in_sync == 0) + { + NFAPI_TRACE(NFAPI_TRACE_NOTE, "VNF P7 In Sync with phy (phy_id:%d)\n", phy->phy_id); -// if(vnf_p7->_public.sync_indication) -// (vnf_p7->_public.sync_indication)(&(vnf_p7->_public), 1); -// } + if(vnf_p7->_public.sync_indication) + (vnf_p7->_public.sync_indication)(&(vnf_p7->_public), 1); + } -// phy->in_sync = 1; -// } -// else -// { -// phy->zero_count++; -// } + phy->in_sync = 1; + } + else + { + phy->zero_count++; + } -// if(phy->in_sync) -// { -// // in sync -// if(phy->slot_offset_filtered > 250) -// { -// // VNF is slow -// phy->insync_minor_adjustment = insync_minor_adjustment_1; //25; -// phy->insync_minor_adjustment_duration = ((phy->slot_offset_filtered) / insync_minor_adjustment_1); -// } -// else if(phy->slot_offset_filtered < -250) -// { -// // VNF is fast -// phy->insync_minor_adjustment = -(insync_minor_adjustment_1); //25; -// phy->insync_minor_adjustment_duration = (((phy->slot_offset_filtered) / -(insync_minor_adjustment_1))); -// } -// else -// { -// phy->insync_minor_adjustment = 0; -// } + if(phy->in_sync) + { + // in sync + if(phy->slot_offset_filtered > 250) + { + // VNF is slow + phy->insync_minor_adjustment = insync_minor_adjustment_1; //25; + phy->insync_minor_adjustment_duration = ((phy->slot_offset_filtered) / insync_minor_adjustment_1); + } + else if(phy->slot_offset_filtered < -250) + { + // VNF is fast + phy->insync_minor_adjustment = -(insync_minor_adjustment_1); //25; + phy->insync_minor_adjustment_duration = (((phy->slot_offset_filtered) / -(insync_minor_adjustment_1))); + } + else + { + phy->insync_minor_adjustment = 0; + } -// if(phy->insync_minor_adjustment != 0) -// { -// // NFAPI_TRACE(NFAPI_TRACE_NOTE, "(%4d/%d) VNF phy_id:%d Apply minor insync adjustment %dus for %d slots (slot_offset_filtered:%d) %d %d %d NEW:%d CURR:%d adjustment:%d\n", -// // phy->sfn, phy->slot, ind.header.phy_id, -// // phy->insync_minor_adjustment, phy->insync_minor_adjustment_duration, -// // phy->slot_offset_filtered, -// // insync_minor_adjustment_1, insync_minor_adjustment_2, phy->slot_offset_trend, -// // NFAPI_SFNSLOT2DEC(new_sfn, new_slot), -// // NFAPI_SFNSLOT2DEC(curr_sfn, curr_slot), -// // phy->adjustment); -// } -// } -// } -// else -// { -// if (phy->in_sync) -// { -// if(phy->adjustment == 0) -// { -// } -// else if(phy->adjustment > 0) -// { -// // VNF is slow -// //if(phy->adjustment == 1) -// { -// // -// if(phy->slot_offset_filtered > 250) -// { -// // VNF is slow -// phy->insync_minor_adjustment = insync_minor_adjustment_2; -// phy->insync_minor_adjustment_duration = 2 * ((phy->slot_offset_filtered - 250) / insync_minor_adjustment_2); -// } -// else if(phy->slot_offset_filtered < -250) -// { -// // VNF is fast -// phy->insync_minor_adjustment = -(insync_minor_adjustment_2); -// phy->insync_minor_adjustment_duration = 2 * ((phy->slot_offset_filtered + 250) / -(insync_minor_adjustment_2)); -// } + if(phy->insync_minor_adjustment != 0) + { + // NFAPI_TRACE(NFAPI_TRACE_NOTE, "(%4d/%d) VNF phy_id:%d Apply minor insync adjustment %dus for %d slots (slot_offset_filtered:%d) %d %d %d NEW:%d CURR:%d adjustment:%d\n", + // phy->sfn, phy->slot, ind.header.phy_id, + // phy->insync_minor_adjustment, phy->insync_minor_adjustment_duration, + // phy->slot_offset_filtered, + // insync_minor_adjustment_1, insync_minor_adjustment_2, phy->slot_offset_trend, + // NFAPI_SFNSLOT2DEC(new_sfn, new_slot), + // NFAPI_SFNSLOT2DEC(curr_sfn, curr_slot), + // phy->adjustment); + } + } + } + else + { + if (phy->in_sync) + { + if(phy->adjustment == 0) + { + } + else if(phy->adjustment > 0) + { + // VNF is slow + //if(phy->adjustment == 1) + { + // + if(phy->slot_offset_filtered > 250) + { + // VNF is slow + phy->insync_minor_adjustment = insync_minor_adjustment_2; + phy->insync_minor_adjustment_duration = 2 * ((phy->slot_offset_filtered - 250) / insync_minor_adjustment_2); + } + else if(phy->slot_offset_filtered < -250) + { + // VNF is fast + phy->insync_minor_adjustment = -(insync_minor_adjustment_2); + phy->insync_minor_adjustment_duration = 2 * ((phy->slot_offset_filtered + 250) / -(insync_minor_adjustment_2)); + } -// } -// //else -// { -// // out of sync? -// } + } + //else + { + // out of sync? + } -// // NFAPI_TRACE(NFAPI_TRACE_NOTE, "(%4d/%d) VNF phy_id:%d Apply minor insync adjustment %dus for %d slots (adjustment:%d slot_offset_filtered:%d) %d %d %d NEW:%d CURR:%d adj:%d\n", -// // phy->sfn, phy->slot, ind.header.phy_id, -// // phy->insync_minor_adjustment, phy->insync_minor_adjustment_duration, phy->adjustment, phy->slot_offset_filtered, -// // insync_minor_adjustment_1, insync_minor_adjustment_2, phy->slot_offset_trend, -// // NFAPI_SFNSLOT2DEC(new_sfn, new_slot), -// // NFAPI_SFNSLOT2DEC(curr_sfn, curr_slot), -// // phy->adjustment); + // NFAPI_TRACE(NFAPI_TRACE_NOTE, "(%4d/%d) VNF phy_id:%d Apply minor insync adjustment %dus for %d slots (adjustment:%d slot_offset_filtered:%d) %d %d %d NEW:%d CURR:%d adj:%d\n", + // phy->sfn, phy->slot, ind.header.phy_id, + // phy->insync_minor_adjustment, phy->insync_minor_adjustment_duration, phy->adjustment, phy->slot_offset_filtered, + // insync_minor_adjustment_1, insync_minor_adjustment_2, phy->slot_offset_trend, + // NFAPI_SFNSLOT2DEC(new_sfn, new_slot), + // NFAPI_SFNSLOT2DEC(curr_sfn, curr_slot), + // phy->adjustment); -// } -// else if(phy->adjustment < 0) -// { -// // VNF is fast -// //if(phy->adjustment == -1) -// { -// // -// if(phy->slot_offset_filtered > 250) -// { -// // VNF is slow -// phy->insync_minor_adjustment = insync_minor_adjustment_2; -// phy->insync_minor_adjustment_duration = 2 * ((phy->slot_offset_filtered - 250) / insync_minor_adjustment_2); -// } -// else if(phy->slot_offset_filtered < -250) -// { -// // VNF is fast -// phy->insync_minor_adjustment = -(insync_minor_adjustment_2); -// phy->insync_minor_adjustment_duration = 2 * ((phy->slot_offset_filtered + 250) / -(insync_minor_adjustment_2)); -// } -// } -// //else -// { -// // out of sync? -// } + } + else if(phy->adjustment < 0) + { + // VNF is fast + //if(phy->adjustment == -1) + { + // + if(phy->slot_offset_filtered > 250) + { + // VNF is slow + phy->insync_minor_adjustment = insync_minor_adjustment_2; + phy->insync_minor_adjustment_duration = 2 * ((phy->slot_offset_filtered - 250) / insync_minor_adjustment_2); + } + else if(phy->slot_offset_filtered < -250) + { + // VNF is fast + phy->insync_minor_adjustment = -(insync_minor_adjustment_2); + phy->insync_minor_adjustment_duration = 2 * ((phy->slot_offset_filtered + 250) / -(insync_minor_adjustment_2)); + } + } + //else + { + // out of sync? + } -// // NFAPI_TRACE(NFAPI_TRACE_NOTE, "(%d/%d) VNF phy_id:%d Apply minor insync adjustment %dus for %d slots (adjustment:%d slot_offset_filtered:%d) %d %d %d\n", -// // phy->sfn, phy->slot, ind.header.phy_id, -// // phy->insync_minor_adjustment, phy->insync_minor_adjustment_duration, phy->adjustment, phy->slot_offset_filtered, -// // insync_minor_adjustment_1, insync_minor_adjustment_2, phy->slot_offset_trend); -// } + // NFAPI_TRACE(NFAPI_TRACE_NOTE, "(%d/%d) VNF phy_id:%d Apply minor insync adjustment %dus for %d slots (adjustment:%d slot_offset_filtered:%d) %d %d %d\n", + // phy->sfn, phy->slot, ind.header.phy_id, + // phy->insync_minor_adjustment, phy->insync_minor_adjustment_duration, phy->adjustment, phy->slot_offset_filtered, + // insync_minor_adjustment_1, insync_minor_adjustment_2, phy->slot_offset_trend); + } -// /* -// if (phy->adjustment > 10 || phy->adjustment < -10) -// { -// phy->zero_count++; // Add one to the getting out of sync counter -// } -// else -// { -// phy->zero_count = 0; // Small error - zero the out of sync counter -// } + /* + if (phy->adjustment > 10 || phy->adjustment < -10) + { + phy->zero_count++; // Add one to the getting out of sync counter + } + else + { + phy->zero_count = 0; // Small error - zero the out of sync counter + } -// if (phy->zero_count >= 10) // If we have had 10 consecutive large errors - drop out of sync -// { -// NFAPI_TRACE(NFAPI_TRACE_NOTE, "we have fallen out of sync...\n"); -// //pP7SockInfo->syncAchieved = 0; -// } -// */ -// } -// } -// } + if (phy->zero_count >= 10) // If we have had 10 consecutive large errors - drop out of sync + { + NFAPI_TRACE(NFAPI_TRACE_NOTE, "we have fallen out of sync...\n"); + //pP7SockInfo->syncAchieved = 0; + } + */ + } + } + } -// if(phy->in_sync == 0) -// { -// /*NFAPI_TRACE(NFAPI_TRACE_NOTE, "***** Adjusting VNF phy_id:%d SFN/SF (%s) from %d to %d (%d) mode:%s zeroCount:%u sync:%s\n", -// ind.header.phy_id, (phy->in_sync ? "via sfn" : "now"), -// NFAPI_SFNSF2DEC(curr_sfn_sf), NFAPI_SFNSF2DEC(new_sfn_sf), phy->adjustment, -// phy->filtered_adjust ? "FILTERED" : "ABSOLUTE", -// phy->zero_count, -// phy->in_sync ? "IN_SYNC" : "OUT_OF_SYNC");*/ + if(phy->in_sync == 0) + { + /*NFAPI_TRACE(NFAPI_TRACE_NOTE, "***** Adjusting VNF phy_id:%d SFN/SF (%s) from %d to %d (%d) mode:%s zeroCount:%u sync:%s\n", + ind.header.phy_id, (phy->in_sync ? "via sfn" : "now"), + NFAPI_SFNSF2DEC(curr_sfn_sf), NFAPI_SFNSF2DEC(new_sfn_sf), phy->adjustment, + phy->filtered_adjust ? "FILTERED" : "ABSOLUTE", + phy->zero_count, + phy->in_sync ? "IN_SYNC" : "OUT_OF_SYNC");*/ -// phy->sfn = new_sfn; -// phy->slot = new_slot; -// } -// } + phy->sfn = new_sfn; + phy->slot = new_slot; + } + } -// // reset for next cycle -// phy->previous_slot_offset_filtered = phy->slot_offset_filtered; -// phy->min_sync_cycle_count = 2; -// phy->slot_offset_filtered = 0; -// phy->slot_offset = 0; -// } -// else -// { -// phy->previous_t1 = ind.t1; -// phy->previous_t2 = ind.t2; -// } + // reset for next cycle + phy->previous_slot_offset_filtered = phy->slot_offset_filtered; + phy->min_sync_cycle_count = 2; + phy->slot_offset_filtered = 0; + phy->slot_offset = 0; + } + else + { + phy->previous_t1 = ind.t1; + phy->previous_t2 = ind.t2; + } } void vnf_handle_timing_info(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vnf_p7) diff --git a/nfapi/open-nFAPI/vnf/src/vnf_p7_interface.c b/nfapi/open-nFAPI/vnf/src/vnf_p7_interface.c index f66919434e..5b36873e1c 100644 --- a/nfapi/open-nFAPI/vnf/src/vnf_p7_interface.c +++ b/nfapi/open-nFAPI/vnf/src/vnf_p7_interface.c @@ -422,7 +422,7 @@ struct timespec current_time; vnf_frame = curr->sfn; vnf_slot = curr->slot; struct timespec curr_time; - clock_gettime(CLOCK_MONOTONIC, &curr_time); + clock_gettime(CLOCK_MONOTONIC, &curr_time); //printf("SFN=%d, slot=%d, Curr_time=%d.%d \n",vnf_frame,vnf_slot,curr_time.tv_sec,curr_time.tv_nsec); vnf_nr_sync(vnf_p7, curr); From ba2c28f6b1b47ddcafc4eafede881d4548de20f6 Mon Sep 17 00:00:00 2001 From: Mahesh Date: Fri, 18 Jun 2021 19:26:56 +0530 Subject: [PATCH 27/91] PNF slot ticking fix --- nfapi/oai_integration/nfapi_vnf.c | 2 +- nfapi/open-nFAPI/nfapi/src/nfapi_p7.c | 1 - nfapi/open-nFAPI/pnf/src/pnf_p7.c | 84 +++++++++++++++++++-- nfapi/open-nFAPI/vnf/src/vnf_p7.c | 29 ++++--- nfapi/open-nFAPI/vnf/src/vnf_p7_interface.c | 3 +- 5 files changed, 92 insertions(+), 27 deletions(-) diff --git a/nfapi/oai_integration/nfapi_vnf.c b/nfapi/oai_integration/nfapi_vnf.c index 8f30a091ab..80757089c6 100644 --- a/nfapi/oai_integration/nfapi_vnf.c +++ b/nfapi/oai_integration/nfapi_vnf.c @@ -596,7 +596,7 @@ extern pthread_mutex_t nfapi_sync_mutex; extern int nfapi_sync_var; int phy_sync_indication(struct nfapi_vnf_p7_config *config, uint8_t sync) { - //printf("[VNF] SYNC %s\n", sync==1 ? "ACHIEVED" : "LOST"); + printf("[VNF] SYNC %s\n", sync==1 ? "ACHIEVED" : "LOST"); if (sync==1 && nfapi_sync_var!=0) { diff --git a/nfapi/open-nFAPI/nfapi/src/nfapi_p7.c b/nfapi/open-nFAPI/nfapi/src/nfapi_p7.c index 3a90ca4363..de2316e4d7 100755 --- a/nfapi/open-nFAPI/nfapi/src/nfapi_p7.c +++ b/nfapi/open-nFAPI/nfapi/src/nfapi_p7.c @@ -307,7 +307,6 @@ static uint8_t pack_dl_tti_pdcch_pdu_rel15_value(void* tlv, uint8_t **ppWritePac static uint8_t pack_dl_tti_pdsch_pdu_rel15_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { - printf("packing pdsch pdu. \n"); nfapi_nr_dl_tti_pdsch_pdu_rel15_t* value = (nfapi_nr_dl_tti_pdsch_pdu_rel15_t*)tlv; // TODO: resolve the packaging of array (currently sending a single element) diff --git a/nfapi/open-nFAPI/pnf/src/pnf_p7.c b/nfapi/open-nFAPI/pnf/src/pnf_p7.c index ab3b9196f1..b14e17d576 100644 --- a/nfapi/open-nFAPI/pnf/src/pnf_p7.c +++ b/nfapi/open-nFAPI/pnf/src/pnf_p7.c @@ -935,9 +935,9 @@ int pnf_p7_slot_ind(pnf_p7_t* pnf_p7, uint16_t phy_id, uint16_t sfn, uint16_t sl // save the curren time, sfn and slot pnf_p7->slot_start_time_hr = pnf_get_current_time_hr(); - pnf_p7->sfn = sfn; + // pnf_p7->sfn = sfn; - pnf_p7->slot = slot; + // pnf_p7->slot = slot; @@ -3202,6 +3202,38 @@ int pnf_p7_message_pump(pnf_p7_t* pnf_p7) return 0; } +struct timespec pnf_timespec_add(struct timespec lhs, struct timespec rhs) +{ + struct timespec result; + + result.tv_sec = lhs.tv_sec + rhs.tv_sec; + result.tv_nsec = lhs.tv_nsec + rhs.tv_nsec; + + if(result.tv_nsec > 1e9) + { + result.tv_sec++; + result.tv_nsec-= 1e9; + } + + return result; +} + +struct timespec pnf_timespec_sub(struct timespec lhs, struct timespec rhs) +{ + struct timespec result; + 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 + { + 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) { @@ -3279,6 +3311,23 @@ int pnf_nr_p7_message_pump(pnf_p7_t* pnf_p7) } 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 timeout; + timeout.tv_sec = 0; + timeout.tv_nsec = 500000; + + 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; @@ -3288,11 +3337,26 @@ int pnf_nr_p7_message_pump(pnf_p7_t* pnf_p7) FD_ZERO(&rfds); FD_SET(pnf_p7->p7_sock, &rfds); - struct timeval timeout; - timeout.tv_sec = 0; - timeout.tv_usec = 500; + clock_gettime(CLOCK_MONOTONIC, &pselect_start); - selectRetval = select(pnf_p7->p7_sock+1, &rfds, NULL, NULL, &timeout); + //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(); @@ -3302,15 +3366,19 @@ int pnf_nr_p7_message_pump(pnf_p7_t* pnf_p7) if(selectRetval == 0) { // timeout - //continue; + + //update slot start timing + slot_start = pnf_timespec_add(slot_start, slot_duration); + + //increment sfn/slot if (pnf_slot == 19) pnf_frame = (pnf_frame + 1) % 1024; pnf_slot = (pnf_slot + 1) % 20; pnf_p7->sfn = pnf_frame; pnf_p7->slot = pnf_slot; + struct timespec curr_time; clock_gettime(CLOCK_MONOTONIC, &curr_time); - //printf("SFN=%d, slot=%d, Curr_time=%d.%d \n",pnf_p7->sfn,pnf_p7->slot,curr_time.tv_sec,curr_time.tv_nsec); } else if (selectRetval == -1 && (errno == EINTR)) { diff --git a/nfapi/open-nFAPI/vnf/src/vnf_p7.c b/nfapi/open-nFAPI/vnf/src/vnf_p7.c index d8d487aba2..e038f59217 100644 --- a/nfapi/open-nFAPI/vnf/src/vnf_p7.c +++ b/nfapi/open-nFAPI/vnf/src/vnf_p7.c @@ -1616,14 +1616,6 @@ void vnf_nr_handle_ul_node_sync(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vnf_p7 // divide by 2 using shift operator uint32_t latency = (tx_2_rx - pnf_proc_time) >> 1; - if(phy->in_sync == 0) - { - //NFAPI_TRACE(NFAPI_TRACE_NOTE, "VNF P7 In Sync with phy (phy_id:%d)\n", phy->phy_id); - - if(vnf_p7->_public.sync_indication) - (vnf_p7->_public.sync_indication)(&(vnf_p7->_public), 1); - } - printf("t1 = %d,t2 = %d, t3 = %d, t4 = %d. \n",ind.t1, ind.t2, ind.t3, t4); //phy->in_sync = 1; if(!(phy->filtered_adjust)) @@ -1675,17 +1667,24 @@ void vnf_nr_handle_ul_node_sync(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vnf_p7 struct timespec ts; clock_gettime(CLOCK_MONOTONIC, &ts); - //NFAPI_TRACE(NFAPI_TRACE_NOTE, "(%4d/%1d) %d.%d PNF to VNF phy_id:%2d (t1/2/3/4:%8u, %8u, %8u, %8u) txrx:%4u procT:%3u latency(us):%4d(avg:%4d) offset(us):%8d filtered(us):%8d wrap[t1:%u t2:%u]\n", - // phy->sfn, phy->slot, ts.tv_sec, ts.tv_nsec, ind.header.phy_id, - // ind.t1, ind.t2, ind.t3, t4, - // tx_2_rx, pnf_proc_time, latency, phy->average_latency, phy->slot_offset, phy->slot_offset_filtered, - // (ind.t1previous_t1), (ind.t2previous_t2)); + // NFAPI_TRACE(NFAPI_TRACE_NOTE, "(%4d/%1d) %d.%d PNF to VNF phy_id:%2d (t1/2/3/4:%8u, %8u, %8u, %8u) txrx:%4u procT:%3u latency(us):%4d(avg:%4d) offset(us):%8d filtered(us):%8d wrap[t1:%u t2:%u]\n", + // phy->sfn, phy->slot, ts.tv_sec, ts.tv_nsec, ind.header.phy_id, + // ind.t1, ind.t2, ind.t3, t4, + // tx_2_rx, pnf_proc_time, latency, phy->average_latency, phy->slot_offset, phy->slot_offset_filtered, + // (ind.t1previous_t1), (ind.t2previous_t2)); } } if (phy->filtered_adjust && (phy->slot_offset_filtered > 1e6 || phy->slot_offset_filtered < -1e6)) - { + { struct timespec ts; + clock_gettime(CLOCK_MONOTONIC, &ts); + NFAPI_TRACE(NFAPI_TRACE_NOTE, "(%4d/%1d) %d.%d PNF to VNF phy_id:%2d (t1/2/3/4:%8u, %8u, %8u, %8u) txrx:%4u procT:%3u latency(us):%4d(avg:%4d) offset(us):%8d filtered(us):%8d wrap[t1:%u t2:%u]\n", + phy->sfn, phy->slot, ts.tv_sec, ts.tv_nsec, ind.header.phy_id, + ind.t1, ind.t2, ind.t3, t4, + tx_2_rx, pnf_proc_time, latency, phy->average_latency, phy->slot_offset, phy->slot_offset_filtered, + (ind.t1previous_t1), (ind.t2previous_t2)); + phy->filtered_adjust = 0; phy->zero_count=0; phy->min_sync_cycle_count = 2; @@ -1961,7 +1960,7 @@ void vnf_nr_handle_ul_node_sync(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vnf_p7 phy->zero_count, phy->in_sync ? "IN_SYNC" : "OUT_OF_SYNC");*/ - phy->sfn = new_sfn; + phy->sfn = new_sfn; phy->slot = new_slot; } } diff --git a/nfapi/open-nFAPI/vnf/src/vnf_p7_interface.c b/nfapi/open-nFAPI/vnf/src/vnf_p7_interface.c index 5b36873e1c..34318dcbcc 100644 --- a/nfapi/open-nFAPI/vnf/src/vnf_p7_interface.c +++ b/nfapi/open-nFAPI/vnf/src/vnf_p7_interface.c @@ -418,12 +418,11 @@ struct timespec current_time; { curr->slot++; } - //printf("Frame = %d, slot = %d in VNF main loop. n",curr->sfn,curr->slot); + //printf("Frame = %d, slot = %d in VNF main loop. \n",curr->sfn,curr->slot); vnf_frame = curr->sfn; vnf_slot = curr->slot; struct timespec curr_time; clock_gettime(CLOCK_MONOTONIC, &curr_time); - //printf("SFN=%d, slot=%d, Curr_time=%d.%d \n",vnf_frame,vnf_slot,curr_time.tv_sec,curr_time.tv_nsec); vnf_nr_sync(vnf_p7, curr); curr = curr->next; From 9421c35a72b07390f9a45349ca7816b31392fe42 Mon Sep 17 00:00:00 2001 From: Mahesh Date: Tue, 29 Jun 2021 08:49:48 +0530 Subject: [PATCH 28/91] Code cleanup --- executables/nr-ru.c | 6 +++--- nfapi/open-nFAPI/nfapi/src/nfapi.c | 2 +- openair1/PHY/NR_TRANSPORT/pucch_rx.c | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/executables/nr-ru.c b/executables/nr-ru.c index 360bd97287..0a042ba9b1 100644 --- a/executables/nr-ru.c +++ b/executables/nr-ru.c @@ -97,6 +97,7 @@ static int DEFBFW[] = {0x00007fff}; extern volatile int oai_exit; + extern void nr_phy_free_RU(RU_t *); extern void nr_phy_config_request(NR_PHY_Config_t *gNB); #include "executables/thread-common.h" @@ -708,7 +709,7 @@ void rx_rf(RU_t *ru,int *frame,int *slot) { } -void tx_rf(RU_t *ru,int frame,int slot, uint64_t timestamp) { +void tx_rf(RU_t *ru,int frame,int slot, uint64_t timestamp) { RU_proc_t *proc = &ru->proc; NR_DL_FRAME_PARMS *fp = ru->nr_frame_parms; nfapi_nr_config_request_scf_t *cfg = &ru->config; @@ -1299,7 +1300,6 @@ void *ru_thread( void *param ) { } // This is a forever while loop, it loops over subframes which are scheduled by incoming samples from HW devices - while (!oai_exit) { // these are local subframe/frame counters to check that we are in synch with the fronthaul timing. // They are set on the first rx/tx in the underly FH routines. @@ -1331,7 +1331,7 @@ void *ru_thread( void *param ) { // do RX front-end processing (frequency-shift, dft) if needed - int slot_type = nr_slot_select(cfg,proc->frame_rx,proc->tti_rx); + int slot_type = nr_slot_select(cfg,proc->frame_rx,proc->tti_rx); if (slot_type == NR_UPLINK_SLOT || slot_type == NR_MIXED_SLOT) { if (ru->feprx) { diff --git a/nfapi/open-nFAPI/nfapi/src/nfapi.c b/nfapi/open-nFAPI/nfapi/src/nfapi.c index 6ca64138f2..ba800c3634 100644 --- a/nfapi/open-nFAPI/nfapi/src/nfapi.c +++ b/nfapi/open-nFAPI/nfapi/src/nfapi.c @@ -189,7 +189,7 @@ uint8_t pull8(uint8_t **in, uint8_t *out, uint8_t *end) return 1; } else - { + { NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s no space in buffer\n", __FUNCTION__); return 0; } diff --git a/openair1/PHY/NR_TRANSPORT/pucch_rx.c b/openair1/PHY/NR_TRANSPORT/pucch_rx.c index 9159627286..aed8c2f8bb 100644 --- a/openair1/PHY/NR_TRANSPORT/pucch_rx.c +++ b/openair1/PHY/NR_TRANSPORT/pucch_rx.c @@ -1466,7 +1466,7 @@ void nr_decode_pucch2(PHY_VARS_gNB *gNB, } } // cw loop corr_dB = dB_fixed64((uint64_t)corr); - LOG_I(PHY,"cw_ML %d, metric %d dB\n",cw_ML,corr_dB); + LOG_D(PHY,"cw_ML %d, metric %d dB\n",cw_ML,corr_dB); decodedPayload[0]=(uint64_t)cw_ML; } else { // polar coded case From 64a7191872cbe7d64a7b816274c0d46554acc300 Mon Sep 17 00:00:00 2001 From: Mahesh Date: Tue, 29 Jun 2021 20:15:29 +0530 Subject: [PATCH 29/91] Cleanup --- openair1/PHY/NR_TRANSPORT/pucch_rx.c | 8 ++-- openair1/SCHED_NR/phy_frame_config_nr.c | 2 +- openair1/SCHED_NR/phy_procedures_nr_gNB.c | 6 --- openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c | 46 ++++++++----------- .../LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c | 2 +- openair2/NR_PHY_INTERFACE/NR_IF_Module.c | 10 ++-- 6 files changed, 30 insertions(+), 44 deletions(-) diff --git a/openair1/PHY/NR_TRANSPORT/pucch_rx.c b/openair1/PHY/NR_TRANSPORT/pucch_rx.c index aed8c2f8bb..8145cf893c 100644 --- a/openair1/PHY/NR_TRANSPORT/pucch_rx.c +++ b/openair1/PHY/NR_TRANSPORT/pucch_rx.c @@ -47,7 +47,6 @@ #include "PHY/NR_REFSIG/nr_refsig.h" #include "common/utils/LOG/log.h" #include "common/utils/LOG/vcd_signal_dumper.h" -#include "nfapi/oai_integration/vendor_ext.h" #include "T.h" @@ -87,8 +86,7 @@ void nr_fill_pucch(PHY_VARS_gNB *gNB, int frame, int slot, nfapi_nr_pucch_pdu_t *pucch_pdu) { - if (NFAPI_MODE == NFAPI_MODE_PNF) - gNB->pucch[0]->active = 0; //check if ture in monolithic mode + int id = nr_find_pucch(pucch_pdu->rnti,frame,slot,gNB); AssertFatal( (id>=0) && (idrnti,id); @@ -169,6 +167,7 @@ void nr_decode_pucch0(PHY_VARS_gNB *gNB, int32_t **rxdataF = gNB->common_vars.rxdataF; NR_DL_FRAME_PARMS *frame_parms = &gNB->frame_parms; + int nr_sequences; const uint8_t *mcs; @@ -1086,7 +1085,8 @@ void init_pucch2_luts() { void nr_decode_pucch2(PHY_VARS_gNB *gNB, int slot, nfapi_nr_uci_pucch_pdu_format_2_3_4_t* uci_pdu, - nfapi_nr_pucch_pdu_t* pucch_pdu) { + nfapi_nr_pucch_pdu_t* pucch_pdu) { + int32_t **rxdataF = gNB->common_vars.rxdataF; NR_DL_FRAME_PARMS *frame_parms = &gNB->frame_parms; //pucch_GroupHopping_t pucch_GroupHopping = pucch_pdu->group_hop_flag + (pucch_pdu->sequence_hop_flag<<1); diff --git a/openair1/SCHED_NR/phy_frame_config_nr.c b/openair1/SCHED_NR/phy_frame_config_nr.c index 4c255e52aa..9be6780597 100644 --- a/openair1/SCHED_NR/phy_frame_config_nr.c +++ b/openair1/SCHED_NR/phy_frame_config_nr.c @@ -315,7 +315,7 @@ int nr_slot_select(nfapi_nr_config_request_scf_t *cfg, int nr_frame, int nr_slot if (cfg->cell_config.frame_duplex_type.value == FDD) { return (NR_UPLINK_SLOT | NR_DOWNLINK_SLOT ); } - + if (nr_frame%2 == 0) { for(int symbol_count=0; symbol_counttdd_table.max_tdd_periodicity_list[nr_slot].max_num_of_symbol_per_slot_list[symbol_count].slot_config.value==1) { diff --git a/openair1/SCHED_NR/phy_procedures_nr_gNB.c b/openair1/SCHED_NR/phy_procedures_nr_gNB.c index 4a99b311db..83483f3a7f 100644 --- a/openair1/SCHED_NR/phy_procedures_nr_gNB.c +++ b/openair1/SCHED_NR/phy_procedures_nr_gNB.c @@ -532,7 +532,6 @@ int phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx) { LOG_D(PHY,"phy_procedures_gNB_uespec_RX frame %d, slot %d\n",frame_rx,slot_rx); if (gNB->frame_parms.frame_type == TDD) - if(NFAPI_MODE != NFAPI_MODE_VNF) fill_ul_rb_mask(gNB, frame_rx, slot_rx); gNB_I0_measurements(gNB); @@ -547,8 +546,6 @@ int phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx) { for (int i=0;ipucch[i]; if (pucch) { - if (NFAPI_MODE == NFAPI_MODE_PNF) - pucch->frame = frame_rx; if ((pucch->active == 1) && (pucch->frame == frame_rx) && (pucch->slot == slot_rx) ) { @@ -615,9 +612,6 @@ int phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx) { for (harq_pid=0;harq_pidharq_processes[harq_pid]; AssertFatal(ulsch_harq!=NULL,"harq_pid %d is not allocated\n",harq_pid); - //printf("ulsch_harq->frame = %d, frame_rx = %d \n", ulsch_harq->frame, frame_rx); - if (NFAPI_MODE == NFAPI_MODE_PNF) - ulsch_harq->frame = frame_rx; if ((ulsch_harq->status == NR_ACTIVE) && (ulsch_harq->frame == frame_rx) && (ulsch_harq->slot == slot_rx) && diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c index eacf4f54a9..8677b4931b 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c @@ -121,38 +121,32 @@ void clear_nr_nfapi_information(gNB_MAC_INST * gNB, nfapi_nr_tx_data_request_t *TX_req = &gNB->TX_req[0]; gNB->pdu_index[CC_idP] = 0; - if (NFAPI_MODE == NFAPI_MODE_VNF) - { - memset(pdcch, 0, sizeof(**pdcch) * MAX_NUM_BWP * MAX_NUM_CORESET); - } - if (NFAPI_MODE == NFAPI_MONOLITHIC || NFAPI_MODE == NFAPI_MODE_PNF) { // monolithic or PNF - DL_req[CC_idP].SFN = frameP; - DL_req[CC_idP].Slot = slotP; - DL_req[CC_idP].dl_tti_request_body.nPDUs = 0; - DL_req[CC_idP].dl_tti_request_body.nGroup = 0; - //DL_req[CC_idP].dl_tti_request_body.transmission_power_pcfich = 6000; - memset(pdcch, 0, sizeof(**pdcch) * MAX_NUM_BWP * MAX_NUM_CORESET); + DL_req[CC_idP].SFN = frameP; + DL_req[CC_idP].Slot = slotP; + DL_req[CC_idP].dl_tti_request_body.nPDUs = 0; + DL_req[CC_idP].dl_tti_request_body.nGroup = 0; + //DL_req[CC_idP].dl_tti_request_body.transmission_power_pcfich = 6000; + memset(pdcch, 0, sizeof(**pdcch) * MAX_NUM_BWP * MAX_NUM_CORESET); - UL_dci_req[CC_idP].SFN = frameP; - UL_dci_req[CC_idP].Slot = slotP; - UL_dci_req[CC_idP].numPdus = 0; + UL_dci_req[CC_idP].SFN = frameP; + UL_dci_req[CC_idP].Slot = slotP; + UL_dci_req[CC_idP].numPdus = 0; - /* advance last round's future UL_tti_req to be ahead of current frame/slot */ - future_ul_tti_req->SFN = (slotP == 0 ? frameP : frameP + 1) % 1024; - /* future_ul_tti_req->Slot is fixed! */ - future_ul_tti_req->n_pdus = 0; - future_ul_tti_req->n_ulsch = 0; - future_ul_tti_req->n_ulcch = 0; - future_ul_tti_req->n_group = 0; + /* advance last round's future UL_tti_req to be ahead of current frame/slot */ + future_ul_tti_req->SFN = (slotP == 0 ? frameP : frameP + 1) % 1024; + /* future_ul_tti_req->Slot is fixed! */ + future_ul_tti_req->n_pdus = 0; + future_ul_tti_req->n_ulsch = 0; + future_ul_tti_req->n_ulcch = 0; + future_ul_tti_req->n_group = 0; - /* UL_tti_req is a simple pointer into the current UL_tti_req_ahead, i.e., - * it walks over UL_tti_req_ahead in a circular fashion */ - gNB->UL_tti_req[CC_idP] = &gNB->UL_tti_req_ahead[CC_idP][slotP]; + /* UL_tti_req is a simple pointer into the current UL_tti_req_ahead, i.e., + * it walks over UL_tti_req_ahead in a circular fashion */ + gNB->UL_tti_req[CC_idP] = &gNB->UL_tti_req_ahead[CC_idP][slotP]; - TX_req[CC_idP].Number_of_PDUs = 0; + TX_req[CC_idP].Number_of_PDUs = 0; - } } /* void check_nr_ul_failure(module_id_t module_idP, diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c index 46ccc8ac53..d5ae4aa4b3 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c @@ -1141,7 +1141,7 @@ int nr_acknack_scheduling(int mod_id, if(NFAPI_MODE == NFAPI_MODE_VNF){ gNB_MAC_INST *gNB = RC.nrmac[mod_id]; gNB->UL_tti_req_ahead[0][7].SFN = f;//Added to set the UL_tti_req_ahead SFN in VNF mode for slot 7 - gNB->UL_tti_req_ahead[0][8].SFN = f;//Added to set the UL_tti_req_ahead SFN in VNF mode for slot 8 + gNB->[8].SFN = f;//Added to set the UL_tti_req_ahead SFN in VNF mode for slot 8 gNB->UL_tti_req_ahead[0][9].SFN = f;//Added to set the UL_tti_req_ahead SFN in VNF mode for slot 9 gNB->UL_tti_req[0] = &gNB->UL_tti_req_ahead[0][slot]; } diff --git a/openair2/NR_PHY_INTERFACE/NR_IF_Module.c b/openair2/NR_PHY_INTERFACE/NR_IF_Module.c index 1481865128..a789f0c34e 100644 --- a/openair2/NR_PHY_INTERFACE/NR_IF_Module.c +++ b/openair2/NR_PHY_INTERFACE/NR_IF_Module.c @@ -135,7 +135,6 @@ void handle_nr_ulsch(NR_UL_IND_t *UL_info) crc->tb_crc_status); /* if CRC passes, pass PDU, otherwise pass NULL as error indication */ - nr_rx_sdu(UL_info->module_id, UL_info->CC_id, UL_info->rx_ind.sfn, @@ -196,9 +195,8 @@ void NR_UL_indication(NR_UL_IND_t *UL_info) { } handle_nr_rach(UL_info); - + handle_nr_uci(UL_info); - // clear HI prior to handling ULSCH mac->UL_dci_req[CC_id].numPdus = 0; handle_nr_ulsch(UL_info); @@ -215,7 +213,7 @@ void NR_UL_indication(NR_UL_IND_t *UL_info) { gNB_dlsch_ulsch_scheduler(module_id, (UL_info->frame+((UL_info->slot>(spf-1-sl_ahead))?1:0)) % 1024, (UL_info->slot+sl_ahead)%spf); - + ifi->CC_mask = 0; sched_info->module_id = module_id; sched_info->CC_id = CC_id; @@ -239,10 +237,10 @@ void NR_UL_indication(NR_UL_IND_t *UL_info) { ifi->NR_Schedule_response(sched_info); } - LOG_D(PHY,"NR_Schedule_response: SFN_SF:%d%d dl_pdus:%d\n", + LOG_D(PHY,"NR_Schedule_response: SFN_SF:%d%d dl_pdus:%d\n", sched_info->frame, sched_info->slot, - sched_info->DL_req->dl_tti_request_body.nPDUs); + sched_info->DL_req->dl_tti_request_body.nPDUs); } } } From cb0de3ba031923607fb01ad857a0117450d5cb55 Mon Sep 17 00:00:00 2001 From: francescomani Date: Fri, 2 Jul 2021 17:29:23 +0200 Subject: [PATCH 30/91] csi period and offset in mac common --- openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c | 51 ++++++++++++++++++ openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h | 3 ++ .../LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c | 52 ------------------- openair2/LAYER2/NR_MAC_gNB/mac_proto.h | 3 -- 4 files changed, 54 insertions(+), 55 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c index 49598ce44d..4d39d6d352 100644 --- a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c +++ b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c @@ -3240,6 +3240,57 @@ uint16_t get_ssb_start_symbol(const long band, NR_SubcarrierSpacing_t scs, int i } } +void csi_period_offset(const NR_CSI_ReportConfig_t *csirep, + int *period, int *offset) { + + NR_CSI_ReportPeriodicityAndOffset_PR p_and_o = csirep->reportConfigType.choice.periodic->reportSlotConfig.present; + + switch(p_and_o){ + case NR_CSI_ReportPeriodicityAndOffset_PR_slots4: + *period = 4; + *offset = csirep->reportConfigType.choice.periodic->reportSlotConfig.choice.slots4; + break; + case NR_CSI_ReportPeriodicityAndOffset_PR_slots5: + *period = 5; + *offset = csirep->reportConfigType.choice.periodic->reportSlotConfig.choice.slots5; + break; + case NR_CSI_ReportPeriodicityAndOffset_PR_slots8: + *period = 8; + *offset = csirep->reportConfigType.choice.periodic->reportSlotConfig.choice.slots8; + break; + case NR_CSI_ReportPeriodicityAndOffset_PR_slots10: + *period = 10; + *offset = csirep->reportConfigType.choice.periodic->reportSlotConfig.choice.slots10; + break; + case NR_CSI_ReportPeriodicityAndOffset_PR_slots16: + *period = 16; + *offset = csirep->reportConfigType.choice.periodic->reportSlotConfig.choice.slots16; + break; + case NR_CSI_ReportPeriodicityAndOffset_PR_slots20: + *period = 20; + *offset = csirep->reportConfigType.choice.periodic->reportSlotConfig.choice.slots20; + break; + case NR_CSI_ReportPeriodicityAndOffset_PR_slots40: + *period = 40; + *offset = csirep->reportConfigType.choice.periodic->reportSlotConfig.choice.slots40; + break; + case NR_CSI_ReportPeriodicityAndOffset_PR_slots80: + *period = 80; + *offset = csirep->reportConfigType.choice.periodic->reportSlotConfig.choice.slots80; + break; + case NR_CSI_ReportPeriodicityAndOffset_PR_slots160: + *period = 160; + *offset = csirep->reportConfigType.choice.periodic->reportSlotConfig.choice.slots160; + break; + case NR_CSI_ReportPeriodicityAndOffset_PR_slots320: + *period = 320; + *offset = csirep->reportConfigType.choice.periodic->reportSlotConfig.choice.slots320; + break; + default: + AssertFatal(1==0,"No periodicity and offset resource found in CSI report"); + } +} + void get_type0_PDCCH_CSS_config_parameters(NR_Type0_PDCCH_CSS_config_t *type0_PDCCH_CSS_config, frame_t frameP, NR_MIB_t *mib, diff --git a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h index 58c830b1de..9c41704e2a 100644 --- a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h +++ b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h @@ -152,6 +152,9 @@ int16_t get_N_RA_RB (int delta_f_RA_PRACH,int delta_f_PUSCH); void find_period_offest_SR (NR_SchedulingRequestResourceConfig_t *SchedulingReqRec, int *period, int *offset); +void csi_period_offset(const NR_CSI_ReportConfig_t *csirep, + int *period, int *offset); + bool set_dl_ptrs_values(NR_PTRS_DownlinkConfig_t *ptrs_config, uint16_t rbSize, uint8_t mcsIndex, uint8_t mcsTable, uint8_t *K_ptrs, uint8_t *L_ptrs,uint8_t *portIndex, diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c index 371e5a134a..43bcdc1f80 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c @@ -1308,58 +1308,6 @@ int nr_acknack_scheduling(int mod_id, } -void csi_period_offset(const NR_CSI_ReportConfig_t *csirep, - int *period, int *offset) { - - NR_CSI_ReportPeriodicityAndOffset_PR p_and_o = csirep->reportConfigType.choice.periodic->reportSlotConfig.present; - - switch(p_and_o){ - case NR_CSI_ReportPeriodicityAndOffset_PR_slots4: - *period = 4; - *offset = csirep->reportConfigType.choice.periodic->reportSlotConfig.choice.slots4; - break; - case NR_CSI_ReportPeriodicityAndOffset_PR_slots5: - *period = 5; - *offset = csirep->reportConfigType.choice.periodic->reportSlotConfig.choice.slots5; - break; - case NR_CSI_ReportPeriodicityAndOffset_PR_slots8: - *period = 8; - *offset = csirep->reportConfigType.choice.periodic->reportSlotConfig.choice.slots8; - break; - case NR_CSI_ReportPeriodicityAndOffset_PR_slots10: - *period = 10; - *offset = csirep->reportConfigType.choice.periodic->reportSlotConfig.choice.slots10; - break; - case NR_CSI_ReportPeriodicityAndOffset_PR_slots16: - *period = 16; - *offset = csirep->reportConfigType.choice.periodic->reportSlotConfig.choice.slots16; - break; - case NR_CSI_ReportPeriodicityAndOffset_PR_slots20: - *period = 20; - *offset = csirep->reportConfigType.choice.periodic->reportSlotConfig.choice.slots20; - break; - case NR_CSI_ReportPeriodicityAndOffset_PR_slots40: - *period = 40; - *offset = csirep->reportConfigType.choice.periodic->reportSlotConfig.choice.slots40; - break; - case NR_CSI_ReportPeriodicityAndOffset_PR_slots80: - *period = 80; - *offset = csirep->reportConfigType.choice.periodic->reportSlotConfig.choice.slots80; - break; - case NR_CSI_ReportPeriodicityAndOffset_PR_slots160: - *period = 160; - *offset = csirep->reportConfigType.choice.periodic->reportSlotConfig.choice.slots160; - break; - case NR_CSI_ReportPeriodicityAndOffset_PR_slots320: - *period = 320; - *offset = csirep->reportConfigType.choice.periodic->reportSlotConfig.choice.slots320; - break; - default: - AssertFatal(1==0,"No periodicity and offset resource found in CSI report"); - } -} - - void nr_sr_reporting(int Mod_idP, frame_t SFN, sub_frame_t slot) { gNB_MAC_INST *nrmac = RC.nrmac[Mod_idP]; diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h index e0f263e049..ea90319dc1 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h +++ b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h @@ -178,9 +178,6 @@ void nr_schedule_pucch(int Mod_idP, frame_t frameP, sub_frame_t slotP); -void csi_period_offset(const NR_CSI_ReportConfig_t *csirep, - int *period, int *offset); - void nr_csi_meas_reporting(int Mod_idP, frame_t frameP, sub_frame_t slotP); From dc3f61b5c58f7ddad03116b8a5d003c3d6bcd791 Mon Sep 17 00:00:00 2001 From: Mahesh Date: Sun, 4 Jul 2021 21:57:28 +0530 Subject: [PATCH 31/91] Build error fix, sync hardcode, UL indication called in every slot --- nfapi/open-nFAPI/pnf/src/pnf_p7.c | 4 +- nfapi/open-nFAPI/vnf/src/vnf_p7_interface.c | 43 ++++++++++++------- openair1/PHY/NR_TRANSPORT/pucch_rx.c | 4 ++ openair1/SCHED_NR/fapi_nr_l1.c | 2 +- .../LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c | 2 +- 5 files changed, 36 insertions(+), 19 deletions(-) diff --git a/nfapi/open-nFAPI/pnf/src/pnf_p7.c b/nfapi/open-nFAPI/pnf/src/pnf_p7.c index b14e17d576..5c4dfa8c9f 100644 --- a/nfapi/open-nFAPI/pnf/src/pnf_p7.c +++ b/nfapi/open-nFAPI/pnf/src/pnf_p7.c @@ -1561,7 +1561,7 @@ uint8_t is_nr_p7_request_in_window(uint16_t sfn,uint16_t slot, const char* name, // } struct timespec curr_time; clock_gettime(CLOCK_MONOTONIC, &curr_time); - printf("PNF SFN:%d, PNF slot:%d, VNF SFN:%d, VNF slot:%d, Curr time;%d.%d. \n",phy->sfn,phy->slot,sfn,slot,curr_time.tv_sec,curr_time.tv_nsec); + printf("PNF SFN:%d, PNF slot:%d, VNF SFN:%d, VNF slot:%d, SFN offset:%d, Curr time;%d.%d. \n",phy->sfn,phy->slot,sfn,slot, phy->sfn - sfn,curr_time.tv_sec,curr_time.tv_nsec); if(current_sfn_slot_dec <= recv_sfn_slot_dec + timing_window){ in_window = 1; NFAPI_TRACE(NFAPI_TRACE_NOTE, "[%d] %s is in window %d\n", current_sfn_slot_dec, name, recv_sfn_slot_dec); @@ -1578,7 +1578,7 @@ uint8_t is_nr_p7_request_in_window(uint16_t sfn,uint16_t slot, const char* name, }//Need to add more cases - + in_window = 0; // gokul return in_window; } diff --git a/nfapi/open-nFAPI/vnf/src/vnf_p7_interface.c b/nfapi/open-nFAPI/vnf/src/vnf_p7_interface.c index 34318dcbcc..d7e2fa5311 100644 --- a/nfapi/open-nFAPI/vnf/src/vnf_p7_interface.c +++ b/nfapi/open-nFAPI/vnf/src/vnf_p7_interface.c @@ -181,9 +181,11 @@ int nfapi_nr_vnf_p7_start(nfapi_vnf_p7_config_t* config) slot_start = timespec_add(slot_start, slot_duration); NFAPI_TRACE(NFAPI_TRACE_INFO, "next slot will start at %d.%d\n", slot_start.tv_sec, slot_start.tv_nsec); - + struct timespec ref_time; + clock_gettime(CLOCK_MONOTONIC, &ref_time); + uint8_t setup_time; while(vnf_p7->terminate == 0) - { + { fd_set rfds; int maxSock = 0; FD_ZERO(&rfds); @@ -193,6 +195,10 @@ int nfapi_nr_vnf_p7_start(nfapi_vnf_p7_config_t* config) FD_SET(vnf_p7->socket, &rfds); maxSock = vnf_p7->socket; + struct timespec curr_time; + clock_gettime(CLOCK_MONOTONIC, &curr_time); + setup_time = curr_time.tv_sec - ref_time.tv_sec; + clock_gettime(CLOCK_MONOTONIC, &pselect_start); //long millisecond = pselect_start.tv_nsec / 1e6; @@ -404,6 +410,19 @@ struct timespec current_time; clock_gettime(CLOCK_MONOTONIC, ¤t_time); // pselect timed out + if(setup_time > 10){ + // Call the scheduler + struct PHY_VARS_gNB_s *gNB = RC.gNB[0]; + pthread_mutex_lock(&gNB->UL_INFO_mutex); + gNB->UL_INFO.frame = vnf_frame; + gNB->UL_INFO.slot = vnf_slot; + + gNB->UL_INFO.module_id = gNB->Mod_id; + gNB->UL_INFO.CC_id = gNB->CC_id; + gNB->if_inst->NR_UL_indication(&gNB->UL_INFO); + pthread_mutex_unlock(&gNB->UL_INFO_mutex); + } + while(curr != 0) { if (curr->slot == 19) @@ -418,13 +437,16 @@ struct timespec current_time; { curr->slot++; } - //printf("Frame = %d, slot = %d in VNF main loop. \n",curr->sfn,curr->slot); + printf("Frame = %d, slot = %d in VNF main loop. \n",curr->sfn,curr->slot); vnf_frame = curr->sfn; vnf_slot = curr->slot; struct timespec curr_time; clock_gettime(CLOCK_MONOTONIC, &curr_time); - vnf_nr_sync(vnf_p7, curr); + //vnf_nr_sync(vnf_p7, curr); + + (vnf_p7->_public.sync_indication)(&(vnf_p7->_public), 1); //hardcoded sync + curr = curr->next; } send_mac_slot_indications(vnf_p7); @@ -435,19 +457,10 @@ struct timespec current_time; // have a p7 message if(FD_ISSET(vnf_p7->socket, &rfds)) { - + printf("P7 message received \n"); vnf_nr_p7_read_dispatch_message(vnf_p7); - // Call the scheduler - struct PHY_VARS_gNB_s *gNB = RC.gNB[0]; - pthread_mutex_lock(&gNB->UL_INFO_mutex); - gNB->UL_INFO.frame = vnf_frame; - gNB->UL_INFO.slot = vnf_slot; - - gNB->UL_INFO.module_id = gNB->Mod_id; - gNB->UL_INFO.CC_id = gNB->CC_id; - gNB->if_inst->NR_UL_indication(&gNB->UL_INFO); - pthread_mutex_unlock(&gNB->UL_INFO_mutex); + } } else diff --git a/openair1/PHY/NR_TRANSPORT/pucch_rx.c b/openair1/PHY/NR_TRANSPORT/pucch_rx.c index 8145cf893c..27892aa417 100644 --- a/openair1/PHY/NR_TRANSPORT/pucch_rx.c +++ b/openair1/PHY/NR_TRANSPORT/pucch_rx.c @@ -48,6 +48,8 @@ #include "common/utils/LOG/log.h" #include "common/utils/LOG/vcd_signal_dumper.h" +#include "nfapi/oai_integration/vendor_ext.h" + #include "T.h" //#define DEBUG_NR_PUCCH_RX 1 @@ -86,6 +88,8 @@ void nr_fill_pucch(PHY_VARS_gNB *gNB, int frame, int slot, nfapi_nr_pucch_pdu_t *pucch_pdu) { + if (NFAPI_MODE == NFAPI_MODE_PNF) + gNB->pucch[0]->active = 0; int id = nr_find_pucch(pucch_pdu->rnti,frame,slot,gNB); AssertFatal( (id>=0) && (idUL_dci_req; frame_t frame = Sched_INFO->frame; sub_frame_t slot = Sched_INFO->slot; - + //printf("Inside nr_schedule_resp SFN:%d, slot:%d \n",Sched_INFO->frame, Sched_INFO->slot); AssertFatal(RC.gNB!=NULL,"RC.gNB is null\n"); AssertFatal(RC.gNB[Mod_id]!=NULL,"RC.gNB[%d] is null\n",Mod_id); diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c index d5ae4aa4b3..46ccc8ac53 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c @@ -1141,7 +1141,7 @@ int nr_acknack_scheduling(int mod_id, if(NFAPI_MODE == NFAPI_MODE_VNF){ gNB_MAC_INST *gNB = RC.nrmac[mod_id]; gNB->UL_tti_req_ahead[0][7].SFN = f;//Added to set the UL_tti_req_ahead SFN in VNF mode for slot 7 - gNB->[8].SFN = f;//Added to set the UL_tti_req_ahead SFN in VNF mode for slot 8 + gNB->UL_tti_req_ahead[0][8].SFN = f;//Added to set the UL_tti_req_ahead SFN in VNF mode for slot 8 gNB->UL_tti_req_ahead[0][9].SFN = f;//Added to set the UL_tti_req_ahead SFN in VNF mode for slot 9 gNB->UL_tti_req[0] = &gNB->UL_tti_req_ahead[0][slot]; } From b38cc83233e563891f2ea41fe0cd76b5542918b9 Mon Sep 17 00:00:00 2001 From: francescomani Date: Mon, 5 Jul 2021 15:43:05 +0200 Subject: [PATCH 32/91] RSRP tables in mac common --- openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c | 47 ++++++++++++++++ openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h | 3 ++ .../LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c | 53 ++----------------- 3 files changed, 55 insertions(+), 48 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c index 4d39d6d352..11b2c70a3b 100644 --- a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c +++ b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c @@ -36,6 +36,53 @@ #define reserved 0xffff +#define MIN_RSRP_VALUE -141 + +//Measured RSRP Values Table 10.1.16.1-1 from 36.133 +//Stored all the upper limits[Max RSRP Value of corresponding index] +//stored -1 for invalid values +int L1_SSB_CSI_RSRP_measReport_mapping_38133_10_1_6_1_1[128] = { + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, //0 - 9 + -1, -1, -1, -1, -1, -1, -140, -139, -138, -137, //10 - 19 + -136, -135, -134, -133, -132, -131, -130, -129, -128, -127, //20 - 29 + -126, -125, -124, -123, -122, -121, -120, -119, -118, -117, //30 - 39 + -116, -115, -114, -113, -112, -111, -110, -109, -108, -107, //40 - 49 + -106, -105, -104, -103, -102, -101, -100, -99, -98, -97, //50 - 59 + -96, -95, -94, -93, -92, -91, -90, -89, -88, -87, //60 - 69 + -86, -85, -84, -83, -82, -81, -80, -79, -78, -77, //70 - 79 + -76, -75, -74, -73, -72, -71, -70, -69, -68, -67, //80 - 89 + -66, -65, -64, -63, -62, -61, -60, -59, -58, -57, //90 - 99 + -56, -55, -54, -53, -52, -51, -50, -49, -48, -47, //100 - 109 + -46, -45, -44, -44, -1, -1, -1, -1, -1, -1, //110 - 119 + -1, -1, -1, -1, -1, -1, -1, -1//120 - 127 + }; + +//Differential RSRP values Table 10.1.6.1-2 from 36.133 +//Stored the upper limits[MAX RSRP Value] +int diff_rsrp_ssb_csi_meas_10_1_6_1_2[16] = { + 0, -2, -4, -6, -8, -10, -12, -14, -16, -18, //0 - 9 + -20, -22, -24, -26, -28, -30 //10 - 15 +}; + + +//returns the measured RSRP value (upper limit) +int get_measured_rsrp(uint8_t index) { + //if index is invalid returning minimum rsrp -140 + if(index <= 15 || index >= 114) + return MIN_RSRP_VALUE; + + return L1_SSB_CSI_RSRP_measReport_mapping_38133_10_1_6_1_1[index]; +} + +//returns the differential RSRP value (upper limit) +int get_diff_rsrp(uint8_t index, int strongest_rsrp) { + if(strongest_rsrp != -1) { + return strongest_rsrp + diff_rsrp_ssb_csi_meas_10_1_6_1_2[index]; + } else + return MIN_RSRP_VALUE; +} + + // start symbols for SSB types A,B,C,D,E uint16_t symbol_ssb_AC[8]={2,8,16,22,30,36,44,50}; uint16_t symbol_ssb_BD[64]={4,8,16,20,32,36,44,48,60,64,72,76,88,92,100,104,144,148,156,160,172,176,184,188,200,204,212,216,228,232,240,244,284,288, diff --git a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h index 9c41704e2a..f0faca742b 100644 --- a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h +++ b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h @@ -148,6 +148,9 @@ uint16_t compute_pucch_prb_size(uint8_t format, uint8_t n_symb, uint8_t n_re_ctrl); +int get_measured_rsrp(uint8_t index); +int get_diff_rsrp(uint8_t index, int strongest_rsrp); + int16_t get_N_RA_RB (int delta_f_RA_PRACH,int delta_f_PUSCH); void find_period_offest_SR (NR_SchedulingRequestResourceConfig_t *SchedulingReqRec, int *period, int *offset); diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c index 43bcdc1f80..1b3f175599 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c @@ -83,7 +83,6 @@ void nr_fill_nfapi_pucch(module_id_t mod_id, pucch->r_pucch); } -#define MIN_RSRP_VALUE -141 #define MAX_NUM_SSB 128 #define MAX_SSB_SCHED 8 #define L1_RSRP_HYSTERIS 10 //considering 10 dBm as hysterisis for avoiding frequent SSB Beam Switching. !Fixme provide exact value if any @@ -92,32 +91,6 @@ void nr_fill_nfapi_pucch(module_id_t mod_id, int ssb_index_sorted[MAX_NUM_SSB] = {0}; int ssb_rsrp_sorted[MAX_NUM_SSB] = {0}; -//Measured RSRP Values Table 10.1.16.1-1 from 36.133 -//Stored all the upper limits[Max RSRP Value of corresponding index] -//stored -1 for invalid values -int L1_SSB_CSI_RSRP_measReport_mapping_38133_10_1_6_1_1[128] = { - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, //0 - 9 - -1, -1, -1, -1, -1, -1, -140, -139, -138, -137, //10 - 19 - -136, -135, -134, -133, -132, -131, -130, -129, -128, -127, //20 - 29 - -126, -125, -124, -123, -122, -121, -120, -119, -118, -117, //30 - 39 - -116, -115, -114, -113, -112, -111, -110, -109, -108, -107, //40 - 49 - -106, -105, -104, -103, -102, -101, -100, -99, -98, -97, //50 - 59 - -96, -95, -94, -93, -92, -91, -90, -89, -88, -87, //60 - 69 - -86, -85, -84, -83, -82, -81, -80, -79, -78, -77, //70 - 79 - -76, -75, -74, -73, -72, -71, -70, -69, -68, -67, //80 - 89 - -66, -65, -64, -63, -62, -61, -60, -59, -58, -57, //90 - 99 - -56, -55, -54, -53, -52, -51, -50, -49, -48, -47, //100 - 109 - -46, -45, -44, -44, -1, -1, -1, -1, -1, -1, //110 - 119 - -1, -1, -1, -1, -1, -1, -1, -1//120 - 127 - }; - -//Differential RSRP values Table 10.1.6.1-2 from 36.133 -//Stored the upper limits[MAX RSRP Value] -int diff_rsrp_ssb_csi_meas_10_1_6_1_2[16] = { - 0, -2, -4, -6, -8, -10, -12, -14, -16, -18, //0 - 9 - -20, -22, -24, -26, -28, -30 //10 - 15 -}; - void nr_schedule_pucch(int Mod_idP, frame_t frameP, @@ -178,7 +151,7 @@ void compute_csi_bitlen(NR_CSI_MeasConfig_t *csi_MeasConfig, NR_UE_info_t *UE_in for (csi_report_id=0; csi_report_id < csi_MeasConfig->csi_ReportConfigToAddModList->list.count; csi_report_id++){ struct NR_CSI_ReportConfig *csi_reportconfig = csi_MeasConfig->csi_ReportConfigToAddModList->list.array[csi_report_id]; - nr_csi_report_t *csi_report = &UE_info->csi_report_template[UE_id][csi_report_id]; + nr_csi_report_t *csi_report = &UE_info->csi_report_template[UE_id][csi_report_id]; csi_ResourceConfigId=csi_reportconfig->resourcesForChannelMeasurement; reportQuantity_type = csi_reportconfig->reportQuantity.present; csi_report->reportQuantity_type = reportQuantity_type; @@ -188,7 +161,7 @@ void compute_csi_bitlen(NR_CSI_MeasConfig_t *csi_MeasConfig, NR_UE_info_t *UE_in if ( csi_resourceconfig->csi_ResourceConfigId != csi_ResourceConfigId) continue; else { - uint8_t nb_ssb_resources =0; + uint8_t nb_ssb_resources = 0; //Finding the CSI_RS or SSB Resources if (NR_CSI_ReportConfig__reportQuantity_PR_cri_RSRP == reportQuantity_type || NR_CSI_ReportConfig__reportQuantity_PR_ssb_Index_RSRP == reportQuantity_type) { @@ -213,10 +186,10 @@ void compute_csi_bitlen(NR_CSI_MeasConfig_t *csi_MeasConfig, NR_UE_info_t *UE_in *(csi_resourceconfig->csi_RS_ResourceSetList.choice.nzp_CSI_RS_SSB->csi_SSB_ResourceSetList->list.array[0])){ ///We can configure only one SSB resource set from spec 38.331 IE CSI-ResourceConfig - nb_ssb_resources= csi_MeasConfig->csi_SSB_ResourceSetToAddModList->list.array[csi_ssb_idx]->csi_SSB_ResourceList.list.count; + nb_ssb_resources = csi_MeasConfig->csi_SSB_ResourceSetToAddModList->list.array[csi_ssb_idx]->csi_SSB_ResourceList.list.count; csi_report->SSB_Index_list = csi_MeasConfig->csi_SSB_ResourceSetToAddModList->list.array[csi_ssb_idx]->csi_SSB_ResourceList.list.array; csi_report->CSI_Index_list = NULL; - break; + break; } } } else /*if (NR_CSI_ReportConfig__reportQuantity_PR_cri_RSRP == UE_info->csi_report_template[UE_id][csi_report_id].reportQuantity_type)*/{ @@ -225,7 +198,7 @@ void compute_csi_bitlen(NR_CSI_MeasConfig_t *csi_MeasConfig, NR_UE_info_t *UE_in *(csi_resourceconfig->csi_RS_ResourceSetList.choice.nzp_CSI_RS_SSB->nzp_CSI_RS_ResourceSetList->list.array[0])) { ///For periodic and semi-persistent CSI Resource Settings, the number of CSI-RS Resource Sets configured is limited to S=1 for spec 38.212 - nb_ssb_resources= csi_MeasConfig->nzp_CSI_RS_ResourceSetToAddModList->list.array[csi_ssb_idx]->nzp_CSI_RS_Resources.list.count; + nb_ssb_resources = csi_MeasConfig->nzp_CSI_RS_ResourceSetToAddModList->list.array[csi_ssb_idx]->nzp_CSI_RS_Resources.list.count; csi_report->CSI_Index_list = csi_MeasConfig->nzp_CSI_RS_ResourceSetToAddModList->list.array[csi_ssb_idx]->nzp_CSI_RS_Resources.list.array; csi_report->SSB_Index_list = NULL; break; @@ -659,22 +632,6 @@ int checkTargetSSBInTCIStates_pdcchConfig(int ssb_index_t, int Mod_idP, int UE_i return -1; } -//returns the measured RSRP value (upper limit) -int get_measured_rsrp(uint8_t index) { - //if index is invalid returning minimum rsrp -140 - if(index <= 15 || index >= 114) - return MIN_RSRP_VALUE; - - return L1_SSB_CSI_RSRP_measReport_mapping_38133_10_1_6_1_1[index]; -} - -//returns the differential RSRP value (upper limit) -int get_diff_rsrp(uint8_t index, int strongest_rsrp) { - if(strongest_rsrp != -1) { - return strongest_rsrp + diff_rsrp_ssb_csi_meas_10_1_6_1_2[index]; - } else - return MIN_RSRP_VALUE; -} //identifies the target SSB Beam index //keeps the required date for PDCCH and PDSCH TCI state activation/deactivation CE consutruction globally From 19c356ee23fc84fc8282d43874833308a024e2a8 Mon Sep 17 00:00:00 2001 From: francescomani Date: Mon, 5 Jul 2021 18:00:44 +0200 Subject: [PATCH 33/91] first implementation of MAC function for SSB RSRP (to be verified) --- openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c | 11 + openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h | 2 + openair2/LAYER2/NR_MAC_UE/mac_proto.h | 18 ++ openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c | 219 ++++++++++++++++++ openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c | 7 +- .../LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c | 10 - 6 files changed, 254 insertions(+), 13 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c index 11b2c70a3b..625eb34b18 100644 --- a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c +++ b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c @@ -82,6 +82,17 @@ int get_diff_rsrp(uint8_t index, int strongest_rsrp) { return MIN_RSRP_VALUE; } +void reverse_n_bits(uint8_t *value, uint16_t bitlen) { + uint16_t j; + uint8_t i; + for(j = bitlen - 1,i = 0; j > i; j--, i++) { + if(((*value>>j)&1) != ((*value>>i)&1)) { + *value ^= (1<UL_BWP_Id; + NR_PUCCH_Config_t *pucch_Config = NULL; + int csi_bits = 0; + + if(mac->cg && + mac->cg->spCellConfig && + mac->cg->spCellConfig->spCellConfigDedicated && + mac->cg->spCellConfig->spCellConfigDedicated->csi_MeasConfig) { + + NR_CSI_MeasConfig_t *csi_measconfig = mac->cg->spCellConfig->spCellConfigDedicated->csi_MeasConfig->choice.setup; + + for (int csi_report_id = 0; csi_report_id < csi_measconfig->csi_ReportConfigToAddModList->list.count; csi_report_id++){ + const NR_CSI_ReportConfig_t *csirep = csi_measconfig->csi_ReportConfigToAddModList->list.array[csi_report_id]; + + if(csirep->reportConfigType.present == NR_CSI_ReportConfig__reportConfigType_PR_periodic){ + int period, offset; + csi_period_offset(csirep, &period, &offset); + + int scs; + NR_BWP_Uplink_t *ubwp = mac->ULbwp[0]; + NR_BWP_UplinkCommon_t *initialUplinkBWP; + if (mac->scc) initialUplinkBWP = mac->scc->uplinkConfigCommon->initialUplinkBWP; + else initialUplinkBWP = &mac->scc_SIB->uplinkConfigCommon->initialUplinkBWP; + + if (ubwp && + mac->cg->spCellConfig->spCellConfigDedicated->uplinkConfig && + mac->cg->spCellConfig->spCellConfigDedicated->uplinkConfig->initialUplinkBWP) + scs = ubwp->bwp_Common->genericParameters.subcarrierSpacing; + else + scs = initialUplinkBWP->genericParameters.subcarrierSpacing; + + if (bwp_id>0 && + mac->ULbwp[bwp_id-1] && + mac->ULbwp[bwp_id-1]->bwp_Dedicated && + mac->ULbwp[bwp_id-1]->bwp_Dedicated->pucch_Config && + mac->ULbwp[bwp_id-1]->bwp_Dedicated->pucch_Config->choice.setup) { + pucch_Config = mac->ULbwp[bwp_id-1]->bwp_Dedicated->pucch_Config->choice.setup; + } + else if (bwp_id==0 && + mac->cg->spCellConfig->spCellConfigDedicated->uplinkConfig && + mac->cg->spCellConfig->spCellConfigDedicated->uplinkConfig->initialUplinkBWP && + mac->cg->spCellConfig->spCellConfigDedicated->uplinkConfig->initialUplinkBWP->pucch_Config && + mac->cg->spCellConfig->spCellConfigDedicated->uplinkConfig->initialUplinkBWP->pucch_Config->choice.setup) { + pucch_Config = mac->cg->spCellConfig->spCellConfigDedicated->uplinkConfig->initialUplinkBWP->pucch_Config->choice.setup; + } + + const int n_slots_frame = nr_slots_per_frame[scs]; + if (((n_slots_frame*frame + slot - offset)%period) == 0 && pucch_Config) { + + NR_PUCCH_CSI_Resource_t *pucchcsires = csirep->reportConfigType.choice.periodic->pucch_CSI_ResourceList.list.array[0]; + NR_PUCCH_ResourceSet_t *pucchresset = pucch_Config->resourceSetToAddModList->list.array[1]; // set with formats >1 + int n = pucchresset->resourceList.list.count; + + int res_index; + for (res_index = 0; res_index < n; res_index++) { + if (*pucchresset->resourceList.list.array[res_index] == pucchcsires->pucch_Resource) + break; + } + AssertFatal(res_index < n, + "CSI resource not found among PUCCH resources\n"); + + pucch->resource_indicator = pucchcsires->pucch_Resource; + csi_bits = nr_get_csi_payload(mac, pucch, csi_measconfig); + } + } + else + AssertFatal(1==0,"Only periodic CSI reporting is currently implemented\n"); + } + } + + return csi_bits; +} + + +uint8_t nr_get_csi_payload(NR_UE_MAC_INST_t *mac, + PUCCH_sched_t *pucch, + NR_CSI_MeasConfig_t *csi_MeasConfig) { + + int n_csi_bits = 0; + + AssertFatal(csi_MeasConfig->csi_ReportConfigToAddModList->list.count>0,"No CSI Report configuration available\n"); + + for (int csi_report_id=0; csi_report_id < csi_MeasConfig->csi_ReportConfigToAddModList->list.count; csi_report_id++){ + struct NR_CSI_ReportConfig *csi_reportconfig = csi_MeasConfig->csi_ReportConfigToAddModList->list.array[csi_report_id]; + NR_CSI_ResourceConfigId_t csi_ResourceConfigId = csi_reportconfig->resourcesForChannelMeasurement; + switch(csi_reportconfig->reportQuantity.present) { + case NR_CSI_ReportConfig__reportQuantity_PR_none: + break; + case NR_CSI_ReportConfig__reportQuantity_PR_ssb_Index_RSRP: + n_csi_bits +=get_ssb_rsrp_payload(mac,pucch,csi_reportconfig,csi_ResourceConfigId,csi_MeasConfig); + break; + case NR_CSI_ReportConfig__reportQuantity_PR_cri_RSRP: + case NR_CSI_ReportConfig__reportQuantity_PR_cri_RI_PMI_CQI: + case NR_CSI_ReportConfig__reportQuantity_PR_cri_RI_i1: + case NR_CSI_ReportConfig__reportQuantity_PR_cri_RI_i1_CQI: + case NR_CSI_ReportConfig__reportQuantity_PR_cri_RI_CQI: + case NR_CSI_ReportConfig__reportQuantity_PR_cri_RI_LI_PMI_CQI: + AssertFatal(1==0,"Measurement report based on CSI-RS not availalble\n"); + default: + AssertFatal(1==0,"Invalid CSI report quantity type %d\n",csi_reportconfig->reportQuantity.present); + } + } + return (n_csi_bits); +} + + +uint8_t get_ssb_rsrp_payload(NR_UE_MAC_INST_t *mac, + PUCCH_sched_t *pucch, + 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 + int bits = 0; + uint32_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]; + if (csi_resourceconfig->csi_ResourceConfigId == csi_ResourceConfigId) { + + 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; + else + nb_meas = 1; + } else + nb_meas = 2; + + for (int csi_ssb_idx = 0; csi_ssb_idx < csi_MeasConfig->csi_SSB_ResourceSetToAddModList->list.count; csi_ssb_idx++) { + if (csi_MeasConfig->csi_SSB_ResourceSetToAddModList->list.array[csi_ssb_idx]->csi_SSB_ResourceSetId == + *(csi_resourceconfig->csi_RS_ResourceSetList.choice.nzp_CSI_RS_SSB->csi_SSB_ResourceSetList->list.array[0])){ + + ///only one SSB resource set from spec 38.331 IE CSI-ResourceConfig + nb_ssb = csi_MeasConfig->csi_SSB_ResourceSetToAddModList->list.array[csi_ssb_idx]->csi_SSB_ResourceList.list.count; + break; + } + } + + AssertFatal(nb_ssb>0,"No SSB found in the resource set\n"); + int ssbri_bits = ceil(log2(nb_ssb)); + + //TODO measurement of multiple SSBs at PHY and indication to MAC + if(nb_ssb>1) + LOG_E(MAC, "In current implementation only the SSB of synchronization is measured at PHY. This works only for a single SSB scenario\n"); + + int ssb_rsrp[2][nb_meas]; // the array contains index and RSRP of each SSB to be reported (nb_meas highest RSRPs) + + //TODO replace the following 2 lines with a function to order the nb_meas highest SSB RSRPs + ssb_rsrp[0][0] = mac->mib_ssb; + ssb_rsrp[1][0] = mac->ssb_rsrp_dBm; + + uint8_t ssbi; + + if (ssbri_bits > 0) { + ssbi = ssb_rsrp[0][0]; + reverse_n_bits(&ssbi, ssbri_bits); + temp_payload = ssbi; + bits += ssbri_bits; + } + + uint8_t rsrp_idx = get_rsrp_index(ssb_rsrp[1][0]); + reverse_n_bits(&rsrp_idx, 7); + temp_payload |= (rsrp_idx<csi_part1_payload = temp_payload; + return bits; +} + + +// returns index from RSRP +// according to Table 10.1.6.1-1 in 38.133 + +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 +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_downlink_indication_t *dl_info, NR_UL_TIME_ALIGNMENT_t *ul_time_alignment, int pdu_id){ VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SEND_SDU, VCD_FUNCTION_IN); diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c index 116b079fe9..ea6e8e40e1 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c @@ -1842,15 +1842,16 @@ void nr_ue_pucch_scheduler(module_id_t module_idP, frame_t frameP, int slotP, in uint16_t rnti = mac->crnti; //FIXME not sure this is valid for all pucch instances // SR - if(trigger_periodic_scheduling_request(mac, pucch, frameP, slotP)) + if(trigger_periodic_scheduling_request(mac, pucch, frameP, slotP)) { + O_SR = 1; /* sr_payload = 1 means that this is a positive SR, sr_payload = 0 means that it is a negative SR */ pucch->sr_payload = nr_ue_get_SR(module_idP, frameP, slotP); - + } // CSI - + O_CSI = nr_get_csi_measurements(mac, frameP, slotP, pucch); // ACKNACK O_ACK = get_downlink_ack(mac, frameP, slotP, pucch); diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c index 1b3f175599..69f3084cba 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c @@ -820,16 +820,6 @@ void tci_handling(module_id_t Mod_idP, int UE_id, frame_t frame, slot_t slot) { }//is-triggering_beam_switch }//tci handling -void reverse_n_bits(uint8_t *value, uint16_t bitlen) { - uint16_t j; - uint8_t i; - for(j = bitlen - 1,i = 0; j > i; j--, i++) { - if(((*value>>j)&1) != ((*value>>i)&1)) { - *value ^= (1< Date: Mon, 5 Jul 2021 18:05:26 +0200 Subject: [PATCH 34/91] Revert "RSRP tables in mac common" This reverts commit b38cc83233e563891f2ea41fe0cd76b5542918b9. --- openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c | 45 ---------------- openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h | 3 -- .../LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c | 53 +++++++++++++++++-- 3 files changed, 48 insertions(+), 53 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c index 625eb34b18..207d6096ab 100644 --- a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c +++ b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c @@ -36,51 +36,6 @@ #define reserved 0xffff -#define MIN_RSRP_VALUE -141 - -//Measured RSRP Values Table 10.1.16.1-1 from 36.133 -//Stored all the upper limits[Max RSRP Value of corresponding index] -//stored -1 for invalid values -int L1_SSB_CSI_RSRP_measReport_mapping_38133_10_1_6_1_1[128] = { - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, //0 - 9 - -1, -1, -1, -1, -1, -1, -140, -139, -138, -137, //10 - 19 - -136, -135, -134, -133, -132, -131, -130, -129, -128, -127, //20 - 29 - -126, -125, -124, -123, -122, -121, -120, -119, -118, -117, //30 - 39 - -116, -115, -114, -113, -112, -111, -110, -109, -108, -107, //40 - 49 - -106, -105, -104, -103, -102, -101, -100, -99, -98, -97, //50 - 59 - -96, -95, -94, -93, -92, -91, -90, -89, -88, -87, //60 - 69 - -86, -85, -84, -83, -82, -81, -80, -79, -78, -77, //70 - 79 - -76, -75, -74, -73, -72, -71, -70, -69, -68, -67, //80 - 89 - -66, -65, -64, -63, -62, -61, -60, -59, -58, -57, //90 - 99 - -56, -55, -54, -53, -52, -51, -50, -49, -48, -47, //100 - 109 - -46, -45, -44, -44, -1, -1, -1, -1, -1, -1, //110 - 119 - -1, -1, -1, -1, -1, -1, -1, -1//120 - 127 - }; - -//Differential RSRP values Table 10.1.6.1-2 from 36.133 -//Stored the upper limits[MAX RSRP Value] -int diff_rsrp_ssb_csi_meas_10_1_6_1_2[16] = { - 0, -2, -4, -6, -8, -10, -12, -14, -16, -18, //0 - 9 - -20, -22, -24, -26, -28, -30 //10 - 15 -}; - - -//returns the measured RSRP value (upper limit) -int get_measured_rsrp(uint8_t index) { - //if index is invalid returning minimum rsrp -140 - if(index <= 15 || index >= 114) - return MIN_RSRP_VALUE; - - return L1_SSB_CSI_RSRP_measReport_mapping_38133_10_1_6_1_1[index]; -} - -//returns the differential RSRP value (upper limit) -int get_diff_rsrp(uint8_t index, int strongest_rsrp) { - if(strongest_rsrp != -1) { - return strongest_rsrp + diff_rsrp_ssb_csi_meas_10_1_6_1_2[index]; - } else - return MIN_RSRP_VALUE; -} void reverse_n_bits(uint8_t *value, uint16_t bitlen) { uint16_t j; diff --git a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h index ac0c734a69..6747b1fc70 100644 --- a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h +++ b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h @@ -148,9 +148,6 @@ uint16_t compute_pucch_prb_size(uint8_t format, uint8_t n_symb, uint8_t n_re_ctrl); -int get_measured_rsrp(uint8_t index); -int get_diff_rsrp(uint8_t index, int strongest_rsrp); - int16_t get_N_RA_RB (int delta_f_RA_PRACH,int delta_f_PUSCH); void find_period_offest_SR (NR_SchedulingRequestResourceConfig_t *SchedulingReqRec, int *period, int *offset); diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c index 69f3084cba..f0f18aba27 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c @@ -83,6 +83,7 @@ void nr_fill_nfapi_pucch(module_id_t mod_id, pucch->r_pucch); } +#define MIN_RSRP_VALUE -141 #define MAX_NUM_SSB 128 #define MAX_SSB_SCHED 8 #define L1_RSRP_HYSTERIS 10 //considering 10 dBm as hysterisis for avoiding frequent SSB Beam Switching. !Fixme provide exact value if any @@ -91,6 +92,32 @@ void nr_fill_nfapi_pucch(module_id_t mod_id, int ssb_index_sorted[MAX_NUM_SSB] = {0}; int ssb_rsrp_sorted[MAX_NUM_SSB] = {0}; +//Measured RSRP Values Table 10.1.16.1-1 from 36.133 +//Stored all the upper limits[Max RSRP Value of corresponding index] +//stored -1 for invalid values +int L1_SSB_CSI_RSRP_measReport_mapping_38133_10_1_6_1_1[128] = { + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, //0 - 9 + -1, -1, -1, -1, -1, -1, -140, -139, -138, -137, //10 - 19 + -136, -135, -134, -133, -132, -131, -130, -129, -128, -127, //20 - 29 + -126, -125, -124, -123, -122, -121, -120, -119, -118, -117, //30 - 39 + -116, -115, -114, -113, -112, -111, -110, -109, -108, -107, //40 - 49 + -106, -105, -104, -103, -102, -101, -100, -99, -98, -97, //50 - 59 + -96, -95, -94, -93, -92, -91, -90, -89, -88, -87, //60 - 69 + -86, -85, -84, -83, -82, -81, -80, -79, -78, -77, //70 - 79 + -76, -75, -74, -73, -72, -71, -70, -69, -68, -67, //80 - 89 + -66, -65, -64, -63, -62, -61, -60, -59, -58, -57, //90 - 99 + -56, -55, -54, -53, -52, -51, -50, -49, -48, -47, //100 - 109 + -46, -45, -44, -44, -1, -1, -1, -1, -1, -1, //110 - 119 + -1, -1, -1, -1, -1, -1, -1, -1//120 - 127 + }; + +//Differential RSRP values Table 10.1.6.1-2 from 36.133 +//Stored the upper limits[MAX RSRP Value] +int diff_rsrp_ssb_csi_meas_10_1_6_1_2[16] = { + 0, -2, -4, -6, -8, -10, -12, -14, -16, -18, //0 - 9 + -20, -22, -24, -26, -28, -30 //10 - 15 +}; + void nr_schedule_pucch(int Mod_idP, frame_t frameP, @@ -151,7 +178,7 @@ void compute_csi_bitlen(NR_CSI_MeasConfig_t *csi_MeasConfig, NR_UE_info_t *UE_in for (csi_report_id=0; csi_report_id < csi_MeasConfig->csi_ReportConfigToAddModList->list.count; csi_report_id++){ struct NR_CSI_ReportConfig *csi_reportconfig = csi_MeasConfig->csi_ReportConfigToAddModList->list.array[csi_report_id]; - nr_csi_report_t *csi_report = &UE_info->csi_report_template[UE_id][csi_report_id]; + nr_csi_report_t *csi_report = &UE_info->csi_report_template[UE_id][csi_report_id]; csi_ResourceConfigId=csi_reportconfig->resourcesForChannelMeasurement; reportQuantity_type = csi_reportconfig->reportQuantity.present; csi_report->reportQuantity_type = reportQuantity_type; @@ -161,7 +188,7 @@ void compute_csi_bitlen(NR_CSI_MeasConfig_t *csi_MeasConfig, NR_UE_info_t *UE_in if ( csi_resourceconfig->csi_ResourceConfigId != csi_ResourceConfigId) continue; else { - uint8_t nb_ssb_resources = 0; + uint8_t nb_ssb_resources =0; //Finding the CSI_RS or SSB Resources if (NR_CSI_ReportConfig__reportQuantity_PR_cri_RSRP == reportQuantity_type || NR_CSI_ReportConfig__reportQuantity_PR_ssb_Index_RSRP == reportQuantity_type) { @@ -186,10 +213,10 @@ void compute_csi_bitlen(NR_CSI_MeasConfig_t *csi_MeasConfig, NR_UE_info_t *UE_in *(csi_resourceconfig->csi_RS_ResourceSetList.choice.nzp_CSI_RS_SSB->csi_SSB_ResourceSetList->list.array[0])){ ///We can configure only one SSB resource set from spec 38.331 IE CSI-ResourceConfig - nb_ssb_resources = csi_MeasConfig->csi_SSB_ResourceSetToAddModList->list.array[csi_ssb_idx]->csi_SSB_ResourceList.list.count; + nb_ssb_resources= csi_MeasConfig->csi_SSB_ResourceSetToAddModList->list.array[csi_ssb_idx]->csi_SSB_ResourceList.list.count; csi_report->SSB_Index_list = csi_MeasConfig->csi_SSB_ResourceSetToAddModList->list.array[csi_ssb_idx]->csi_SSB_ResourceList.list.array; csi_report->CSI_Index_list = NULL; - break; + break; } } } else /*if (NR_CSI_ReportConfig__reportQuantity_PR_cri_RSRP == UE_info->csi_report_template[UE_id][csi_report_id].reportQuantity_type)*/{ @@ -198,7 +225,7 @@ void compute_csi_bitlen(NR_CSI_MeasConfig_t *csi_MeasConfig, NR_UE_info_t *UE_in *(csi_resourceconfig->csi_RS_ResourceSetList.choice.nzp_CSI_RS_SSB->nzp_CSI_RS_ResourceSetList->list.array[0])) { ///For periodic and semi-persistent CSI Resource Settings, the number of CSI-RS Resource Sets configured is limited to S=1 for spec 38.212 - nb_ssb_resources = csi_MeasConfig->nzp_CSI_RS_ResourceSetToAddModList->list.array[csi_ssb_idx]->nzp_CSI_RS_Resources.list.count; + nb_ssb_resources= csi_MeasConfig->nzp_CSI_RS_ResourceSetToAddModList->list.array[csi_ssb_idx]->nzp_CSI_RS_Resources.list.count; csi_report->CSI_Index_list = csi_MeasConfig->nzp_CSI_RS_ResourceSetToAddModList->list.array[csi_ssb_idx]->nzp_CSI_RS_Resources.list.array; csi_report->SSB_Index_list = NULL; break; @@ -632,6 +659,22 @@ int checkTargetSSBInTCIStates_pdcchConfig(int ssb_index_t, int Mod_idP, int UE_i return -1; } +//returns the measured RSRP value (upper limit) +int get_measured_rsrp(uint8_t index) { + //if index is invalid returning minimum rsrp -140 + if(index <= 15 || index >= 114) + return MIN_RSRP_VALUE; + + return L1_SSB_CSI_RSRP_measReport_mapping_38133_10_1_6_1_1[index]; +} + +//returns the differential RSRP value (upper limit) +int get_diff_rsrp(uint8_t index, int strongest_rsrp) { + if(strongest_rsrp != -1) { + return strongest_rsrp + diff_rsrp_ssb_csi_meas_10_1_6_1_2[index]; + } else + return MIN_RSRP_VALUE; +} //identifies the target SSB Beam index //keeps the required date for PDCCH and PDSCH TCI state activation/deactivation CE consutruction globally From 02f3fecfef5e0da9085390673d080430afa0d87e Mon Sep 17 00:00:00 2001 From: Mahesh Date: Mon, 5 Jul 2021 22:55:35 +0530 Subject: [PATCH 35/91] future_ul_tti hardcoding solved, other hardcodings commented out --- nfapi/nrNFAPI.md | 4 -- openair2/GNB_APP/gnb_app.c | 4 +- openair2/GNB_APP/gnb_config.c | 1 - openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c | 23 +++++++--- .../LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c | 11 +++-- .../LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c | 33 +++++-------- .../LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c | 46 +++++++++---------- 7 files changed, 56 insertions(+), 66 deletions(-) diff --git a/nfapi/nrNFAPI.md b/nfapi/nrNFAPI.md index b78a205e84..9b996bbedf 100644 --- a/nfapi/nrNFAPI.md +++ b/nfapi/nrNFAPI.md @@ -38,7 +38,3 @@ sudo RFSIMULATOR=127.0.0.1 ./nr-uesoftmodem --rfsim --phy-test --rrc_config_path To be updated. -## Notes -* If running for the first time on local branch, run in the following order - VNF then PNF. This is so that necessary files are generated for the UE to run. Stop this run (it's ok if it stops on its own due to an error). From every subsequent run follow the next bullet. -* In order to achieve synchronization between the VNF and PNF, and receive P7 messages within the timing window, the order in which we should run the modules on different terminals is UE->VNF->PNF. -* Currently downlink transmission from gNB to UE is partially functional and we are working on improving this. Uplink P7 messages are disabled and we will work on uplink integration after completing downlink. diff --git a/openair2/GNB_APP/gnb_app.c b/openair2/GNB_APP/gnb_app.c index 66302d056b..da8d75c67b 100644 --- a/openair2/GNB_APP/gnb_app.c +++ b/openair2/GNB_APP/gnb_app.c @@ -218,7 +218,7 @@ void *gNB_app_task(void *args_p) //registered_gnb = 0; __attribute__((unused)) uint32_t register_gnb_pending = gNB_app_register (gnb_id_start, gnb_id_end); } - +if (RC.nb_nr_inst > 0) { if (NODE_IS_CU(RC.nrrrc[0]->node_type)) { if (itti_create_task(TASK_CU_F1, F1AP_CU_task, NULL) < 0) { @@ -240,7 +240,7 @@ void *gNB_app_task(void *args_p) itti_send_msg_to_task (TASK_DU_F1, GNB_MODULE_ID_TO_INSTANCE(0), msg_p); } - +} do { // Wait for a message itti_receive_msg (TASK_GNB_APP, &msg_p); diff --git a/openair2/GNB_APP/gnb_config.c b/openair2/GNB_APP/gnb_config.c index 456d7cd6de..1942c9f934 100644 --- a/openair2/GNB_APP/gnb_config.c +++ b/openair2/GNB_APP/gnb_config.c @@ -1410,7 +1410,6 @@ void NRRCConfig(void) { config_get( GNBSParams,sizeof(GNBSParams)/sizeof(paramdef_t),NULL); RC.nb_nr_inst = GNBSParams[GNB_ACTIVE_GNBS_IDX].numelt; - // Get num MACRLC instances config_getlist( &MACRLCParamList,NULL,0, NULL); diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c index a4c9a14aa3..7d9d55808a 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c @@ -57,6 +57,8 @@ uint16_t nr_pdcch_order_table[6] = { 31, 31, 511, 2047, 2047, 8191 }; +uint8_t first_sched_entry = 1; + void clear_mac_stats(gNB_MAC_INST *gNB) { memset((void*)gNB->UE_info.mac_stats,0,MAX_MOBILES_PER_GNB*sizeof(NR_mac_stats_t)); } @@ -367,6 +369,20 @@ void gNB_dlsch_ulsch_scheduler(module_id_t module_idP, memset(&vrb_map_UL[last_slot * MAX_BWP_SIZE], 0, sizeof(uint16_t) * MAX_BWP_SIZE); clear_nr_nfapi_information(RC.nrmac[module_idP], CC_id, frame, slot); + + //first entry + if (NFAPI_MODE == NFAPI_MODE_VNF){ + if(first_sched_entry == 1) + { + for (int i = 0; iUL_tti_req_ahead[CC_id][i].SFN = frame + 1; + else + gNB->UL_tti_req_ahead[CC_id][i].SFN = frame; + } + first_sched_entry = 0; + } + } } @@ -410,13 +426,6 @@ void gNB_dlsch_ulsch_scheduler(module_id_t module_idP, // This schedules the DCI for Uplink and subsequently PUSCH - if(NFAPI_MODE == NFAPI_MODE_VNF){ - gNB->UL_tti_req_ahead[0][7].SFN = frame;//Added to set the UL_tti_req_ahead SFN in VNF mode for slot 7 - gNB->UL_tti_req_ahead[0][8].SFN = frame;//Added to set the UL_tti_req_ahead SFN in VNF mode for slot 8 - gNB->UL_tti_req_ahead[0][9].SFN = frame;//Added to set the UL_tti_req_ahead SFN in VNF mode for slot 9 - gNB->UL_tti_req[0] = &gNB->UL_tti_req_ahead[0][slot]; - } - nr_schedule_ulsch(module_idP, frame, slot); // This schedules the DCI for Downlink and PDSCH diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c index 7ffd544d10..17b1fc5233 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c @@ -834,8 +834,9 @@ void nr_schedule_ue_spec(module_id_t module_id, int8_t current_harq_pid = sched_pdsch->dl_harq_pid; if (current_harq_pid < 0) { /* PP has not selected a specific HARQ Process, get a new one */ - if (NFAPI_MODE == NFAPI_MODE_VNF) - sched_ctrl->available_dl_harq.head = 0; + // if (NFAPI_MODE == NFAPI_MODE_VNF) + // sched_ctrl->available_dl_harq.head = 0; + remove_front_nr_list(&sched_ctrl->available_dl_harq); current_harq_pid = sched_ctrl->available_dl_harq.head; AssertFatal(current_harq_pid >= 0, "no free HARQ process available for UE %d\n", @@ -852,9 +853,9 @@ void nr_schedule_ue_spec(module_id_t module_id, remove_nr_list(&sched_ctrl->retrans_dl_harq, current_harq_pid); } NR_UE_harq_t *harq = &sched_ctrl->harq_processes[current_harq_pid]; - if (NFAPI_MODE == NFAPI_MODE_VNF) { - harq->is_waiting = false; - } + // if (NFAPI_MODE == NFAPI_MODE_VNF) { + // harq->is_waiting = false; + // } DevAssert(!harq->is_waiting); add_tail_nr_list(&sched_ctrl->feedback_dl_harq, current_harq_pid); NR_sched_pucch_t *pucch = &sched_ctrl->sched_pucch[sched_pdsch->pucch_allocation]; diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c index 11bc09f7b3..93a2d87345 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c @@ -46,10 +46,6 @@ void nr_fill_nfapi_pucch(module_id_t mod_id, nfapi_nr_ul_tti_request_t *future_ul_tti_req = &RC.nrmac[mod_id]->UL_tti_req_ahead[0][pucch->ul_slot]; - if (NFAPI_MODE == NFAPI_MODE_VNF){ - future_ul_tti_req->SFN = pucch->frame; - future_ul_tti_req->Slot = pucch->ul_slot; - } AssertFatal(future_ul_tti_req->SFN == pucch->frame && future_ul_tti_req->Slot == pucch->ul_slot, @@ -64,7 +60,7 @@ void nr_fill_nfapi_pucch(module_id_t mod_id, memset(pucch_pdu, 0, sizeof(nfapi_nr_pucch_pdu_t)); future_ul_tti_req->n_pdus += 1; - LOG_D(MAC, + LOG_I(MAC, "%4d.%2d Scheduling pucch reception in %4d.%2d: bits SR %d, ACK %d, CSI %d on res %d\n", frame, slot, @@ -148,7 +144,7 @@ void nr_schedule_pucch(int Mod_idP, || frameP != curr_pucch->frame || slotP != curr_pucch->ul_slot) continue; - LOG_D(NR_MAC,"Scheduling PUCCH[%d] RX for UE %d in %d.%d O_ack %d\n",i,UE_id,curr_pucch->frame,curr_pucch->ul_slot,O_ack); + LOG_I(NR_MAC,"Scheduling PUCCH[%d] RX for UE %d in %d.%d O_ack %d\n",i,UE_id,curr_pucch->frame,curr_pucch->ul_slot,O_ack); nr_fill_nfapi_pucch(Mod_idP, frameP, slotP, curr_pucch, UE_id); memset(curr_pucch, 0, sizeof(*curr_pucch)); } @@ -519,9 +515,9 @@ void nr_csi_meas_reporting(int Mod_idP, // find free PUCCH that is in order with possibly existing PUCCH // schedulings (other CSI, SR) NR_sched_pucch_t *curr_pucch = &sched_ctrl->sched_pucch[1]; - if(NFAPI_MODE == NFAPI_MODE_VNF){ - curr_pucch->csi_bits = 0; curr_pucch->sr_flag = 0; curr_pucch->dai_c = 0; - } + // if(NFAPI_MODE == NFAPI_MODE_VNF){ + // curr_pucch->csi_bits = 0; curr_pucch->sr_flag = 0; curr_pucch->dai_c = 0; + // } AssertFatal(curr_pucch->csi_bits == 0 && !curr_pucch->sr_flag && curr_pucch->dai_c == 0, @@ -1141,23 +1137,16 @@ int nr_acknack_scheduling(int mod_id, __func__, pucch->csi_bits); /* if the currently allocated PUCCH of this UE is full, allocate it */ - if (NFAPI_MODE == NFAPI_MODE_VNF){ - pucch->sr_flag = 1; - pucch->dai_c = 1; - } + // if (NFAPI_MODE == NFAPI_MODE_VNF){ + // pucch->sr_flag = 1; + // pucch->dai_c = 1; + // } if (pucch->dai_c == 2) { /* advance the UL slot information in PUCCH by one so we won't schedule in * the same slot again */ const int f = pucch->frame; const int s = pucch->ul_slot; - if(NFAPI_MODE == NFAPI_MODE_VNF){ - gNB_MAC_INST *gNB = RC.nrmac[mod_id]; - gNB->UL_tti_req_ahead[0][7].SFN = f;//Added to set the UL_tti_req_ahead SFN in VNF mode for slot 7 - gNB->UL_tti_req_ahead[0][8].SFN = f;//Added to set the UL_tti_req_ahead SFN in VNF mode for slot 8 - gNB->UL_tti_req_ahead[0][9].SFN = f;//Added to set the UL_tti_req_ahead SFN in VNF mode for slot 9 - gNB->UL_tti_req[0] = &gNB->UL_tti_req_ahead[0][slot]; - } nr_fill_nfapi_pucch(mod_id, frame, slot, pucch, UE_id); memset(pucch, 0, sizeof(*pucch)); pucch->frame = s == n_slots_frame - 1 ? (f + 1) % 1024 : f; @@ -1194,8 +1183,8 @@ int nr_acknack_scheduling(int mod_id, get_pdsch_to_harq_feedback(mod_id, UE_id, ss_type, pdsch_to_harq_feedback); /* there is a HARQ. Check whether we can use it for this ACKNACK */ - if(NFAPI_MODE == NFAPI_MODE_VNF) - return 0; + // if(NFAPI_MODE == NFAPI_MODE_VNF) + // return 0; if (pucch->dai_c > 0) { /* this UE already has a PUCCH occasion */ DevAssert(pucch->frame == frame); diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c index 9999581cf1..603f1ae3c7 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c @@ -1326,37 +1326,33 @@ void nr_schedule_ulsch(module_id_t module_id, frame_t frame, sub_frame_t slot) sched_ctrl->SR = false; int8_t harq_id = sched_pusch->ul_harq_pid; - if (NFAPI_MODE == NFAPI_MODE_VNF) - harq_id = 1; - else - { - if (harq_id < 0) { - /* PP has not selected a specific HARQ Process, get a new one */ - harq_id = sched_ctrl->available_ul_harq.head; - // if(NFAPI_MODE == NFAPI_MODE_VNF) - // harq_id = 1; - AssertFatal(harq_id >= 0, - "no free HARQ process available for UE %d\n", - UE_id); - 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); - } + + if (harq_id < 0) { + /* PP has not selected a specific HARQ Process, get a new one */ + harq_id = sched_ctrl->available_ul_harq.head; + // if(NFAPI_MODE == NFAPI_MODE_VNF) + // harq_id = 1; + AssertFatal(harq_id >= 0, + "no free HARQ process available for UE %d\n", + UE_id); + 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); add_tail_nr_list(&sched_ctrl->feedback_ul_harq, harq_id); cur_harq->feedback_slot = sched_pusch->slot; cur_harq->is_waiting = true; - if (NFAPI_MODE == NFAPI_MODE_VNF) - cur_harq->is_waiting = 0; + // if (NFAPI_MODE == NFAPI_MODE_VNF) + // cur_harq->is_waiting = 0; int rnti_types[2] = { NR_RNTI_C, 0 }; From 74a092f73ac2dd6db45850e128eefe65849f34d5 Mon Sep 17 00:00:00 2001 From: Mahesh Date: Tue, 6 Jul 2021 15:59:52 +0530 Subject: [PATCH 36/91] Documentation update, UL transmission --- doc/NFAPI_archi.md | 16 ++ nfapi/oai_integration/nfapi_pnf.c | 3 +- openair2/NR_PHY_INTERFACE/NR_IF_Module.c | 208 +++++++++++++---------- 3 files changed, 137 insertions(+), 90 deletions(-) diff --git a/doc/NFAPI_archi.md b/doc/NFAPI_archi.md index 61c66bd043..6bc906f494 100644 --- a/doc/NFAPI_archi.md +++ b/doc/NFAPI_archi.md @@ -100,14 +100,30 @@ if (Sched_INFO->TX_req->Number_of_PDUs > 0) ``` +```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 + +``` + ## 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. 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). A point to note is 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). Ideally, it should be received within a duration significantly lesser than slot_ahead so that there is adequate time for PHY processing. +```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 oai_slot_ind-->pselect; + slot_inc -- next slot --> pselect +``` diff --git a/nfapi/oai_integration/nfapi_pnf.c b/nfapi/oai_integration/nfapi_pnf.c index ed0bafa300..d1a0ee5941 100644 --- a/nfapi/oai_integration/nfapi_pnf.c +++ b/nfapi/oai_integration/nfapi_pnf.c @@ -1240,9 +1240,8 @@ int pnf_phy_dl_tti_req(gNB_L1_rxtx_proc_t *proc, nfapi_pnf_p7_config_t *pnf_p7, if (dl_tti_pdu_list[i].PDUType == NFAPI_NR_DL_TTI_PDCCH_PDU_TYPE) { nfapi_nr_dl_tti_request_pdu_t *dl_tti_pdu=&dl_tti_pdu_list[i]; memcpy(dl_tti_pdu,&dl_tti_pdu_list[i],sizeof(nfapi_nr_dl_tti_request_pdu_t)); - int SFN=sfn+2; //if(!&dl_tti_pdu->pdcch_pdu) - handle_nfapi_nr_pdcch_pdu(gNB, SFN, slot, &dl_tti_pdu->pdcch_pdu); + handle_nfapi_nr_pdcch_pdu(gNB, sfn, slot, &dl_tti_pdu->pdcch_pdu); //dl_tti_pdu_list[i].pdcch_pdu.pdcch_pdu_rel15.numDlDci++; // ? // NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() pdcch_vars->num_dci:%d\n", __FUNCTION__, pdcch_vars->num_dci); } else if (dl_tti_pdu_list[i].PDUType == NFAPI_NR_DL_TTI_SSB_PDU_TYPE) { diff --git a/openair2/NR_PHY_INTERFACE/NR_IF_Module.c b/openair2/NR_PHY_INTERFACE/NR_IF_Module.c index fa76fd00bc..edc3a7909b 100644 --- a/openair2/NR_PHY_INTERFACE/NR_IF_Module.c +++ b/openair2/NR_PHY_INTERFACE/NR_IF_Module.c @@ -53,53 +53,70 @@ extern uint16_t sf_ahead; extern uint16_t sl_ahead; void handle_nr_rach(NR_UL_IND_t *UL_info) { - - if (UL_info->rach_ind.number_of_pdus>0) { - LOG_D(MAC,"UL_info[Frame %d, Slot %d] Calling initiate_ra_proc RACH:SFN/SLOT:%d/%d\n",UL_info->frame,UL_info->slot, UL_info->rach_ind.sfn,UL_info->rach_ind.slot); - int npdus = UL_info->rach_ind.number_of_pdus; - for(int i = 0; i < npdus; i++) { - UL_info->rach_ind.number_of_pdus--; - if (UL_info->rach_ind.pdu_list[i].num_preamble>0) - AssertFatal(UL_info->rach_ind.pdu_list[i].num_preamble==1, - "More than 1 preamble not supported\n"); - - nr_initiate_ra_proc(UL_info->module_id, - UL_info->CC_id, - UL_info->rach_ind.sfn, - UL_info->rach_ind.slot, - UL_info->rach_ind.pdu_list[i].preamble_list[0].preamble_index, - UL_info->rach_ind.pdu_list[i].freq_index, - UL_info->rach_ind.pdu_list[i].symbol_index, - UL_info->rach_ind.pdu_list[i].preamble_list[0].timing_advance); + if(NFAPI_MODE == NFAPI_MODE_PNF) { + if (UL_info->rach_ind.number_of_pdus>0) { + //LOG_D(PHY,"UL_info->crc_ind.crc_indication_body.number_of_crcs:%d CRC_IND:SFN/SF:%d\n", UL_info->crc_ind.crc_indication_body.number_of_crcs, NFAPI_SFNSF2DEC(UL_info->crc_ind.sfn_sf)); + oai_nfapi_nr_rach_indication(&UL_info->rach_ind); + UL_info->rach_ind.number_of_pdus = 0; + } + } + else{ + if (UL_info->rach_ind.number_of_pdus>0) { + LOG_D(MAC,"UL_info[Frame %d, Slot %d] Calling initiate_ra_proc RACH:SFN/SLOT:%d/%d\n",UL_info->frame,UL_info->slot, UL_info->rach_ind.sfn,UL_info->rach_ind.slot); + int npdus = UL_info->rach_ind.number_of_pdus; + for(int i = 0; i < npdus; i++) { + UL_info->rach_ind.number_of_pdus--; + if (UL_info->rach_ind.pdu_list[i].num_preamble>0) + AssertFatal(UL_info->rach_ind.pdu_list[i].num_preamble==1, + "More than 1 preamble not supported\n"); + + nr_initiate_ra_proc(UL_info->module_id, + UL_info->CC_id, + UL_info->rach_ind.sfn, + UL_info->rach_ind.slot, + UL_info->rach_ind.pdu_list[i].preamble_list[0].preamble_index, + UL_info->rach_ind.pdu_list[i].freq_index, + UL_info->rach_ind.pdu_list[i].symbol_index, + UL_info->rach_ind.pdu_list[i].preamble_list[0].timing_advance); + } } } } void handle_nr_uci(NR_UL_IND_t *UL_info) -{ - const module_id_t mod_id = UL_info->module_id; - const frame_t frame = UL_info->frame; - const sub_frame_t slot = UL_info->slot; - int num_ucis = UL_info->uci_ind.num_ucis; - nfapi_nr_uci_t *uci_list = UL_info->uci_ind.uci_list; +{ + if(NFAPI_MODE == NFAPI_MODE_PNF) { + if (UL_info->uci_ind.num_ucis>0) { + //LOG_D(PHY,"UL_info->crc_ind.crc_indication_body.number_of_crcs:%d CRC_IND:SFN/SF:%d\n", UL_info->crc_ind.crc_indication_body.number_of_crcs, NFAPI_SFNSF2DEC(UL_info->crc_ind.sfn_sf)); + oai_nfapi_nr_uci_indication(&UL_info->uci_ind); + UL_info->uci_ind.num_ucis = 0; + } + } + else{ + const module_id_t mod_id = UL_info->module_id; + const frame_t frame = UL_info->frame; + const sub_frame_t slot = UL_info->slot; + int num_ucis = UL_info->uci_ind.num_ucis; + nfapi_nr_uci_t *uci_list = UL_info->uci_ind.uci_list; - for (int i = 0; i < num_ucis; i++) { - switch (uci_list[i].pdu_type) { - case NFAPI_NR_UCI_PUSCH_PDU_TYPE: - LOG_E(MAC, "%s(): unhandled NFAPI_NR_UCI_PUSCH_PDU_TYPE\n", __func__); - break; + for (int i = 0; i < num_ucis; i++) { + switch (uci_list[i].pdu_type) { + case NFAPI_NR_UCI_PUSCH_PDU_TYPE: + LOG_E(MAC, "%s(): unhandled NFAPI_NR_UCI_PUSCH_PDU_TYPE\n", __func__); + break; - case NFAPI_NR_UCI_FORMAT_0_1_PDU_TYPE: { - const nfapi_nr_uci_pucch_pdu_format_0_1_t *uci_pdu = &uci_list[i].pucch_pdu_format_0_1; - handle_nr_uci_pucch_0_1(mod_id, frame, slot, uci_pdu); - break; - } + case NFAPI_NR_UCI_FORMAT_0_1_PDU_TYPE: { + const nfapi_nr_uci_pucch_pdu_format_0_1_t *uci_pdu = &uci_list[i].pucch_pdu_format_0_1; + handle_nr_uci_pucch_0_1(mod_id, frame, slot, uci_pdu); + break; + } - case NFAPI_NR_UCI_FORMAT_2_3_4_PDU_TYPE: { - const nfapi_nr_uci_pucch_pdu_format_2_3_4_t *uci_pdu = &uci_list[i].pucch_pdu_format_2_3_4; - handle_nr_uci_pucch_2_3_4(mod_id, frame, slot, uci_pdu); - break; + case NFAPI_NR_UCI_FORMAT_2_3_4_PDU_TYPE: { + const nfapi_nr_uci_pucch_pdu_format_2_3_4_t *uci_pdu = &uci_list[i].pucch_pdu_format_2_3_4; + handle_nr_uci_pucch_2_3_4(mod_id, frame, slot, uci_pdu); + break; + } } } } @@ -109,60 +126,75 @@ void handle_nr_uci(NR_UL_IND_t *UL_info) void handle_nr_ulsch(NR_UL_IND_t *UL_info) { - if (UL_info->rx_ind.number_of_pdus > 0 && UL_info->crc_ind.number_crcs > 0) { - for (int i = 0; i < UL_info->rx_ind.number_of_pdus; i++) { - for (int j = 0; j < UL_info->crc_ind.number_crcs; j++) { - // find crc_indication j corresponding rx_indication i - const nfapi_nr_rx_data_pdu_t *rx = &UL_info->rx_ind.pdu_list[i]; - const nfapi_nr_crc_t *crc = &UL_info->crc_ind.crc_list[j]; - LOG_D(PHY, - "UL_info->crc_ind.pdu_list[%d].rnti:%04x " - "UL_info->rx_ind.pdu_list[%d].rnti:%04x\n", - j, - crc->rnti, - i, - rx->rnti); + if(NFAPI_MODE == NFAPI_MODE_PNF) { + if (UL_info->crc_ind.number_crcs>0) { + //LOG_D(PHY,"UL_info->crc_ind.crc_indication_body.number_of_crcs:%d CRC_IND:SFN/SF:%d\n", UL_info->crc_ind.crc_indication_body.number_of_crcs, NFAPI_SFNSF2DEC(UL_info->crc_ind.sfn_sf)); + oai_nfapi_nr_crc_indication(&UL_info->crc_ind); + UL_info->crc_ind.number_crcs = 0; + } - if (crc->rnti != rx->rnti) - continue; + if (UL_info->rx_ind.number_of_pdus>0) { + //LOG_D(PHY,"UL_info->rx_ind.number_of_pdus:%d RX_IND:SFN/SF:%d\n", UL_info->rx_ind.rx_indication_body.number_of_pdus, NFAPI_SFNSF2DEC(UL_info->rx_ind.sfn_sf)); + oai_nfapi_nr_rx_data_indication(&UL_info->rx_ind); + UL_info->rx_ind.number_of_pdus = 0; + } + } + else{ + if (UL_info->rx_ind.number_of_pdus > 0 && UL_info->crc_ind.number_crcs > 0) { + for (int i = 0; i < UL_info->rx_ind.number_of_pdus; i++) { + for (int j = 0; j < UL_info->crc_ind.number_crcs; j++) { + // find crc_indication j corresponding rx_indication i + const nfapi_nr_rx_data_pdu_t *rx = &UL_info->rx_ind.pdu_list[i]; + const nfapi_nr_crc_t *crc = &UL_info->crc_ind.crc_list[j]; + LOG_D(PHY, + "UL_info->crc_ind.pdu_list[%d].rnti:%04x " + "UL_info->rx_ind.pdu_list[%d].rnti:%04x\n", + j, + crc->rnti, + i, + rx->rnti); - LOG_D(MAC, - "%4d.%2d Calling rx_sdu (CRC %s/tb_crc_status %d)\n", - UL_info->frame, - UL_info->slot, - crc->tb_crc_status ? "error" : "ok", - crc->tb_crc_status); + if (crc->rnti != rx->rnti) + continue; - /* if CRC passes, pass PDU, otherwise pass NULL as error indication */ - nr_rx_sdu(UL_info->module_id, - UL_info->CC_id, - UL_info->rx_ind.sfn, - UL_info->rx_ind.slot, - rx->rnti, - crc->tb_crc_status ? NULL : rx->pdu, - rx->pdu_length, - rx->timing_advance, - rx->ul_cqi, - rx->rssi); - handle_nr_ul_harq(UL_info->module_id, UL_info->frame, UL_info->slot, crc); - break; - } // for (j=0;jcrc_ind.number_crcs;j++) - } // for (i=0;irx_ind.number_of_pdus;i++) + LOG_D(MAC, + "%4d.%2d Calling rx_sdu (CRC %s/tb_crc_status %d)\n", + UL_info->frame, + UL_info->slot, + crc->tb_crc_status ? "error" : "ok", + crc->tb_crc_status); - UL_info->crc_ind.number_crcs = 0; - UL_info->rx_ind.number_of_pdus = 0; - } else if (UL_info->rx_ind.number_of_pdus != 0 - || UL_info->crc_ind.number_crcs != 0) { - LOG_E(PHY, - "hoping not to have mis-match between CRC ind and RX ind - " - "hopefully the missing message is coming shortly " - "rx_ind:%d(SFN/SL:%d/%d) crc_ind:%d(SFN/SL:%d/%d) \n", - UL_info->rx_ind.number_of_pdus, - UL_info->rx_ind.sfn, - UL_info->rx_ind.slot, - UL_info->crc_ind.number_crcs, - UL_info->rx_ind.sfn, - UL_info->rx_ind.slot); + /* if CRC passes, pass PDU, otherwise pass NULL as error indication */ + nr_rx_sdu(UL_info->module_id, + UL_info->CC_id, + UL_info->rx_ind.sfn, + UL_info->rx_ind.slot, + rx->rnti, + crc->tb_crc_status ? NULL : rx->pdu, + rx->pdu_length, + rx->timing_advance, + rx->ul_cqi, + rx->rssi); + handle_nr_ul_harq(UL_info->module_id, UL_info->frame, UL_info->slot, crc); + break; + } // for (j=0;jcrc_ind.number_crcs;j++) + } // for (i=0;irx_ind.number_of_pdus;i++) + + UL_info->crc_ind.number_crcs = 0; + UL_info->rx_ind.number_of_pdus = 0; + } else if (UL_info->rx_ind.number_of_pdus != 0 + || UL_info->crc_ind.number_crcs != 0) { + LOG_E(PHY, + "hoping not to have mis-match between CRC ind and RX ind - " + "hopefully the missing message is coming shortly " + "rx_ind:%d(SFN/SL:%d/%d) crc_ind:%d(SFN/SL:%d/%d) \n", + UL_info->rx_ind.number_of_pdus, + UL_info->rx_ind.sfn, + UL_info->rx_ind.slot, + UL_info->crc_ind.number_crcs, + UL_info->rx_ind.sfn, + UL_info->rx_ind.slot); + } } } From b15c39d9f8e06c652cb000fb479c189bdd1a61be Mon Sep 17 00:00:00 2001 From: francescomani Date: Thu, 8 Jul 2021 14:35:18 +0200 Subject: [PATCH 37/91] bugfix in pucch resource selection for csi meas report --- openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c | 9 ++++++--- 1 file changed, 6 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 51b1211ed0..d160f89274 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c @@ -2174,14 +2174,17 @@ uint8_t nr_get_csi_measurements(NR_UE_MAC_INST_t *mac, int n = pucchresset->resourceList.list.count; int res_index; + int found = -1; for (res_index = 0; res_index < n; res_index++) { - if (*pucchresset->resourceList.list.array[res_index] == pucchcsires->pucch_Resource) + if (*pucchresset->resourceList.list.array[res_index] == pucchcsires->pucch_Resource) { + found = res_index; break; + } } - AssertFatal(res_index < n, + AssertFatal(found != -1, "CSI resource not found among PUCCH resources\n"); - pucch->resource_indicator = pucchcsires->pucch_Resource; + pucch->resource_indicator = found; csi_bits = nr_get_csi_payload(mac, pucch, csi_measconfig); } } From 724b0c076bf60b13be7766670747f21d0901be45 Mon Sep 17 00:00:00 2001 From: francescomani Date: Thu, 8 Jul 2021 15:15:22 +0200 Subject: [PATCH 38/91] fix in rsrp table including max and min int for out of range report --- openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c | 2 +- .../LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c | 22 +++++++++---------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c index d160f89274..ec8506697b 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c @@ -2212,7 +2212,7 @@ uint8_t nr_get_csi_payload(NR_UE_MAC_INST_t *mac, case NR_CSI_ReportConfig__reportQuantity_PR_none: break; case NR_CSI_ReportConfig__reportQuantity_PR_ssb_Index_RSRP: - n_csi_bits +=get_ssb_rsrp_payload(mac,pucch,csi_reportconfig,csi_ResourceConfigId,csi_MeasConfig); + n_csi_bits += get_ssb_rsrp_payload(mac,pucch,csi_reportconfig,csi_ResourceConfigId,csi_MeasConfig); break; case NR_CSI_ReportConfig__reportQuantity_PR_cri_RSRP: case NR_CSI_ReportConfig__reportQuantity_PR_cri_RI_PMI_CQI: diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c index f0f18aba27..b7dda3ac63 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c @@ -97,17 +97,17 @@ int ssb_rsrp_sorted[MAX_NUM_SSB] = {0}; //stored -1 for invalid values int L1_SSB_CSI_RSRP_measReport_mapping_38133_10_1_6_1_1[128] = { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, //0 - 9 - -1, -1, -1, -1, -1, -1, -140, -139, -138, -137, //10 - 19 - -136, -135, -134, -133, -132, -131, -130, -129, -128, -127, //20 - 29 - -126, -125, -124, -123, -122, -121, -120, -119, -118, -117, //30 - 39 - -116, -115, -114, -113, -112, -111, -110, -109, -108, -107, //40 - 49 - -106, -105, -104, -103, -102, -101, -100, -99, -98, -97, //50 - 59 - -96, -95, -94, -93, -92, -91, -90, -89, -88, -87, //60 - 69 - -86, -85, -84, -83, -82, -81, -80, -79, -78, -77, //70 - 79 - -76, -75, -74, -73, -72, -71, -70, -69, -68, -67, //80 - 89 - -66, -65, -64, -63, -62, -61, -60, -59, -58, -57, //90 - 99 - -56, -55, -54, -53, -52, -51, -50, -49, -48, -47, //100 - 109 - -46, -45, -44, -44, -1, -1, -1, -1, -1, -1, //110 - 119 + -1, -1, -1, -1, -1, -1, INT_MIN, -140, -139, -138, //10 - 19 + -137, -136, -135, -134, -133, -132, -131, -130, -129, -128, //20 - 29 + -127, -126, -125, -124, -123, -122, -121, -120, -119, -118, //30 - 39 + -117,-116, -115, -114, -113, -112, -111, -110, -109, -108, //40 - 49 + -107, -106, -105, -104, -103, -102, -101, -100, -99, -98, //50 - 59 + -97, -96, -95, -94, -93, -92, -91, -90, -89, -88, //60 - 69 + -87, -86, -85, -84, -83, -82, -81, -80, -79, -78, //70 - 79 + -77, -76, -75, -74, -73, -72, -71, -70, -69, -68, //80 - 89 + -67, -66, -65, -64, -63, -62, -61, -60, -59, -58, //90 - 99 + -57, -56, -55, -54, -53, -52, -51, -50, -49, -48, //100 - 109 + -47, -46, -45, -44, INT_MAX, -1, -1, -1, -1, -1, //110 - 119 -1, -1, -1, -1, -1, -1, -1, -1//120 - 127 }; From 3228ebf3f6b14580bb1de47024955f40c822968c Mon Sep 17 00:00:00 2001 From: francescomani Date: Sat, 10 Jul 2021 11:26:56 +0200 Subject: [PATCH 39/91] using pdsch_pdu for sib1 indication --- .../nfapi/public_inc/fapi_nr_ue_interface.h | 7 -- openair1/SCHED_NR_UE/phy_procedures_nr_ue.c | 2 +- openair2/LAYER2/NR_MAC_UE/mac_proto.h | 10 +-- openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c | 10 ++- openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c | 65 ++++++++----------- openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.h | 2 +- 6 files changed, 41 insertions(+), 55 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 809d90191a..e1bb2579eb 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 @@ -117,18 +117,11 @@ typedef struct { short rsrp_dBm; } fapi_nr_ssb_pdu_t; -typedef struct { - uint32_t pdu_length; - uint8_t* pdu; - uint32_t sibs_mask; -} fapi_nr_sib_pdu_t; - typedef struct { uint8_t pdu_type; union { fapi_nr_pdsch_pdu_t pdsch_pdu; fapi_nr_ssb_pdu_t ssb_pdu; - fapi_nr_sib_pdu_t sib_pdu; }; } fapi_nr_rx_indication_body_t; diff --git a/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c b/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c index 83e439956c..cec1df4f88 100644 --- a/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c +++ b/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c @@ -1165,7 +1165,7 @@ void nr_ue_dlsch_procedures(PHY_VARS_NR_UE *ue, // send to mac if (ue->if_inst && ue->if_inst->dl_indication) { ue->if_inst->dl_indication(&dl_indication, ul_time_alignment); - } + } if (ue->mac_enabled == 1) { diff --git a/openair2/LAYER2/NR_MAC_UE/mac_proto.h b/openair2/LAYER2/NR_MAC_UE/mac_proto.h index 24b97d1403..dac62cf9a6 100755 --- a/openair2/LAYER2/NR_MAC_UE/mac_proto.h +++ b/openair2/LAYER2/NR_MAC_UE/mac_proto.h @@ -68,11 +68,11 @@ int8_t nr_ue_decode_mib( \param pduP pointer to pdu \param pdu_length length of pdu */ int8_t nr_ue_decode_BCCH_DL_SCH(module_id_t module_id, - int cc_id, - unsigned int gNB_index, - uint32_t sibs_mask, - uint8_t *pduP, - uint32_t pdu_len); + int cc_id, + unsigned int gNB_index, + uint8_t ack_nack, + uint8_t *pduP, + uint32_t pdu_len); /**\brief primitive from RRC layer to MAC layer for configuration L1/L2, now supported 4 rrc messages: MIB, cell_group_config for MAC/PHY, spcell_config(serving cell config) \param module_id module id diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c index ec8506697b..a2cfd4bb25 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c @@ -254,11 +254,15 @@ int8_t nr_ue_decode_mib(module_id_t module_id, int8_t nr_ue_decode_BCCH_DL_SCH(module_id_t module_id, int cc_id, unsigned int gNB_index, - uint32_t sibs_mask, + uint8_t ack_nack, uint8_t *pduP, uint32_t pdu_len) { - LOG_D(NR_MAC, "Decoding NR-BCCH-DL-SCH-Message (SIB1 or SI)\n"); - nr_mac_rrc_data_ind_ue(module_id, cc_id, gNB_index, 0, 0, 0, NR_BCCH_DL_SCH, (uint8_t *) pduP, pdu_len); + if(ack_nack) { + LOG_D(NR_MAC, "Decoding NR-BCCH-DL-SCH-Message (SIB1 or SI)\n"); + nr_mac_rrc_data_ind_ue(module_id, cc_id, gNB_index, 0, 0, 0, NR_BCCH_DL_SCH, (uint8_t *) pduP, pdu_len); + } + else + LOG_E(NR_MAC, "Got NACK on NR-BCCH-DL-SCH-Message (SIB1 or SI)\n"); return 0; } diff --git a/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c b/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c index 59dce6fd12..435d7e8d30 100644 --- a/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c +++ b/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c @@ -66,8 +66,8 @@ int handle_bcch_bch(module_id_t module_id, int cc_id, } // L2 Abstraction Layer -int handle_bcch_dlsch(module_id_t module_id, int cc_id, unsigned int gNB_index, uint32_t sibs_mask, uint8_t *pduP, uint32_t pdu_len){ - return nr_ue_decode_BCCH_DL_SCH(module_id, cc_id, gNB_index, sibs_mask, pduP, pdu_len); +int handle_bcch_dlsch(module_id_t module_id, int cc_id, unsigned int gNB_index, uint8_t ack_nack, uint8_t *pduP, uint32_t pdu_len){ + return nr_ue_decode_BCCH_DL_SCH(module_id, cc_id, gNB_index, ack_nack, pduP, pdu_len); } // L2 Abstraction Layer @@ -170,43 +170,32 @@ int nr_ue_dl_indication(nr_downlink_indication_t *dl_info, NR_UL_TIME_ALIGNMENT_ dl_info->rx_ind->number_pdus); switch(dl_info->rx_ind->rx_indication_body[i].pdu_type){ + case FAPI_NR_RX_PDU_TYPE_SSB: + mac->ssb_rsrp_dBm = (dl_info->rx_ind->rx_indication_body+i)->ssb_pdu.rsrp_dBm; + ret_mask |= (handle_bcch_bch(dl_info->module_id, dl_info->cc_id, dl_info->gNB_index, + (dl_info->rx_ind->rx_indication_body+i)->ssb_pdu.pdu, + (dl_info->rx_ind->rx_indication_body+i)->ssb_pdu.additional_bits, + (dl_info->rx_ind->rx_indication_body+i)->ssb_pdu.ssb_index, + (dl_info->rx_ind->rx_indication_body+i)->ssb_pdu.ssb_length, + (dl_info->rx_ind->rx_indication_body+i)->ssb_pdu.ssb_start_subcarrier, + (dl_info->rx_ind->rx_indication_body+i)->ssb_pdu.cell_id)) << FAPI_NR_RX_PDU_TYPE_SSB; - case FAPI_NR_RX_PDU_TYPE_SSB: - mac->ssb_rsrp_dBm = (dl_info->rx_ind->rx_indication_body+i)->ssb_pdu.rsrp_dBm; - ret_mask |= (handle_bcch_bch(dl_info->module_id, dl_info->cc_id, dl_info->gNB_index, - (dl_info->rx_ind->rx_indication_body+i)->ssb_pdu.pdu, - (dl_info->rx_ind->rx_indication_body+i)->ssb_pdu.additional_bits, - (dl_info->rx_ind->rx_indication_body+i)->ssb_pdu.ssb_index, - (dl_info->rx_ind->rx_indication_body+i)->ssb_pdu.ssb_length, - (dl_info->rx_ind->rx_indication_body+i)->ssb_pdu.ssb_start_subcarrier, - (dl_info->rx_ind->rx_indication_body+i)->ssb_pdu.cell_id)) << FAPI_NR_RX_PDU_TYPE_SSB; - - break; - - case FAPI_NR_RX_PDU_TYPE_SIB: - - ret_mask |= (handle_bcch_dlsch(dl_info->module_id, - dl_info->cc_id, dl_info->gNB_index, - (dl_info->rx_ind->rx_indication_body+i)->sib_pdu.sibs_mask, - (dl_info->rx_ind->rx_indication_body+i)->sib_pdu.pdu, - (dl_info->rx_ind->rx_indication_body+i)->sib_pdu.pdu_length)) << FAPI_NR_RX_PDU_TYPE_SIB; - - break; - - case FAPI_NR_RX_PDU_TYPE_DLSCH: - - ret_mask |= (handle_dlsch(dl_info, ul_time_alignment, i)) << FAPI_NR_RX_PDU_TYPE_DLSCH; - - break; - - case FAPI_NR_RX_PDU_TYPE_RAR: - - ret_mask |= (handle_dlsch(dl_info, ul_time_alignment, i)) << FAPI_NR_RX_PDU_TYPE_RAR; - - break; - - default: - break; + break; + case FAPI_NR_RX_PDU_TYPE_SIB: + ret_mask |= (handle_bcch_dlsch(dl_info->module_id, + dl_info->cc_id, dl_info->gNB_index, + (dl_info->rx_ind->rx_indication_body+i)->pdsch_pdu.ack_nack, + (dl_info->rx_ind->rx_indication_body+i)->pdsch_pdu.pdu, + (dl_info->rx_ind->rx_indication_body+i)->pdsch_pdu.pdu_length)) << FAPI_NR_RX_PDU_TYPE_SIB; + break; + case FAPI_NR_RX_PDU_TYPE_DLSCH: + ret_mask |= (handle_dlsch(dl_info, ul_time_alignment, i)) << FAPI_NR_RX_PDU_TYPE_DLSCH; + break; + case FAPI_NR_RX_PDU_TYPE_RAR: + ret_mask |= (handle_dlsch(dl_info, ul_time_alignment, i)) << FAPI_NR_RX_PDU_TYPE_RAR; + break; + default: + break; } } } diff --git a/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.h b/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.h index 1ab9954344..1ba8238f1e 100755 --- a/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.h +++ b/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.h @@ -244,7 +244,7 @@ int handle_bcch_bch(module_id_t module_id, /**\brief handle BCCH-DL-SCH message from dl_indication \param pdu_len length(bytes) of pdu \param pduP pointer to pdu*/ -int handle_bcch_dlsch(module_id_t module_id, int cc_id, unsigned int gNB_index, uint32_t sibs_mask, uint8_t *pduP, uint32_t pdu_len); +int handle_bcch_dlsch(module_id_t module_id, int cc_id, unsigned int gNB_index, uint8_t ack_nack, uint8_t *pduP, uint32_t pdu_len); int handle_dci(module_id_t module_id, int cc_id, unsigned int gNB_index, frame_t frame, int slot, fapi_nr_dci_indication_pdu_t *dci); From 8981f5cbd7295b9b9c61ba499004aa56f4664129 Mon Sep 17 00:00:00 2001 From: francescomani Date: Sat, 10 Jul 2021 11:41:38 +0200 Subject: [PATCH 40/91] fix in pucch ue scheduler for pucch_Config = NULL --- openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c index ea6e8e40e1..58956bff47 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c @@ -1857,7 +1857,8 @@ void nr_ue_pucch_scheduler(module_id_t module_idP, frame_t frameP, int slotP, in O_ACK = get_downlink_ack(mac, frameP, slotP, pucch); NR_BWP_Id_t bwp_id = mac->UL_BWP_Id; - NR_PUCCH_Config_t *pucch_Config; + NR_PUCCH_Config_t *pucch_Config = NULL; + if (bwp_id>0 && mac->ULbwp[bwp_id-1] && mac->ULbwp[bwp_id-1]->bwp_Dedicated && @@ -1875,11 +1876,10 @@ void nr_ue_pucch_scheduler(module_id_t module_idP, frame_t frameP, int slotP, in mac->cg->spCellConfig->spCellConfigDedicated->uplinkConfig->initialUplinkBWP->pucch_Config->choice.setup) { pucch_Config = mac->cg->spCellConfig->spCellConfigDedicated->uplinkConfig->initialUplinkBWP->pucch_Config->choice.setup; } - else AssertFatal(1==0,"no pucch_Config\n"); // if multiplexing of HARQ and CSI is not possible, transmit only HARQ bits - if ((O_ACK != 0) && (O_ACK != 0) && (pucch_Config->format2->choice.setup->simultaneousHARQ_ACK_CSI == NULL)) { + if ((O_ACK != 0) && (O_ACK != 0) && pucch_Config && (pucch_Config->format2->choice.setup->simultaneousHARQ_ACK_CSI == NULL)) { O_CSI = 0; pucch->csi_part1_payload = 0; pucch->csi_part2_payload = 0; From 5055023dae658f7f2ccd4121ca8e7634dc0e6a08 Mon Sep 17 00:00:00 2001 From: francescomani Date: Sat, 10 Jul 2021 12:17:46 +0200 Subject: [PATCH 41/91] fix in activation of pucch_vars --- openair1/SCHED_NR_UE/fapi_nr_ue_l1.c | 1 + openair1/SCHED_NR_UE/pucch_uci_ue_nr.c | 3 +++ 2 files changed, 4 insertions(+) diff --git a/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c b/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c index bb54c0027c..8cbf91e93b 100644 --- a/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c +++ b/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c @@ -204,6 +204,7 @@ int8_t nr_ue_scheduled_response(nr_scheduled_response_t *scheduled_response){ memcpy((void*)&(pucch_vars->pucch_pdu[j]), (void*)pucch_config_pdu, sizeof(fapi_nr_ul_config_pucch_pdu)); pucch_vars->active[j] = true; found = true; + break; } } if (!found) diff --git a/openair1/SCHED_NR_UE/pucch_uci_ue_nr.c b/openair1/SCHED_NR_UE/pucch_uci_ue_nr.c index df1cbad3ca..88ea3a2524 100644 --- a/openair1/SCHED_NR_UE/pucch_uci_ue_nr.c +++ b/openair1/SCHED_NR_UE/pucch_uci_ue_nr.c @@ -321,6 +321,7 @@ void pucch_procedures_ue_nr(PHY_VARS_NR_UE *ue, for (int i=0; i<2; i++) { if(pucch_vars->active[i]) { + pucch_pdu = &pucch_vars->pucch_pdu[i]; uint16_t nb_of_prbs = pucch_pdu->prb_size; /* Generate PUCCH signal according to its format and parameters */ @@ -350,6 +351,8 @@ void pucch_procedures_ue_nr(PHY_VARS_NR_UE *ue, tx_amp = AMP; #endif + LOG_D(PHY,"Generation of PUCCH format %d at frame.slot %d.%d\n",pucch_pdu->format_type,proc->frame_tx,nr_slot_tx); + switch(pucch_pdu->format_type) { case 0: nr_generate_pucch0(ue, From 8ad3b40cd5995087c0e36c1401b9b432b3f96b0c Mon Sep 17 00:00:00 2001 From: francescomani Date: Mon, 12 Jul 2021 11:53:35 +0200 Subject: [PATCH 42/91] fixes in pucch configuration for SA --- openair1/PHY/NR_UE_TRANSPORT/pucch_nr.c | 3 +++ openair1/SCHED_NR_UE/phy_procedures_nr_ue.c | 2 +- openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c | 28 +++++++++++++++++++- openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c | 5 +++- 4 files changed, 35 insertions(+), 3 deletions(-) diff --git a/openair1/PHY/NR_UE_TRANSPORT/pucch_nr.c b/openair1/PHY/NR_UE_TRANSPORT/pucch_nr.c index f3dfa698d0..61bca6f409 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/pucch_nr.c +++ b/openair1/PHY/NR_UE_TRANSPORT/pucch_nr.c @@ -91,6 +91,9 @@ void nr_generate_pucch0(PHY_VARS_NR_UE *ue, // the value of u,v (delta always 0 for PUCCH) has to be calculated according to TS 38.211 Subclause 6.3.2.2.1 uint8_t u[2]={0,0},v[2]={0,0}; + LOG_D(PHY,"pucch0: nr_symbols %d, start_symbol %d, prb_start %d, second_hop_prb %d, group_hop_flag %d, sequence_hop_flag %d, mcs %d\n",pucch_pdu->nr_of_symbols,pucch_pdu->start_symbol_index,pucch_pdu->prb_start,pucch_pdu->second_hop_prb,pucch_pdu->group_hop_flag,pucch_pdu->sequence_hop_flag,pucch_pdu->mcs); + + #ifdef DEBUG_NR_PUCCH_TX printf("\t [nr_generate_pucch0] sequence generation: variable initialization for test\n"); #endif diff --git a/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c b/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c index cec1df4f88..8b6ec13592 100644 --- a/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c +++ b/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c @@ -1053,7 +1053,7 @@ void nr_ue_dlsch_procedures(PHY_VARS_NR_UE *ue, break; } - LOG_D(PHY, "In %s DL PDU length in bits: %d, in bytes: %d \n", __FUNCTION__, dlsch0->harq_processes[harq_pid]->TBS, dlsch0->harq_processes[harq_pid]->TBS / 8); + LOG_D(PHY, "In %s DL PDU length in bits: %d, in bytes: %d \n", __FUNCTION__, dlsch0->harq_processes[harq_pid]->TBS, dlsch0->harq_processes[harq_pid]->TBS / 8); diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c index a2cfd4bb25..95aa1c662f 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c @@ -1310,6 +1310,27 @@ void nr_ue_configure_pucch(NR_UE_MAC_INST_t *mac, } pucch_pdu->freq_hop_flag = 1; pucch_pdu->time_domain_occ_idx = 0; + + if (O_SR == 0 || pucch->sr_payload == 0) { /* only ack is transmitted TS 36.213 9.2.3 UE procedure for reporting HARQ-ACK */ + if (O_ACK == 1) + pucch_pdu->mcs = sequence_cyclic_shift_1_harq_ack_bit[pucch->ack_payload & 0x1]; /* only harq of 1 bit */ + else + pucch_pdu->mcs = sequence_cyclic_shift_2_harq_ack_bits[pucch->ack_payload & 0x3]; /* only harq with 2 bits */ + } + else { /* SR + eventually ack are transmitted TS 36.213 9.2.5.1 UE procedure for multiplexing HARQ-ACK or CSI and SR */ + if (pucch->sr_payload == 1) { /* positive scheduling request */ + if (O_ACK == 1) + pucch_pdu->mcs = sequence_cyclic_shift_1_harq_ack_bit_positive_sr[pucch->ack_payload & 0x1]; /* positive SR and harq of 1 bit */ + else if (O_ACK == 2) + pucch_pdu->mcs = sequence_cyclic_shift_2_harq_ack_bits_positive_sr[pucch->ack_payload & 0x3]; /* positive SR and harq with 2 bits */ + else + pucch_pdu->mcs = 0; /* only positive SR */ + } + } + + // TODO verify if SR can be transmitted in this mode + pucch_pdu->payload = (pucch->sr_payload << O_ACK) | pucch->ack_payload; + } else if (pucch->pucch_resource != NULL) { @@ -1522,6 +1543,10 @@ int16_t get_pucch_tx_power_ue(NR_UE_MAC_INST_t *mac, else P_O_NOMINAL_PUCCH = *mac->scc_SIB->uplinkConfigCommon->initialUplinkBWP.pucch_ConfigCommon->choice.setup->p0_nominal; struct NR_PUCCH_PowerControl *power_config = pucch_Config->pucch_PowerControl; + + if (!power_config) + return (PUCCH_POWER_DEFAULT); + int16_t P_O_UE_PUCCH; int16_t G_b_f_c = 0; @@ -1730,7 +1755,7 @@ void select_pucch_resource(NR_UE_MAC_INST_t *mac, NR_BWP_Id_t bwp_id = mac->UL_BWP_Id; int n_list; - if ((bwp_id ==0 && + if ((bwp_id == 0 && mac->cg == NULL) || (bwp_id == 0 && mac->cg && @@ -2033,6 +2058,7 @@ uint8_t get_downlink_ack(NR_UE_MAC_INST_t *mac, } pucch->ack_payload = o_ACK; + return(number_harq_feedback); } diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c index 58956bff47..4472dfea8e 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c @@ -1879,7 +1879,10 @@ void nr_ue_pucch_scheduler(module_id_t module_idP, frame_t frameP, int slotP, in // if multiplexing of HARQ and CSI is not possible, transmit only HARQ bits - if ((O_ACK != 0) && (O_ACK != 0) && pucch_Config && (pucch_Config->format2->choice.setup->simultaneousHARQ_ACK_CSI == NULL)) { + if ((O_ACK != 0) && (O_CSI != 0) && + pucch_Config && + pucch_Config->format2 && + (pucch_Config->format2->choice.setup->simultaneousHARQ_ACK_CSI == NULL)) { O_CSI = 0; pucch->csi_part1_payload = 0; pucch->csi_part2_payload = 0; From 58063acf5400e931a7d2d2d0b77ce969ae56ce8a Mon Sep 17 00:00:00 2001 From: francescomani Date: Mon, 12 Jul 2021 16:30:29 +0200 Subject: [PATCH 43/91] rx_gain = 0 in rfsimulator --- executables/nr-ue.c | 5 +- executables/nr-uesoftmodem.c | 3 +- .../NR_UE_TRANSPORT/nr_transport_proto_ue.h | 12 +++-- .../PHY/NR_UE_TRANSPORT/nr_ue_rf_helpers.c | 49 +++++++++++++------ targets/ARCH/rfsimulator/simulator.c | 1 + 5 files changed, 47 insertions(+), 23 deletions(-) diff --git a/executables/nr-ue.c b/executables/nr-ue.c index 10a9ca317b..82b11f9b7f 100644 --- a/executables/nr-ue.c +++ b/executables/nr-ue.c @@ -220,7 +220,6 @@ static void UE_synch(void *arg) { LOG_I(PHY, "[UE thread Synch] Running Initial Synch (mode %d)\n",UE->mode); uint64_t dl_carrier, ul_carrier; - double rx_gain_off = 0; nr_get_carrier_frequencies(&UE->frame_parms, &dl_carrier, &ul_carrier); if (nr_initial_sync(&syncD->proc, UE, 2) == 0) { @@ -230,7 +229,7 @@ static void UE_synch(void *arg) { // rerun with new cell parameters and frequency-offset // todo: the freq_offset computed on DL shall be scaled before being applied to UL - nr_rf_card_config(&openair0_cfg[UE->rf_map.card], rx_gain_off, ul_carrier, dl_carrier, freq_offset); + nr_rf_card_config_freq(&openair0_cfg[UE->rf_map.card], ul_carrier, dl_carrier, freq_offset); LOG_I(PHY,"Got synch: hw_slot_offset %d, carrier off %d Hz, rxgain %f (DL %f Hz, UL %f Hz)\n", hw_slot_offset, @@ -264,7 +263,7 @@ static void UE_synch(void *arg) { freq_offset *= -1; - nr_rf_card_config(&openair0_cfg[UE->rf_map.card], rx_gain_off, ul_carrier, dl_carrier, freq_offset); + nr_rf_card_config_freq(&openair0_cfg[UE->rf_map.card], ul_carrier, dl_carrier, freq_offset); LOG_I(PHY, "Initial sync failed: trying carrier off %d Hz\n", freq_offset); diff --git a/executables/nr-uesoftmodem.c b/executables/nr-uesoftmodem.c index cbc79912a2..010251d134 100644 --- a/executables/nr-uesoftmodem.c +++ b/executables/nr-uesoftmodem.c @@ -376,7 +376,8 @@ void init_openair0(void) { nr_get_carrier_frequencies(frame_parms, &dl_carrier, &ul_carrier); - nr_rf_card_config(&openair0_cfg[card], rx_gain_off, ul_carrier, dl_carrier, freq_off); + nr_rf_card_config_freq(&openair0_cfg[card], ul_carrier, dl_carrier, freq_off); + nr_rf_card_config_gain(&openair0_cfg[card], rx_gain_off); openair0_cfg[card].configFilename = get_softmodem_params()->rf_config_file; 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 1e7e10def7..6453e42986 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h @@ -1477,11 +1477,13 @@ void nr_get_carrier_frequencies(NR_DL_FRAME_PARMS *fp, @param dl_Carrier DL carrier to be set @param freq_offset Freq offset to be set */ -void nr_rf_card_config(openair0_config_t *openair0_cfg, - double rx_gain_off, - uint64_t ul_Carrier, - uint64_t dl_Carrier, - int freq_offset); +void nr_rf_card_config_gain(openair0_config_t *openair0_cfg, + double rx_gain_off); + +void nr_rf_card_config_freq(openair0_config_t *openair0_cfg, + uint64_t ul_Carrier, + uint64_t dl_Carrier, + int freq_offset); void print_CQI(void *o,UCI_format_t uci_format,uint8_t eNB_id,int N_RB_DL); diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_ue_rf_helpers.c b/openair1/PHY/NR_UE_TRANSPORT/nr_ue_rf_helpers.c index 6cf782d9d8..29cccdcf88 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_ue_rf_helpers.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_ue_rf_helpers.c @@ -48,11 +48,9 @@ void nr_get_carrier_frequencies(NR_DL_FRAME_PARMS *fp, uint64_t *dl_carrier, uin } -void nr_rf_card_config(openair0_config_t *openair0_cfg, - double rx_gain_offset, - uint64_t ul_carrier, - uint64_t dl_carrier, - int freq_offset){ + +void nr_rf_card_config_gain(openair0_config_t *openair0_cfg, + double rx_gain_off){ uint8_t mod_id = 0; uint8_t cc_id = 0; @@ -61,6 +59,36 @@ void nr_rf_card_config(openair0_config_t *openair0_cfg, double rx_gain = ue->rx_total_gain_dB; double tx_gain = ue->tx_total_gain_dB; + for (int i = rf_chain; i < rf_chain + 4; i++) { + + if (tx_gain) + openair0_cfg->tx_gain[i] = tx_gain; + if (rx_gain) + openair0_cfg->rx_gain[i] = rx_gain - rx_gain_off; + + openair0_cfg->autocal[i] = 1; + + if (i < openair0_cfg->rx_num_channels) { + LOG_I(PHY, "HW: Configuring channel %d (rf_chain %d): setting tx_gain %f, rx_gain %f\n", + i, + rf_chain, + openair0_cfg->tx_gain[i], + openair0_cfg->rx_gain[i]); + } + + } +} + +void nr_rf_card_config_freq(openair0_config_t *openair0_cfg, + uint64_t ul_carrier, + uint64_t dl_carrier, + int freq_offset){ + + uint8_t mod_id = 0; + uint8_t cc_id = 0; + PHY_VARS_NR_UE *ue = PHY_vars_UE_g[mod_id][cc_id]; + int rf_chain = ue->rf_map.chain; + for (int i = rf_chain; i < rf_chain + 4; i++) { if (i < openair0_cfg->rx_num_channels) @@ -73,22 +101,15 @@ void nr_rf_card_config(openair0_config_t *openair0_cfg, else openair0_cfg->tx_freq[i] = 0.0; - if (tx_gain) - openair0_cfg->tx_gain[i] = tx_gain; - if (rx_gain) - openair0_cfg->rx_gain[i] = rx_gain - rx_gain_offset; - openair0_cfg->autocal[i] = 1; if (i < openair0_cfg->rx_num_channels) { - LOG_I(PHY, "HW: Configuring channel %d (rf_chain %d): setting tx_gain %f, rx_gain %f, tx_freq %f Hz, rx_freq %f Hz\n", + LOG_I(PHY, "HW: Configuring channel %d (rf_chain %d): setting tx_freq %f Hz, rx_freq %f Hz\n", i, rf_chain, - openair0_cfg->tx_gain[i], - openair0_cfg->rx_gain[i], openair0_cfg->tx_freq[i], openair0_cfg->rx_freq[i]); } } -} \ No newline at end of file +} diff --git a/targets/ARCH/rfsimulator/simulator.c b/targets/ARCH/rfsimulator/simulator.c index 3bd4285cff..40badb54a6 100644 --- a/targets/ARCH/rfsimulator/simulator.c +++ b/targets/ARCH/rfsimulator/simulator.c @@ -805,6 +805,7 @@ int device_init(openair0_device *device, openair0_config_t *openair0_cfg) { 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->priv = rfsimulator; device->trx_write_init = rfsimulator_write_init; From d9d4e807437b2adf1f10aa93dd1a05d090ce9f81 Mon Sep 17 00:00:00 2001 From: francescomani Date: Tue, 13 Jul 2021 09:38:21 +0200 Subject: [PATCH 44/91] adding missing parameter in pucchsim --- openair1/SIMULATION/NR_PHY/pucchsim.c | 1 + 1 file changed, 1 insertion(+) diff --git a/openair1/SIMULATION/NR_PHY/pucchsim.c b/openair1/SIMULATION/NR_PHY/pucchsim.c index b3a6f112e7..a3eb4452d7 100644 --- a/openair1/SIMULATION/NR_PHY/pucchsim.c +++ b/openair1/SIMULATION/NR_PHY/pucchsim.c @@ -504,6 +504,7 @@ int main(int argc, char **argv) pucch_tx_pdu.start_symbol_index = startingSymbolIndex; pucch_tx_pdu.bwp_start = 0; pucch_tx_pdu.prb_start = startingPRB; + pucch_tx_pdu.prb_size = nrofPRB; pucch_tx_pdu.hopping_id = hopping_id; pucch_tx_pdu.group_hop_flag = 0; pucch_tx_pdu.sequence_hop_flag = 0; From 78da8436243a6f2cf6c263cdaddd3384fbc7a182 Mon Sep 17 00:00:00 2001 From: Laurent OpenCells Date: Fri, 16 Jul 2021 17:16:15 +0200 Subject: [PATCH 45/91] code-cleanup-20210716 --- common/config/config_userapi.c | 7 +- executables/nr-softmodem-common.h | 3 - executables/nr-uesoftmodem.c | 2 - openair1/PHY/NR_TRANSPORT/nr_pbch.c | 4 +- .../PHY/NR_TRANSPORT/nr_transport_proto.h | 13 -- .../PHY/NR_UE_TRANSPORT/nr_initial_sync.c | 2 - openair1/PHY/NR_UE_TRANSPORT/nr_pbch.c | 4 +- openair1/PHY/defs_nr_UE.h | 2 - openair1/SCHED_NR/nr_prach_procedures.c | 3 - .../SIMULATION/ETH_TRANSPORT/emu_transport.c | 1 - openair1/SIMULATION/ETH_TRANSPORT/extern.h | 1 - openair1/SIMULATION/ETH_TRANSPORT/vars.h | 1 - openair1/SIMULATION/NR_PHY/dlsim.c | 1 - openair1/SIMULATION/NR_PHY/ulsim.c | 1 - openair1/SIMULATION/TOOLS/corr_mat.m | 4 +- openair1/SIMULATION/TOOLS/random_channel.c | 101 ++++++--------- openair1/SIMULATION/TOOLS/scm_corrmat.h | 6 +- openair2/LAYER2/MAC/config.c | 2 +- openair2/LAYER2/MAC/config_ue.c | 1 + openair2/LAYER2/MAC/eNB_scheduler.c | 5 +- openair2/LAYER2/MAC/mac_extern.h | 1 - openair2/LAYER2/MAC/main_ue.c | 3 +- openair2/LAYER2/MAC/rar_tools.c | 1 - openair2/LAYER2/NR_MAC_COMMON/nr_mac_extern.h | 1 - .../PDCP_v10.1.0/pdcp_control_primitive.c | 1 - openair2/LAYER2/openair2_proc.c | 4 +- openair2/MCE_APP/mce_app.c | 1 - openair2/RRC/LTE/rrc_eNB.c | 2 - openair2/RRC/LTE/rrc_extern.h | 1 - openair2/RRC/NR/nr_rrc_extern.h | 1 - openair2/UTIL/TRACE/fifo_printf.c | 117 ------------------ openair2/UTIL/TRACE/fifo_printf.h | 37 ------ .../UTIL/TRACE/fifo_printf_proto_extern.h | 41 ------ openair2/UTIL/TRACE/print.h | 32 ----- openair3/MME_APP/mme_app.c | 1 - .../ETHERNET/USERSPACE/LIB/ethernet_lib.c | 1 - 36 files changed, 61 insertions(+), 348 deletions(-) delete mode 100644 openair2/UTIL/TRACE/fifo_printf.c delete mode 100644 openair2/UTIL/TRACE/fifo_printf.h delete mode 100644 openair2/UTIL/TRACE/fifo_printf_proto_extern.h delete mode 100644 openair2/UTIL/TRACE/print.h diff --git a/common/config/config_userapi.c b/common/config/config_userapi.c index af70cae71e..462299b893 100644 --- a/common/config/config_userapi.c +++ b/common/config/config_userapi.c @@ -83,9 +83,14 @@ char *config_check_valptr(paramdef_t *cfgoptions, char **ptr, int length) { } if (*ptr == NULL) { - *ptr = malloc(length>40?length:40); // LTS: dummy fix, waiting Francois full fix in 4G branch // the issue is we don't know at this point the size we will get + // for parmeters on the command line, + // The length sould probably managed, in a later version + // 100 is a very large value for a string parameter of today OAI + if (length<100) + length=100; + *ptr = malloc(length); if ( *ptr != NULL) { memset(*ptr,0,length); diff --git a/executables/nr-softmodem-common.h b/executables/nr-softmodem-common.h index 813ffcf8fa..e37a5f3208 100644 --- a/executables/nr-softmodem-common.h +++ b/executables/nr-softmodem-common.h @@ -154,7 +154,4 @@ extern int emulate_rf; extern int numerology; extern int usrp_tx_thread; -extern volatile int start_eNB; -extern volatile int start_UE; - #endif diff --git a/executables/nr-uesoftmodem.c b/executables/nr-uesoftmodem.c index cbc79912a2..b16bc6d9c3 100644 --- a/executables/nr-uesoftmodem.c +++ b/executables/nr-uesoftmodem.c @@ -107,8 +107,6 @@ int config_sync_var=-1; RAN_CONTEXT_t RC; -volatile int start_eNB = 0; -volatile int start_UE = 0; volatile int oai_exit = 0; diff --git a/openair1/PHY/NR_TRANSPORT/nr_pbch.c b/openair1/PHY/NR_TRANSPORT/nr_pbch.c index 0bc04e3047..a4cec432de 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_pbch.c +++ b/openair1/PHY/NR_TRANSPORT/nr_pbch.c @@ -42,7 +42,7 @@ extern short nr_qpsk_mod_table[8]; -uint8_t nr_pbch_payload_interleaving_pattern[32] = {16, 23, 18, 17, 8, 30, 10, 6, 24, 7, 0, 5, 3, 2, 1, 4, +const uint8_t nr_pbch_payload_interleaving_pattern[32] = {16, 23, 18, 17, 8, 30, 10, 6, 24, 7, 0, 5, 3, 2, 1, 4, 9, 11, 12, 13, 14, 15, 19, 20, 21, 22, 25, 26, 27, 28, 29, 31 }; @@ -141,7 +141,7 @@ int nr_generate_pbch_dmrs(uint32_t *gold_pbch_dmrs, return 0; } -void nr_pbch_scrambling(NR_gNB_PBCH *pbch, +static void nr_pbch_scrambling(NR_gNB_PBCH *pbch, uint32_t Nid, uint8_t nushift, uint16_t M, diff --git a/openair1/PHY/NR_TRANSPORT/nr_transport_proto.h b/openair1/PHY/NR_TRANSPORT/nr_transport_proto.h index 994ff18bc8..667d112157 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_transport_proto.h +++ b/openair1/PHY/NR_TRANSPORT/nr_transport_proto.h @@ -78,19 +78,6 @@ int nr_generate_pbch_dmrs(uint32_t *gold_pbch_dmrs, nfapi_nr_config_request_scf_t *config, NR_DL_FRAME_PARMS *frame_parms); -/*! -\fn int nr_pbch_scrambling -\brief PBCH scrambling function -@param - */ -void nr_pbch_scrambling(NR_gNB_PBCH *pbch, - uint32_t Nid, - uint8_t nushift, - uint16_t M, - uint16_t length, - uint8_t encoded, - uint32_t unscrambling_mask); - /*! \fn int nr_generate_pbch \brief Generation of the PBCH diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync.c b/openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync.c index df35f14869..e216b70872 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync.c @@ -375,8 +375,6 @@ int nr_initial_sync(UE_nr_rxtx_proc_t *proc, PHY_VARS_NR_UE *ue, int n_frames) #endif //#endif - ue->is_synchronized_on_frame = is; // to notify on which of the two frames sync was successful - if (ue->UE_scan_carrier == 0) { #if UE_AUTOTEST_TRACE diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_pbch.c b/openair1/PHY/NR_UE_TRANSPORT/nr_pbch.c index f0e6e9984b..7e5a80b3ff 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_pbch.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_pbch.c @@ -332,7 +332,7 @@ void nr_pbch_detection_mrc(NR_DL_FRAME_PARMS *frame_parms, #endif } -void nr_pbch_unscrambling(NR_UE_PBCH *pbch, +static void nr_pbch_unscrambling(NR_UE_PBCH *pbch, uint16_t Nid, uint8_t nushift, uint16_t M, @@ -555,7 +555,7 @@ int nr_rx_pbch( PHY_VARS_NR_UE *ue, nr_ue_pbch_vars->pbch_a_prime = a_reversed; //payload un-scrambling - memset(&nr_ue_pbch_vars->pbch_a_interleaved, 0, sizeof(uint32_t) ); + nr_ue_pbch_vars->pbch_a_interleaved=0; M = (Lmax == 64)? (NR_POLAR_PBCH_PAYLOAD_BITS - 6) : (NR_POLAR_PBCH_PAYLOAD_BITS - 3); nushift = ((nr_ue_pbch_vars->pbch_a_prime>>24)&1) ^ (((nr_ue_pbch_vars->pbch_a_prime>>6)&1)<<1); nr_pbch_unscrambling(nr_ue_pbch_vars,frame_parms->Nid_cell,nushift,M,NR_POLAR_PBCH_PAYLOAD_BITS,1,unscrambling_mask); diff --git a/openair1/PHY/defs_nr_UE.h b/openair1/PHY/defs_nr_UE.h index e3c0737838..cd51f8bbef 100644 --- a/openair1/PHY/defs_nr_UE.h +++ b/openair1/PHY/defs_nr_UE.h @@ -761,8 +761,6 @@ typedef struct { int UE_fo_compensation; /// \brief Indicator that UE is synchronized to a gNB int is_synchronized; - /// \brief Indicates on which frame is synchronized in a two frame synchronization - int is_synchronized_on_frame; /// \brief Indicator that UE lost frame synchronization int lost_sync; /// Data structure for UE process scheduling diff --git a/openair1/SCHED_NR/nr_prach_procedures.c b/openair1/SCHED_NR/nr_prach_procedures.c index c95d3dc937..838f45aad5 100644 --- a/openair1/SCHED_NR/nr_prach_procedures.c +++ b/openair1/SCHED_NR/nr_prach_procedures.c @@ -49,9 +49,6 @@ extern uint8_t nfapi_mode; -extern int oai_nfapi_nr_rach_ind(nfapi_rach_indication_t *rach_ind); - - void L1_nr_prach_procedures(PHY_VARS_gNB *gNB,int frame,int slot) { uint16_t max_preamble[4]={0},max_preamble_energy[4]={0},max_preamble_delay[4]={0}; diff --git a/openair1/SIMULATION/ETH_TRANSPORT/emu_transport.c b/openair1/SIMULATION/ETH_TRANSPORT/emu_transport.c index f71a8ee117..03fbfeffe0 100644 --- a/openair1/SIMULATION/ETH_TRANSPORT/emu_transport.c +++ b/openair1/SIMULATION/ETH_TRANSPORT/emu_transport.c @@ -231,7 +231,6 @@ void clear_UE_transport_info(uint8_t nb_UE) for (UE_id=0; UE_idR_sqrt[i] = (struct complex*) calloc(nb_tx*nb_rx*nb_tx*nb_rx,sizeof(struct complex)); //chan_desc->R_sqrt = (struct complex*)&R_sqrt[i][0]; /* all chan_desc share the same R_sqrt, coming from caller */ - chan_desc->R_sqrt[i] = R_sqrt[0]; + chan_desc->R_sqrt[i] = R_sqrt; } } @@ -177,13 +177,13 @@ void fill_channel_desc(channel_desc_t *chan_desc, reset_meas(&chan_desc->convolution); } -double mbsfn_delays[] = {0,.03,.15,.31,.37,1.09,12.490,12.52,12.64,12.80,12.86,13.58,27.49,27.52,27.64,27.80,27.86,28.58}; -double mbsfn_amps_dB[] = {0,-1.5,-1.4,-3.6,-0.6,-7.0,-10,-11.5,-11.4,-13.6,-10.6,-17.0,-20,-21.5,-21.4,-23.6,-20.6,-27}; +static double mbsfn_delays[] = {0,.03,.15,.31,.37,1.09,12.490,12.52,12.64,12.80,12.86,13.58,27.49,27.52,27.64,27.80,27.86,28.58}; +static double mbsfn_amps_dB[] = {0,-1.5,-1.4,-3.6,-0.6,-7.0,-10,-11.5,-11.4,-13.6,-10.6,-17.0,-20,-21.5,-21.4,-23.6,-20.6,-27}; -double scm_c_delays[] = {0, 0.0125, 0.0250, 0.3625, 0.3750, 0.3875, 0.2500, 0.2625, 0.2750, 1.0375, 1.0500, 1.0625, 2.7250, 2.7375, 2.7500, 4.6000, 4.6125, 4.6250}; -double scm_c_amps_dB[] = {0.00, -2.22, -3.98, -1.86, -4.08, -5.84, -1.08, -3.30, -5.06, -9.08, -11.30, -13.06, -15.14, -17.36, -19.12, -20.64, -22.85, -24.62}; +static double scm_c_delays[] = {0, 0.0125, 0.0250, 0.3625, 0.3750, 0.3875, 0.2500, 0.2625, 0.2750, 1.0375, 1.0500, 1.0625, 2.7250, 2.7375, 2.7500, 4.6000, 4.6125, 4.6250}; +static double scm_c_amps_dB[] = {0.00, -2.22, -3.98, -1.86, -4.08, -5.84, -1.08, -3.30, -5.06, -9.08, -11.30, -13.06, -15.14, -17.36, -19.12, -20.64, -22.85, -24.62}; -double tdl_a_delays[] = {0.0000, +static double tdl_a_delays[] = {0.0000, 0.3819, 0.4025, 0.5868, @@ -207,7 +207,7 @@ double tdl_a_delays[] = {0.0000, 5.3043, 9.6586 }; -double tdl_a_amps_dB[] = {-13.4, +static double tdl_a_amps_dB[] = {-13.4, 0, -2.2, -4, @@ -232,7 +232,7 @@ double tdl_a_amps_dB[] = {-13.4, -29.7 }; -double tdl_b_delays[] = {0.0000, +static double tdl_b_delays[] = {0.0000, 0.1072, 0.2155, 0.2095, @@ -257,7 +257,7 @@ double tdl_b_delays[] = {0.0000, 4.7834 }; -double tdl_b_amps_dB[] = {0, +static double tdl_b_amps_dB[] = {0, -2.2, -4, -3.2, @@ -282,7 +282,7 @@ double tdl_b_amps_dB[] = {0, -11.3 }; -double tdl_c_delays[] = {0, +static double tdl_c_delays[] = {0, 0.2099, 0.2219, 0.2329, @@ -308,7 +308,7 @@ double tdl_c_delays[] = {0, 8.6523 }; -double tdl_c_amps_dB[] = {-4.4, +static double tdl_c_amps_dB[] = {-4.4, -1.2, -3.5, -5.2, @@ -334,7 +334,7 @@ double tdl_c_amps_dB[] = {-4.4, -22.8 }; -double tdl_d_delays[] = {//0, +static double tdl_d_delays[] = {//0, 0, 0.035, 0.612, @@ -350,7 +350,7 @@ double tdl_d_delays[] = {//0, 12.525 }; -double tdl_d_amps_dB[] = {//-0.2, +static double tdl_d_amps_dB[] = {//-0.2, //-13.5, -.00147, -18.8, @@ -369,7 +369,7 @@ double tdl_d_amps_dB[] = {//-0.2, #define TDL_D_RICEAN_FACTOR .046774 -double tdl_e_delays[] = {0, +static double tdl_e_delays[] = {0, 0.5133, 0.5440, 0.5630, @@ -385,7 +385,7 @@ double tdl_e_delays[] = {0, 20.6519 }; -double tdl_e_amps_dB[] = {//-0.03, +static double tdl_e_amps_dB[] = {//-0.03, //-22.03, -.00433, -15.8, @@ -405,102 +405,78 @@ double tdl_e_amps_dB[] = {//-0.03, #define TDL_E_RICEAN_FACTOR 0.0063096 -double epa_delays[] = { 0,.03,.07,.09,.11,.19,.41}; -double epa_amps_dB[] = {0.0,-1.0,-2.0,-3.0,-8.0,-17.2,-20.8}; +static double epa_delays[] = { 0,.03,.07,.09,.11,.19,.41}; +static double epa_amps_dB[] = {0.0,-1.0,-2.0,-3.0,-8.0,-17.2,-20.8}; -double eva_delays[] = { 0,.03,.15,.31,.37,.71,1.09,1.73,2.51}; -double eva_amps_dB[] = {0.0,-1.5,-1.4,-3.6,-0.6,-9.1,-7.0,-12.0,-16.9}; +static double eva_delays[] = { 0,.03,.15,.31,.37,.71,1.09,1.73,2.51}; +static double eva_amps_dB[] = {0.0,-1.5,-1.4,-3.6,-0.6,-9.1,-7.0,-12.0,-16.9}; -double etu_delays[] = { 0,.05,.12,.2,.23,.5,1.6,2.3,5.0}; -double etu_amps_dB[] = {-1.0,-1.0,-1.0,0.0,0.0,0.0,-3.0,-5.0,-7.0}; +static double etu_delays[] = { 0,.05,.12,.2,.23,.5,1.6,2.3,5.0}; +static double etu_amps_dB[] = {-1.0,-1.0,-1.0,0.0,0.0,0.0,-3.0,-5.0,-7.0}; -double default_amps_lin[] = {0.3868472, 0.3094778, 0.1547389, 0.0773694, 0.0386847, 0.0193424, 0.0096712, 0.0038685}; -double default_amp_lin[] = {1}; - -double ts_shift_delays[] = {0, 1/7.68}; -double ts_shift_amps[] = {0, 1}; +static double default_amps_lin[] = {0.3868472, 0.3094778, 0.1547389, 0.0773694, 0.0386847, 0.0193424, 0.0096712, 0.0038685}; +static double default_amp_lin[] = {1}; //correlation matrix for a 2x2 channel with full Tx correlation -struct complex R_sqrt_22_corr_tap[16] = {{0.70711,0}, {0.0, 0.0}, {0.70711,0}, {0.0, 0.0}, +static struct complex R_sqrt_22_corr[16] = {{0.70711,0}, {0.0, 0.0}, {0.70711,0}, {0.0, 0.0}, {0.0, 0.0}, {0.70711,0}, {0.0, 0.0}, {0.70711,0}, {0.70711,0}, {0.0, 0.0}, {0.70711,0}, {0.0, 0.0}, {0.0, 0.0}, {0.70711,0}, {0.0, 0.0}, {0.70711,0} }; -struct complex *R_sqrt_22_corr[1] = {R_sqrt_22_corr_tap}; //correlation matrix for a fully correlated 2x1 channel (h1==h2) -struct complex R_sqrt_21_corr_tap[4] = {{0.70711,0}, {0.70711,0}, {0.70711,0}, {0.70711,0}}; -struct complex *R_sqrt_21_corr[1] = {R_sqrt_21_corr_tap}; +static struct complex R_sqrt_21_corr[] = {{0.70711,0}, {0.70711,0}, {0.70711,0}, {0.70711,0}}; //correlation matrix for a 2x2 channel with full Tx anti-correlation -struct complex R_sqrt_22_anticorr_tap[16] = {{0.70711,0}, {0.0, 0.0}, {-0.70711,0}, {0.0, 0.0}, +static struct complex R_sqrt_22_anticorr[16] = {{0.70711,0}, {0.0, 0.0}, {-0.70711,0}, {0.0, 0.0}, {0.0, 0.0}, {0.70711,0}, {0.0, 0.0}, {-0.70711,0}, {-0.70711,0}, {0.0, 0.0}, {0.70711,0}, {0.0, 0.0}, {0.0, 0.0}, {-0.70711,0}, {0.0, 0.0}, {0.70711,0} }; -struct complex *R_sqrt_22_anticorr[1] = {R_sqrt_22_anticorr_tap}; //correlation matrix for a fully anti-correlated 2x1 channel (h1==-h2) -struct complex R_sqrt_21_anticorr_tap[4] = {{0.70711,0}, {-0.70711,0}, {-0.70711,0}, {0.70711,0}}; -struct complex *R_sqrt_21_anticorr[1] = {R_sqrt_21_anticorr_tap}; - -struct complex **R_sqrt_ptr2; +static struct complex R_sqrt_21_anticorr[4] = {{0.70711,0}, {-0.70711,0}, {-0.70711,0}, {0.70711,0}}; // full correlation matrix in vectorized form for 2x2 channel, where h1 is perfectly orthogonal to h2 -struct complex R_sqrt_22_orthogonal_tap[16] = {{0.70711,0.0}, {0.0, 0.0}, {0.0,0.0}, {0.0, 0.0}, +static struct complex R_sqrt_22_orthogonal[16] = {{0.70711,0.0}, {0.0, 0.0}, {0.0,0.0}, {0.0, 0.0}, {0.0, 0.0}, {0.0,0.0}, {0.0, 0.0}, {0.0,0.0}, {0.0,0.0}, {0.0, 0.0}, {0.0,0.0}, {0.0, 0.0}, {0.0, 0.0}, {0.0,0.0}, {0.0, 0.0}, {0.70711,0.0} }; -struct complex *R_sqrt_22_orthogonal[1] = {R_sqrt_22_orthogonal_tap}; // full correlation matrix for TM4 to make orthogonal effective channel - - - - -struct complex R_sqrt_22_orth_eff_ch_TM4_prec_real_tap[16] = {{0.70711,0.0}, {0.0, 0.0}, {0.70711,0.0}, {0.0, 0.0}, +static struct complex R_sqrt_22_orth_eff_ch_TM4_prec_real[16] = {{0.70711,0.0}, {0.0, 0.0}, {0.70711,0.0}, {0.0, 0.0}, {0.0, 0.0}, {0.70711,0.0}, {0.0, 0.0}, {-0.70711,0.0}, {0.70711,0.0}, {0.0, 0.0}, {0.70711,0.0}, {0.0, 0.0}, {0.0, 0.0}, {-0.70711,0.0}, {0.0, 0.0}, {0.70711,0.0} }; -struct complex *R_sqrt_22_orth_eff_ch_TM4_prec_real[1] = {R_sqrt_22_orth_eff_ch_TM4_prec_real_tap}; - - - -struct complex R_sqrt_22_orth_eff_ch_TM4_prec_imag_tap[16] = {{0.70711,0.0}, {0.0,0.0}, {0.0, -0.70711}, {0.0,0.0}, +static struct complex R_sqrt_22_orth_eff_ch_TM4_prec_imag[16] = {{0.70711,0.0}, {0.0,0.0}, {0.0, -0.70711}, {0.0,0.0}, {0.0, 0.0}, {0.70711,0.0}, {0.0, 0.0}, {0.0,0.70711}, {0.0,-0.70711}, {0.0, 0.0}, {-0.70711,0.0}, {0.0, 0.0}, {0.0, 0.0}, {0.0,0.70711}, {0.0, 0.0}, {-0.70711,0.0} }; -struct complex *R_sqrt_22_orth_eff_ch_TM4_prec_imag[1] = {R_sqrt_22_orth_eff_ch_TM4_prec_imag_tap}; //Correlation matrix for EPA channel -struct complex R_sqrt_22_EPA_low_tap[16] = {{1.0,0.0}, {0.0,0.0}, {0.0,0.0}, {0.0,0.0}, +static struct complex R_sqrt_22_EPA_low[16] = {{1.0,0.0}, {0.0,0.0}, {0.0,0.0}, {0.0,0.0}, {0.0,0.0}, {1.0,0.0}, {0.0,0.0}, {0.0,0.0}, {0.0,0.0}, {0.0,0.0}, {1.0,0.0}, {0.0,0.0}, {0.0,0.0}, {0.0,0.0}, {0.0,0.0}, {1.0,0.0} }; -struct complex *R_sqrt_22_EPA_low[1] = {R_sqrt_22_EPA_low_tap}; -struct complex R_sqrt_22_EPA_high_tap[16] = { +static struct complex R_sqrt_22_EPA_high[16] = { {0.7179,0.0}, {0.4500,0.0}, {0.4500,0.0}, {0.2821,0.0}, {0.4500,0.0}, {0.7179,0.0}, {0.2821,0.0}, {0.4500,0.0}, {0.4500,0.0}, {0.2821,0.0}, {0.7179,0.0}, {0.4500,0.0}, {0.2821,0.0}, {0.4500,0.0}, {0.4500,0.0}, {0.7179,0.0} }; -struct complex *R_sqrt_22_EPA_high[1] = {R_sqrt_22_EPA_high_tap}; -struct complex R_sqrt_22_EPA_medium_tap[16] = {{0.8375,0.0}, {0.5249,0.0}, {0.1286,0.0}, {0.0806,0.0}, +static struct complex R_sqrt_22_EPA_medium[16] = {{0.8375,0.0}, {0.5249,0.0}, {0.1286,0.0}, {0.0806,0.0}, {0.5249,0.0}, {0.8375,0.0}, {0.0806,0.0}, {0.1286,0.0}, {0.1286,0.0}, {0.0806,0.0}, {0.8375,0.0}, {0.5249,0.0}, {0.0806,0.0}, {0.1286,0.0}, {0.5249,0.0}, {0.8375,0.0} }; -struct complex *R_sqrt_22_EPA_medium[1] = {R_sqrt_22_EPA_medium_tap}; - - //Rayleigh1_orth_eff_ch_TM4 @@ -600,6 +576,7 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx, double sum_amps; double aoa,ricean_factor,Td,maxDoppler; int channel_length,nb_taps; + struct complex *R_sqrt_ptr2; chan_desc->modelid = channel_model; chan_desc->nb_tx = nb_tx; chan_desc->nb_rx = nb_rx; @@ -880,7 +857,7 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx, chan_desc->R_sqrt = (struct complex **) malloc(chan_desc->nb_taps*sizeof(struct complex **)); for (i = 0; inb_taps; i++) - chan_desc->R_sqrt[i] = R_sqrt_22_EPA_low[0]; + chan_desc->R_sqrt[i] = R_sqrt_22_EPA_low; } else { printf("Correlation matrices are implemented for 2 x 2 only"); } @@ -935,7 +912,7 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx, chan_desc->R_sqrt = (struct complex **) malloc(chan_desc->nb_taps*sizeof(struct complex **)); for (i = 0; inb_taps; i++) - chan_desc->R_sqrt[i] = R_sqrt_22_EPA_high[0]; + chan_desc->R_sqrt[i] = R_sqrt_22_EPA_high; } else { printf("Correlation matrices are implemented for 2 x 2 only"); } @@ -990,7 +967,7 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx, chan_desc->R_sqrt = (struct complex **) malloc(chan_desc->nb_taps*sizeof(struct complex **)); for (i = 0; inb_taps; i++) - chan_desc->R_sqrt[i] = R_sqrt_22_EPA_medium[0]; + chan_desc->R_sqrt[i] = R_sqrt_22_EPA_medium; } else { printf("Correlation matrices are implemented for 2 x 2 only"); } @@ -1397,11 +1374,13 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx, case TS_SHIFT: nb_taps = 2; + double ts_shift_delays[] = {0, 1/7.68}; Td = ts_shift_delays[1]; channel_length = 10; ricean_factor = 0.0; aoa = 0.0; maxDoppler = 0; + double ts_shift_amps[] = {0, 1}; fill_channel_desc(chan_desc,nb_tx, nb_rx, nb_taps, diff --git a/openair1/SIMULATION/TOOLS/scm_corrmat.h b/openair1/SIMULATION/TOOLS/scm_corrmat.h index 6ee6567ce9..5695e0bd0f 100644 --- a/openair1/SIMULATION/TOOLS/scm_corrmat.h +++ b/openair1/SIMULATION/TOOLS/scm_corrmat.h @@ -19,7 +19,7 @@ * contact@openairinterface.org */ -double R22_sqrt[6][32] = { +static double R22_sqrt[6][32] = { {0.921700, -0.000000, 0.010380, -0.027448, -0.250153, 0.294754, 0.005961, 0.010769, 0.010380, 0.027448, 0.921700, 0.000000, -0.011595, -0.004130, -0.250153, 0.294754, -0.250153, -0.294754, -0.011595, 0.004130, 0.921700, 0.000000, 0.010380, -0.027448, 0.005961, -0.010769, -0.250153, -0.294754, 0.010380, 0.027448, 0.921700, 0.000000}, {0.923810, 0.000000, 0.004069, 0.027832, 0.151730, 0.350180, -0.009882, 0.006114, 0.004069, -0.027832, 0.923810, 0.000000, 0.011218, -0.003029, 0.151730, 0.350180, 0.151730, -0.350180, 0.011218, 0.003029, 0.923810, -0.000000, 0.004069, 0.027832, -0.009882, -0.006114, 0.151730, -0.350180, 0.004069, -0.027832, 0.923810, 0.000000}, {0.927613, 0.000000, 0.014253, 0.025767, -0.061171, -0.367133, 0.009258, -0.007340, 0.014253, -0.025767, 0.927613, -0.000000, -0.011138, -0.003942, -0.061171, -0.367133, -0.061171, 0.367133, -0.011138, 0.003942, 0.927613, 0.000000, 0.014253, 0.025767, 0.009258, 0.007340, -0.061171, 0.367133, 0.014253, -0.025767, 0.927613, 0.000000}, @@ -27,7 +27,7 @@ double R22_sqrt[6][32] = { {0.919726, -0.000000, 0.038700, -0.111146, 0.217804, 0.300925, 0.045531, -0.013659, 0.038700, 0.111146, 0.919726, 0.000000, -0.027201, 0.038983, 0.217804, 0.300925, 0.217804, -0.300925, -0.027201, -0.038983, 0.919726, 0.000000, 0.038700, -0.111146, 0.045531, 0.013659, 0.217804, -0.300925, 0.038700, 0.111146, 0.919726, 0.000000}, {0.867608, -0.000000, 0.194097, -0.112414, -0.418811, 0.095938, -0.081264, 0.075727, 0.194097, 0.112414, 0.867608, -0.000000, -0.106125, -0.032801, -0.418811, 0.095938, -0.418811, -0.095938, -0.106125, 0.032801, 0.867608, 0.000000, 0.194097, -0.112414, -0.081264, -0.075727, -0.418811, -0.095938, 0.194097, 0.112414, 0.867608, 0.000000}, }; -double R21_sqrt[6][8] = { +static double R21_sqrt[6][8] = { {0.922167, 0.000000,-0.250280, 0.294903,-0.250280, -0.294903,0.922167, 0.000000}, {0.924238, 0.000000,0.151801, 0.350342,0.151801, -0.350342,0.924238, 0.000000}, {0.928080, 0.000000,-0.061202, -0.367318,-0.061202, 0.367318,0.928080, 0.000000}, @@ -35,7 +35,7 @@ double R21_sqrt[6][8] = { {0.927225, 0.000000,0.219580, 0.303378,0.219580, -0.303378,0.927225, 0.000000}, {0.896133, 0.000000,-0.432581, 0.099092,-0.432581, -0.099092,0.896133, 0.000000}, }; -double R12_sqrt[6][8] = { +static double R12_sqrt[6][8] = { {0.999494, 0.000000,0.011256, -0.029765,0.011256, 0.029765,0.999494, 0.000000}, {0.999537, 0.000000,0.004402, 0.030114,0.004402, -0.030114,0.999537, 0.000000}, {0.999497, 0.000000,0.015358, 0.027764,0.015358, -0.027764,0.999497, 0.000000}, diff --git a/openair2/LAYER2/MAC/config.c b/openair2/LAYER2/MAC/config.c index 71f91a67ec..8d4a53da6c 100644 --- a/openair2/LAYER2/MAC/config.c +++ b/openair2/LAYER2/MAC/config.c @@ -51,7 +51,7 @@ #include "LTE_MBSFN-SubframeConfigList.h" #include "LTE_MBSFN-SubframeConfig.h" #include "LTE_PMCH-InfoList-r9.h" - +#include extern RAN_CONTEXT_t RC; extern int l2_init_eNB(void); diff --git a/openair2/LAYER2/MAC/config_ue.c b/openair2/LAYER2/MAC/config_ue.c index 79202d87e3..f5c12e710d 100644 --- a/openair2/LAYER2/MAC/config_ue.c +++ b/openair2/LAYER2/MAC/config_ue.c @@ -57,6 +57,7 @@ #include "LTE_PMCH-InfoList-r9.h" +#include extern void mac_init_cell_params(int Mod_idP,int CC_idP); extern void phy_reset_ue(module_id_t Mod_id,uint8_t CC_id,uint8_t eNB_index); diff --git a/openair2/LAYER2/MAC/eNB_scheduler.c b/openair2/LAYER2/MAC/eNB_scheduler.c index 4e063d2207..4b06720713 100644 --- a/openair2/LAYER2/MAC/eNB_scheduler.c +++ b/openair2/LAYER2/MAC/eNB_scheduler.c @@ -556,10 +556,7 @@ copy_ulreq(module_id_t module_idP, frame_t frameP, sub_frame_t subframeP) { } } -extern int16_t find_dlsch(uint16_t rnti, PHY_VARS_eNB *eNB,find_type_t type); -extern int16_t find_ulsch(uint16_t rnti, PHY_VARS_eNB *eNB,find_type_t type); -extern void clean_eNb_ulsch(LTE_eNB_ULSCH_t *ulsch); -extern void clean_eNb_dlsch(LTE_eNB_DLSCH_t *dlsch); +#include void eNB_dlsch_ulsch_scheduler(module_id_t module_idP, diff --git a/openair2/LAYER2/MAC/mac_extern.h b/openair2/LAYER2/MAC/mac_extern.h index cbca693b2a..522dc2721f 100644 --- a/openair2/LAYER2/MAC/mac_extern.h +++ b/openair2/LAYER2/MAC/mac_extern.h @@ -58,7 +58,6 @@ extern unsigned char NB_eNB_INST; extern uint16_t NB_UE_INST; extern uint16_t NB_THREAD_INST; extern unsigned char NB_RN_INST; -extern unsigned short NODE_ID[1]; extern const int cqi_to_mcs[16]; diff --git a/openair2/LAYER2/MAC/main_ue.c b/openair2/LAYER2/MAC/main_ue.c index 2868d94930..2140d66a10 100644 --- a/openair2/LAYER2/MAC/main_ue.c +++ b/openair2/LAYER2/MAC/main_ue.c @@ -44,8 +44,7 @@ #include "common/ran_context.h" -extern void openair_rrc_top_init_ue( int eMBMS_active, char *uecap_xer, uint8_t cba_group_active, uint8_t HO_active); - +#include 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/LAYER2/MAC/rar_tools.c b/openair2/LAYER2/MAC/rar_tools.c index d48952318a..740923cc08 100644 --- a/openair2/LAYER2/MAC/rar_tools.c +++ b/openair2/LAYER2/MAC/rar_tools.c @@ -41,7 +41,6 @@ #define DEBUG_RAR extern unsigned int localRIV2alloc_LUT25[512]; -extern unsigned int distRIV2alloc_LUT25[512]; extern unsigned short RIV2nb_rb_LUT25[512]; extern unsigned short RIV2first_rb_LUT25[512]; extern RAN_CONTEXT_t RC; diff --git a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_extern.h b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_extern.h index 1e0ab98d4c..1b3e5e5d60 100644 --- a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_extern.h +++ b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_extern.h @@ -56,7 +56,6 @@ extern unsigned char NB_UE_INST;*/ extern unsigned char NB_INST; extern unsigned char NB_eNB_INST; extern unsigned char NB_RN_INST; -extern unsigned short NODE_ID[1]; /* Scheduler */ extern RAN_CONTEXT_t RC; diff --git a/openair2/LAYER2/PDCP_v10.1.0/pdcp_control_primitive.c b/openair2/LAYER2/PDCP_v10.1.0/pdcp_control_primitive.c index 0ef6893d08..c2736ddd84 100644 --- a/openair2/LAYER2/PDCP_v10.1.0/pdcp_control_primitive.c +++ b/openair2/LAYER2/PDCP_v10.1.0/pdcp_control_primitive.c @@ -32,7 +32,6 @@ #include "rtos_header.h" #include "platform.h" #include "protocol_vars_extern.h" -#include "print.h" //----------------------------------------------------------------------------- #include "rlc.h" #include "pdcp.h" diff --git a/openair2/LAYER2/openair2_proc.c b/openair2/LAYER2/openair2_proc.c index bbdc55e036..3d2c06f489 100644 --- a/openair2/LAYER2/openair2_proc.c +++ b/openair2/LAYER2/openair2_proc.c @@ -503,8 +503,8 @@ int openair2_stats_read(char *buffer, char **my_buffer, off_t off, int length) { } else if(Mac_rlc_xface->Is_cluster_head[k] ==1) { Mod_id=k; len+=sprintf(&buffer[len], - "-------------------------------------------------------------------CH %d: TTI: %d------------------------------------------------------------------\n", - NODE_ID[Mod_id],Mac_rlc_xface->frame); + "------------------------------------------------------------------- TTI: %d------------------------------------------------------------------\n", + Mac_rlc_xface->frame); for(i=1; i<=NB_CNX_CH; i++) { if (CH_mac_inst[Mod_id].Dcch_lchan[i].Active==1) { diff --git a/openair2/MCE_APP/mce_app.c b/openair2/MCE_APP/mce_app.c index 3572de215c..4ac12ab5b4 100644 --- a/openair2/MCE_APP/mce_app.c +++ b/openair2/MCE_APP/mce_app.c @@ -54,7 +54,6 @@ # define X2AP_ENB_REGISTER_RETRY_DELAY 10 #include "openair1/PHY/INIT/phy_init.h" -extern unsigned char NB_MCE_INST; extern RAN_CONTEXT_t RC; diff --git a/openair2/RRC/LTE/rrc_eNB.c b/openair2/RRC/LTE/rrc_eNB.c index 006f03a63e..b96dbcf1eb 100644 --- a/openair2/RRC/LTE/rrc_eNB.c +++ b/openair2/RRC/LTE/rrc_eNB.c @@ -110,7 +110,6 @@ extern RAN_CONTEXT_t RC; extern eNB_MAC_INST *eNB_mac_inst; extern UE_MAC_INST *UE_mac_inst; -extern uint16_t two_tier_hexagonal_cellIds[7]; mui_t rrc_eNB_mui = 0; @@ -6120,7 +6119,6 @@ rrc_eNB_generate_HO_RRCConnectionReconfiguration(const protocol_ctxt_t *const ct mobilityInfo = CALLOC(1, sizeof(*mobilityInfo)); memset((void *)mobilityInfo, 0, sizeof(*mobilityInfo)); mobilityInfo->targetPhysCellId = RC.rrc[ctxt_pP->module_id]->carrier[0].physCellId; - //(PhysCellId_t) two_tier_hexagonal_cellIds[ue_context_pP->ue_context.handover_info->modid_t]; LOG_D(RRC, "[eNB %d] Frame %d: handover preparation: targetPhysCellId: %ld mod_id: %d ue: %x \n", ctxt_pP->module_id, ctxt_pP->frame, diff --git a/openair2/RRC/LTE/rrc_extern.h b/openair2/RRC/LTE/rrc_extern.h index 6564f38ade..7f7fd6579e 100644 --- a/openair2/RRC/LTE/rrc_extern.h +++ b/openair2/RRC/LTE/rrc_extern.h @@ -47,7 +47,6 @@ extern LTE_LogicalChannelConfig_t SRB2_logicalChannelConfig_defaultValue; extern unsigned char NB_INST; extern unsigned char NB_eNB_INST; extern uint16_t NB_UE_INST; -extern unsigned short NODE_ID[1]; extern void* bigphys_malloc(int); diff --git a/openair2/RRC/NR/nr_rrc_extern.h b/openair2/RRC/NR/nr_rrc_extern.h index 04e0392236..3b08a24027 100644 --- a/openair2/RRC/NR/nr_rrc_extern.h +++ b/openair2/RRC/NR/nr_rrc_extern.h @@ -47,7 +47,6 @@ extern NR_LogicalChannelConfig_t NR_SRB3_logicalChannelConfig_defaultValue; extern unsigned char NB_INST; extern unsigned char NB_eNB_INST; extern uint16_t NB_UE_INST; -extern unsigned short NODE_ID[1]; extern void* bigphys_malloc(int); diff --git a/openair2/UTIL/TRACE/fifo_printf.c b/openair2/UTIL/TRACE/fifo_printf.c deleted file mode 100644 index 2dc4da0637..0000000000 --- a/openair2/UTIL/TRACE/fifo_printf.c +++ /dev/null @@ -1,117 +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 - */ - -/* - * fifo_printf.c - * ------------------- - * AUTHOR : Lionel GAUTHIER - * COMPANY : EURECOM - * EMAIL : Lionel.Gauthier@eurecom.fr - * - */ -#include "rtos_header.h" -#include "platform.h" -#include "protocol_vars_extern.h" - -#include -#include -#include - - -#include "fifo_printf.h" - -#ifndef FIFO_PRINTF -//----------------------------------------------------------------------------- -int fifo_printf_null (const char *fmt, ...) -{ - return 0; -} -#else -static uint8_t fifo_printed_l1[FIFO_PRINTF_MAX_STRING_SIZE]; -static uint8_t fifo_printed_l2[FIFO_PRINTF_MAX_STRING_SIZE]; -//----------------------------------------------------------------------------- -void -fifo_printf_init (void) -{ - //----------------------------------------------------------------------------- - printk ("[TRACE] INIT\n"); - rtf_create (FIFO_PRINTF_L1_NO, FIFO_PRINTF_SIZE); - rtf_create (FIFO_PRINTF_L2_NO, FIFO_PRINTF_SIZE); -} - -//----------------------------------------------------------------------------- -void -fifo_printf_clean_up (void) -{ - //----------------------------------------------------------------------------- - rtf_destroy (FIFO_PRINTF_L1_NO); - rtf_destroy (FIFO_PRINTF_L2_NO); -} - -//----------------------------------------------------------------------------- -int -fifo_printf (const char *fmt, ...) -{ - //----------------------------------------------------------------------------- - int i; - va_list args; - - va_start (args, fmt); - - if (pthread_self () == &task_l1l) { - i = vsprintf (fifo_printed_l1, fmt, args); - va_end (args); - - /* perhaps we should discard old data instead */ - if (i > FIFO_PRINTF_MAX_STRING_SIZE) { - rt_printk ("[WCDMA] FIFO_PRINTF WROTE OUTSIDE ITS MEMORY BOUNDARY : ERRORS WILL OCCUR\n"); - } - - if (i <= 0) { - return 0; - } - - rtf_put (FIFO_PRINTF_L1_NO, fifo_printed_l1, i); - - return i; - } - - if (pthread_self () == &task_l2) { - i = vsprintf (fifo_printed_l2, fmt, args); - va_end (args); - - /* perhaps we should discard old data instead */ - if (i > FIFO_PRINTF_MAX_STRING_SIZE) { - rt_printk ("[WCDMA] FIFO_PRINTF WROTE OUTSIDE ITS MEMORY BOUNDARY : ERRORS WILL OCCUR\n"); - } - - if (i <= 0) { - return 0; - } - - rtf_put (FIFO_PRINTF_L2_NO, fifo_printed_l2, i); - - return i; - } - - return 0; -} -#endif diff --git a/openair2/UTIL/TRACE/fifo_printf.h b/openair2/UTIL/TRACE/fifo_printf.h deleted file mode 100644 index ce2702b19a..0000000000 --- a/openair2/UTIL/TRACE/fifo_printf.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 - */ - -/*************************************************************************** - fifo_printf.h - description - ------------------- - AUTHOR : Lionel GAUTHIER - COMPANY : EURECOM - EMAIL : Lionel.Gauthier@eurecom.fr - - - ***************************************************************************/ -#ifndef __FIFO_PRINTF_H__ -# define __FIFO_PRINTF_H__ -# define FIFO_PRINTF_MAX_STRING_SIZE 500 -# define FIFO_PRINTF_L1_NO 63 -# define FIFO_PRINTF_L2_NO 62 -# define FIFO_PRINTF_SIZE 65536 -#endif diff --git a/openair2/UTIL/TRACE/fifo_printf_proto_extern.h b/openair2/UTIL/TRACE/fifo_printf_proto_extern.h deleted file mode 100644 index 0855a8da93..0000000000 --- a/openair2/UTIL/TRACE/fifo_printf_proto_extern.h +++ /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 - */ - -/*************************************************************************** - fifo_printf_proto_extern.h - description - ------------------- - AUTHOR : Lionel GAUTHIER - COMPANY : EURECOM - EMAIL : Lionel.Gauthier@eurecom.fr - - - - ***************************************************************************/ -#ifndef __FIFO_PRINTF_PROTO_EXTERN_H__ -# define __FIFO_PRINTF_PROTO_EXTERN_H__ -#ifdef FIFO_PRINTF -extern void fifo_printf_init (void); -extern void fifo_printf_clean_up (void); -extern int fifo_printf (const char *fmt, ...); -#else -extern int fifo_printf_null (const char *fmt, ...); -#endif -#endif diff --git a/openair2/UTIL/TRACE/print.h b/openair2/UTIL/TRACE/print.h deleted file mode 100644 index 72c43f20d4..0000000000 --- a/openair2/UTIL/TRACE/print.h +++ /dev/null @@ -1,32 +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 - */ - -/*************************************************************************** - print.h - description - ------------------- - AUTHOR : Lionel GAUTHIER - COMPANY : EURECOM - EMAIL : Lionel.Gauthier@eurecom.fr - ***************************************************************************/ -#ifndef __PRINT_H__ -# define __PRINT_H__ -# define msg printf -#endif diff --git a/openair3/MME_APP/mme_app.c b/openair3/MME_APP/mme_app.c index 5a32ddc98c..57f1b4c9d2 100644 --- a/openair3/MME_APP/mme_app.c +++ b/openair3/MME_APP/mme_app.c @@ -54,7 +54,6 @@ # define X2AP_ENB_REGISTER_RETRY_DELAY 10 #include "openair1/PHY/INIT/phy_init.h" -extern unsigned char NB_MCE_INST; extern RAN_CONTEXT_t RC; diff --git a/targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.c b/targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.c index dce410de47..f35a18eb0e 100644 --- a/targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.c +++ b/targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.c @@ -42,7 +42,6 @@ #include #include #include -#include #include "common_lib.h" #include "ethernet_lib.h" From c9c1df5e32c4394410a49eda807089b7c882fab0 Mon Sep 17 00:00:00 2001 From: Mahesh Date: Tue, 20 Jul 2021 08:29:55 +0530 Subject: [PATCH 46/91] fix tdd slot config pack/unpack --- nfapi/open-nFAPI/nfapi/src/nfapi_p5.c | 35 +++++++++++-------- nfapi/open-nFAPI/vnf/src/vnf_p7.c | 4 +-- .../LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c | 1 - 3 files changed, 22 insertions(+), 18 deletions(-) diff --git a/nfapi/open-nFAPI/nfapi/src/nfapi_p5.c b/nfapi/open-nFAPI/nfapi/src/nfapi_p5.c index 8aea9f590c..8072b5f530 100644 --- a/nfapi/open-nFAPI/nfapi/src/nfapi_p5.c +++ b/nfapi/open-nFAPI/nfapi/src/nfapi_p5.c @@ -860,9 +860,14 @@ static uint8_t pack_config_request(void *msg, uint8_t **ppWritePackedMsg, uint8_ static uint8_t pack_nr_config_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t* config) { - printf("\n\nEntering pack_config_request\n"); + nfapi_nr_config_request_scf_t *pNfapiMsg = (nfapi_nr_config_request_scf_t*)msg; + for(int i = 0; i<40; i++){ //packing tdd slot config + for(int symbol = 0; symbol<14;symbol++){ + push8(pNfapiMsg->tdd_table.max_tdd_periodicity_list[i].max_num_of_symbol_per_slot_list[symbol].slot_config.value, ppWritePackedMsg,end); + } + } return (push8(pNfapiMsg->num_tlv, ppWritePackedMsg, end) && pack_tlv(NFAPI_NR_CONFIG_DL_BANDWIDTH_TAG, &(pNfapiMsg->carrier_config.dl_bandwidth), ppWritePackedMsg, end, &pack_uint16_tlv_value) && @@ -884,10 +889,10 @@ static uint8_t pack_nr_config_request(void *msg, uint8_t **ppWritePackedMsg, uin pack_tlv(NFAPI_NR_CONFIG_RESTRICTED_SET_CONFIG_TAG, &(pNfapiMsg->prach_config.restricted_set_config), ppWritePackedMsg, end, &pack_uint8_tlv_value) && pack_tlv(NFAPI_NR_CONFIG_SSB_PER_RACH_TAG, &(pNfapiMsg->prach_config.ssb_per_rach), ppWritePackedMsg, end, &pack_uint8_tlv_value) && pack_tlv(NFAPI_NR_CONFIG_PRACH_SUB_C_SPACING_TAG, &(pNfapiMsg->prach_config.prach_sub_c_spacing), ppWritePackedMsg, end, &pack_uint8_tlv_value) && - pack_tlv(NFAPI_NR_CONFIG_PRACH_ROOT_SEQUENCE_INDEX_TAG, &(pNfapiMsg->prach_config.num_prach_fd_occasions_list[0].prach_root_sequence_index), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_NR_CONFIG_K1_TAG, &(pNfapiMsg->prach_config.num_prach_fd_occasions_list[0].k1), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_NR_CONFIG_PRACH_ZERO_CORR_CONF_TAG, &(pNfapiMsg->prach_config.num_prach_fd_occasions_list[0].prach_zero_corr_conf), ppWritePackedMsg, end, &pack_uint8_tlv_value) && - pack_tlv(NFAPI_NR_CONFIG_NUM_ROOT_SEQUENCES_TAG, &(pNfapiMsg->prach_config.num_prach_fd_occasions_list[0].num_root_sequences), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + pack_tlv(NFAPI_NR_CONFIG_PRACH_ROOT_SEQUENCE_INDEX_TAG, &(pNfapiMsg->prach_config.num_prach_fd_occasions_list[0].prach_root_sequence_index), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_NR_CONFIG_K1_TAG, &(pNfapiMsg->prach_config.num_prach_fd_occasions_list[0].k1), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_NR_CONFIG_PRACH_ZERO_CORR_CONF_TAG, &(pNfapiMsg->prach_config.num_prach_fd_occasions_list[0].prach_zero_corr_conf), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + pack_tlv(NFAPI_NR_CONFIG_NUM_ROOT_SEQUENCES_TAG, &(pNfapiMsg->prach_config.num_prach_fd_occasions_list[0].num_root_sequences), ppWritePackedMsg, end, &pack_uint8_tlv_value) && pack_tlv(NFAPI_NR_CONFIG_SCS_COMMON_TAG, &(pNfapiMsg->ssb_config.scs_common), ppWritePackedMsg, end, &pack_uint8_tlv_value) && @@ -903,11 +908,6 @@ static uint8_t pack_nr_config_request(void *msg, uint8_t **ppWritePackedMsg, uin pack_tlv(NFAPI_NR_CONFIG_SSB_SUBCARRIER_OFFSET_TAG, &(pNfapiMsg->ssb_table.ssb_subcarrier_offset), ppWritePackedMsg, end, &pack_uint8_tlv_value) && pack_tlv(NFAPI_NR_CONFIG_TDD_PERIOD_TAG, &(pNfapiMsg->tdd_table.tdd_period), ppWritePackedMsg, end, &pack_uint8_tlv_value) && - pack_tlv(NFAPI_NR_CONFIG_SLOT_CONFIG_TAG, &(pNfapiMsg->tdd_table.max_tdd_periodicity_list[0].max_num_of_symbol_per_slot_list[0].slot_config), ppWritePackedMsg, end, &pack_uint8_tlv_value) && - - //pack_tlv(NFAPI_NR_NFAPI_DOWNLINK_UES_PER_SUBFRAME_TAG, &(pNfapiMsg->nfapi_config.dl_ue_per_sf), ppWritePackedMsg, end, &pack_uint8_tlv_value) && - //pack_tlv(NFAPI_NR_NFAPI_MAXIMUM_TRANSMIT_POWER_TAG, &(pNfapiMsg->nfapi_config.max_transmit_power), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - //pack_tlv(NFAPI_NR_NFAPI_NRARFCN_TAG, &(pNfapiMsg->nfapi_config.nrarfcn), ppWritePackedMsg, end, &pack_uint32_tlv_value) && pack_tlv(NFAPI_NR_NFAPI_P7_PNF_ADDRESS_IPV4_TAG, &(pNfapiMsg->nfapi_config.p7_pnf_address_ipv4), ppWritePackedMsg, end, &pack_ipv4_address_value) && pack_tlv(NFAPI_NR_NFAPI_P7_PNF_ADDRESS_IPV6_TAG, &(pNfapiMsg->nfapi_config.p7_pnf_address_ipv6), ppWritePackedMsg, end, &pack_ipv6_address_value) && pack_tlv(NFAPI_NR_NFAPI_P7_PNF_PORT_TAG, &(pNfapiMsg->nfapi_config.p7_pnf_port), ppWritePackedMsg, end, &pack_uint16_tlv_value) && @@ -2070,12 +2070,18 @@ static uint8_t unpack_nr_config_request(uint8_t **ppReadPackedMsg, uint8_t *end, { nfapi_nr_config_request_scf_t *pNfapiMsg = (nfapi_nr_config_request_scf_t*)msg; - pNfapiMsg->tdd_table.max_tdd_periodicity_list = (nfapi_nr_max_tdd_periodicity_t*) malloc(20*sizeof(nfapi_nr_max_tdd_periodicity_t)); + pNfapiMsg->tdd_table.max_tdd_periodicity_list = (nfapi_nr_max_tdd_periodicity_t*) malloc(40*sizeof(nfapi_nr_max_tdd_periodicity_t)); + for(int i=0;i<40;i++) - pNfapiMsg->tdd_table.max_tdd_periodicity_list[i].max_num_of_symbol_per_slot_list = (nfapi_nr_max_num_of_symbol_per_slot_t*) malloc(14*sizeof(nfapi_nr_max_num_of_symbol_per_slot_t)); + pNfapiMsg->tdd_table.max_tdd_periodicity_list[i].max_num_of_symbol_per_slot_list = (nfapi_nr_max_num_of_symbol_per_slot_t*) malloc(14*sizeof(nfapi_nr_max_num_of_symbol_per_slot_t)); pNfapiMsg->prach_config.num_prach_fd_occasions_list=(nfapi_nr_num_prach_fd_occasions_t *) malloc(sizeof(nfapi_nr_num_prach_fd_occasions_t)); + for(int i = 0; i < 40; i++){ //unpacking tdd slot config + for(int symbol = 0; symbol<14;symbol++){ + pull8(ppReadPackedMsg,&pNfapiMsg->tdd_table.max_tdd_periodicity_list[i].max_num_of_symbol_per_slot_list[symbol].slot_config.value, end); + } + } unpack_tlv_t unpack_fns[] = { { NFAPI_NR_CONFIG_DL_BANDWIDTH_TAG, &(pNfapiMsg->carrier_config.dl_bandwidth), &unpack_uint16_tlv_value}, @@ -2111,8 +2117,6 @@ static uint8_t unpack_nr_config_request(uint8_t **ppReadPackedMsg, uint8_t *end, { NFAPI_NR_CONFIG_SSB_PERIOD_TAG, &(pNfapiMsg->ssb_table.ssb_period), &unpack_uint8_tlv_value}, { NFAPI_NR_CONFIG_SSB_SUBCARRIER_OFFSET_TAG, &(pNfapiMsg->ssb_table.ssb_subcarrier_offset), &unpack_uint8_tlv_value}, { NFAPI_NR_CONFIG_TDD_PERIOD_TAG, &(pNfapiMsg->tdd_table.tdd_period), &unpack_uint8_tlv_value}, - { NFAPI_NR_CONFIG_SLOT_CONFIG_TAG, &(pNfapiMsg->tdd_table.max_tdd_periodicity_list[0].max_num_of_symbol_per_slot_list[0].slot_config), &unpack_uint8_tlv_value}, - { NFAPI_NR_NFAPI_P7_PNF_ADDRESS_IPV4_TAG, &(pNfapiMsg->nfapi_config.p7_pnf_address_ipv4), &unpack_ipv4_address_value}, { 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}, { NFAPI_NR_NFAPI_P7_VNF_ADDRESS_IPV4_TAG, &(pNfapiMsg->nfapi_config.p7_vnf_address_ipv4), &unpack_ipv4_address_value}, @@ -2122,9 +2126,10 @@ static uint8_t unpack_nr_config_request(uint8_t **ppReadPackedMsg, uint8_t *end, { NFAPI_NR_NFAPI_TIMING_INFO_PERIOD_TAG, &(pNfapiMsg->nfapi_config.timing_info_period), &unpack_uint8_tlv_value}, { NFAPI_NR_NFAPI_TIMING_WINDOW_TAG, &(pNfapiMsg->nfapi_config.timing_window), &unpack_uint8_tlv_value}, }; + return ( pull8(ppReadPackedMsg, &pNfapiMsg->num_tlv, end) && unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); - + } static uint8_t unpack_config_response(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t* config) diff --git a/nfapi/open-nFAPI/vnf/src/vnf_p7.c b/nfapi/open-nFAPI/vnf/src/vnf_p7.c index e038f59217..443ccc3d49 100644 --- a/nfapi/open-nFAPI/vnf/src/vnf_p7.c +++ b/nfapi/open-nFAPI/vnf/src/vnf_p7.c @@ -2039,8 +2039,8 @@ void vnf_nr_handle_timing_info(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vnf_p7) { NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() LARGE SFN/SF DELTA between PNF and VNF delta:%d VNF:%d PNF:%d\n\n\n\n\n\n\n\n\n", __FUNCTION__, vnf_pnf_sfnslot_delta,NFAPI_SFNSLOT2DEC(vnf_p7->p7_connections[0].sfn,vnf_p7->p7_connections[0].slot),NFAPI_SFNSLOT2DEC(ind.last_sfn,ind.last_slot)) ; // Panos: Careful here!!! Modification of the original nfapi-code - // vnf_p7->p7_connections[0].sfn = ind.last_sfn; - // vnf_p7->p7_connections[0].slot = ind.last_slot; + vnf_p7->p7_connections[0].sfn = ind.last_sfn; + vnf_p7->p7_connections[0].slot = ind.last_slot; } } } diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c index 17b1fc5233..888c55ca7e 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c @@ -836,7 +836,6 @@ void nr_schedule_ue_spec(module_id_t module_id, /* PP has not selected a specific HARQ Process, get a new one */ // if (NFAPI_MODE == NFAPI_MODE_VNF) // sched_ctrl->available_dl_harq.head = 0; - remove_front_nr_list(&sched_ctrl->available_dl_harq); current_harq_pid = sched_ctrl->available_dl_harq.head; AssertFatal(current_harq_pid >= 0, "no free HARQ process available for UE %d\n", From 5ed848c76ef1760c887d7f287879585366328bfe Mon Sep 17 00:00:00 2001 From: Laurent OpenCells Date: Tue, 20 Jul 2021 16:30:14 +0200 Subject: [PATCH 47/91] more fixes on gcc warnings, misleading indentation and CPU mitigation when the traffic demand in 5G exeeds the available througput --- executables/nr-ru.c | 632 +- executables/nr-softmodem.c | 106 +- .../nfapi/public_inc/nfapi_interface.h | 2 +- nfapi/open-nFAPI/nfapi/src/nfapi.c | 1752 +- nfapi/open-nFAPI/nfapi/src/nfapi_p4.c | 3531 ++-- nfapi/open-nFAPI/nfapi/src/nfapi_p5.c | 5153 +++--- nfapi/open-nFAPI/nfapi/src/nfapi_p7.c | 13443 +++++++--------- openair1/PHY/CODING/3gpplte_sse.c | 4 +- .../CODING/3gpplte_turbo_decoder_sse_16bit.c | 2 +- .../CODING/3gpplte_turbo_decoder_sse_8bit.c | 2 +- .../lte_ul_channel_estimation.c | 1 - .../PHY/LTE_UE_TRANSPORT/dlsch_demodulation.c | 8 +- openair1/PHY/LTE_UE_TRANSPORT/pmch_ue.c | 4 +- openair1/PHY/LTE_UE_TRANSPORT/ulsch_coding.c | 490 +- .../PHY/NR_TRANSPORT/nr_ulsch_demodulation.c | 2 +- .../PHY/NR_UE_TRANSPORT/nr_dlsch_decoding.c | 1210 +- .../NR_UE_TRANSPORT/nr_dlsch_demodulation.c | 6 +- openair1/PHY/TOOLS/nr_phy_scope.c | 2 +- openair1/SIMULATION/NR_PHY/prachsim.c | 2 +- openair1/SIMULATION/NR_PHY/ulsim.c | 2 +- openair2/LAYER2/nr_rlc/nr_rlc_entity_am.c | 2 +- openair2/LAYER2/nr_rlc/nr_rlc_entity_tm.c | 2 +- openair2/LAYER2/nr_rlc/nr_rlc_entity_um.c | 2 +- 23 files changed, 12170 insertions(+), 14190 deletions(-) mode change 100755 => 100644 nfapi/open-nFAPI/nfapi/src/nfapi_p7.c diff --git a/executables/nr-ru.c b/executables/nr-ru.c index 421ff4ad3e..3de8eb667f 100644 --- a/executables/nr-ru.c +++ b/executables/nr-ru.c @@ -114,8 +114,7 @@ extern int numerology; extern void wait_gNBs(void); -int attach_rru(RU_t *ru) -{ +int attach_rru(RU_t *ru) { ssize_t msg_len,len; RRU_CONFIG_msg_t rru_config_msg; int received_capabilities=0; @@ -183,8 +182,7 @@ int attach_rru(RU_t *ru) return 0; } -int connect_rau(RU_t *ru) -{ +int connect_rau(RU_t *ru) { RRU_CONFIG_msg_t rru_config_msg; ssize_t msg_len; int tick_received = 0; @@ -281,22 +279,20 @@ int connect_rau(RU_t *ru) /* Southbound Fronthaul functions, RCC/RAU */ // southbound IF5 fronthaul for 16-bit OAI format -void fh_if5_south_out(RU_t *ru, int frame, int slot, uint64_t timestamp) -{ +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 ); send_IF5(ru, timestamp, slot, &ru->seqno, IF5_RRH_GW_DL); } // southbound IF4p5 fronthaul -void fh_if4p5_south_out(RU_t *ru, int frame, int slot, uint64_t timestamp) -{ +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 ); 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) send_IF4p5(ru,frame, slot, IF4p5_PDLFFT); } @@ -307,8 +303,7 @@ void fh_if4p5_south_out(RU_t *ru, int frame, int slot, uint64_t timestamp) // Synchronous if5 from south void fh_if5_south_in(RU_t *ru, int *frame, - int *tti) -{ + int *tti) { NR_DL_FRAME_PARMS *fp = ru->nr_frame_parms; RU_proc_t *proc = &ru->proc; recv_IF5(ru, &proc->timestamp_rx, *tti, IF5_RRH_GW_UL); @@ -338,8 +333,7 @@ void fh_if5_south_in(RU_t *ru, // Synchronous if4p5 from south void fh_if4p5_south_in(RU_t *ru, int *frame, - int *slot) -{ + int *slot) { NR_DL_FRAME_PARMS *fp = ru->nr_frame_parms; RU_proc_t *proc = &ru->proc; int f,sl; @@ -636,7 +630,6 @@ void rx_rf(RU_t *ru,int *frame,int *slot) { ru->nb_rx); } - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ, 0 ); proc->timestamp_rx = ts-ru->ts_offset; @@ -649,6 +642,7 @@ void rx_rf(RU_t *ru,int *frame,int *slot) { proc->timestamp_rx = 0; } else { samples_per_slot_prev = fp->get_samples_per_slot((*slot-1)%fp->slots_per_frame,fp); + if (proc->timestamp_rx - old_ts != samples_per_slot_prev) { LOG_D(PHY,"rx_rf: rfdevice timing drift of %"PRId64" samples (ts_off %"PRId64")\n",proc->timestamp_rx - old_ts - samples_per_slot_prev,ru->ts_offset); ru->ts_offset += (proc->timestamp_rx - old_ts - samples_per_slot_prev); @@ -678,7 +672,8 @@ void rx_rf(RU_t *ru,int *frame,int *slot) { } 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, slot %d)\n",(long long unsigned int)proc->timestamp_rx,proc->frame_rx,*frame,proc->tti_rx,*slot); + 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, slot %d)\n",(long long unsigned int)proc->timestamp_rx,proc->frame_rx, + *frame,proc->tti_rx,*slot); exit_fun("Exiting"); } } else { @@ -706,7 +701,6 @@ void tx_rf(RU_t *ru,int frame,int slot, uint64_t timestamp) { int i,txsymb; T(T_ENB_PHY_OUTPUT_SIGNAL, T_INT(0), T_INT(0), T_INT(frame), T_INT(slot), T_INT(0), T_BUFFER(&ru->common.txdata[0][fp->get_samples_slot_timestamp(slot,fp,0)], fp->samples_per_subframe * 4)); - int slot_type = nr_slot_select(cfg,frame,slot%fp->slots_per_frame); int prevslot_type = nr_slot_select(cfg,frame,(slot+(fp->slots_per_frame-1))%fp->slots_per_frame); int nextslot_type = nr_slot_select(cfg,frame,(slot+1)%fp->slots_per_frame); @@ -716,20 +710,23 @@ void tx_rf(RU_t *ru,int frame,int slot, uint64_t timestamp) { //nr_subframe_t SF_type = nr_slot_select(cfg,slot%fp->slots_per_frame); if (slot_type == NR_DOWNLINK_SLOT || slot_type == NR_MIXED_SLOT || IS_SOFTMODEM_RFSIM) { - - if (cfg->cell_config.frame_duplex_type.value == TDD){ + if (cfg->cell_config.frame_duplex_type.value == TDD) { if(slot_type == NR_MIXED_SLOT) { txsymb = 0; + for(int symbol_count = 0; symbol_counttdd_table.max_tdd_periodicity_list[slot].max_num_of_symbol_per_slot_list[symbol_count].slot_config.value == 0) txsymb++; } + AssertFatal(txsymb>0,"illegal txsymb %d\n",txsymb); + if(slot%(fp->slots_per_subframe/2)) siglen = txsymb * (fp->ofdm_symbol_size + fp->nb_prefix_samples); else siglen = (fp->ofdm_symbol_size + fp->nb_prefix_samples0) + (txsymb - 1) * (fp->ofdm_symbol_size + fp->nb_prefix_samples); - //+ ru->end_of_burst_delay; + + //+ ru->end_of_burst_delay; flags = 3; // end of burst } @@ -745,11 +742,13 @@ void tx_rf(RU_t *ru,int frame,int slot, uint64_t timestamp) { // bit 11 enables the gpio programming // currently we switch beams every 10 slots (should = 1 TDD period in FR2) and we take the beam index of the first symbol of the first slot of this period int beam=0; + if (slot%10==0) { - if (ru->common.beam_id[0][slot*fp->symbols_per_slot] < 8) { - beam = ru->common.beam_id[0][slot*fp->symbols_per_slot] | 8; - } + if (ru->common.beam_id[0][slot*fp->symbols_per_slot] < 8) { + beam = ru->common.beam_id[0][slot*fp->symbols_per_slot] | 8; + } } + /* if (slot==0 || slot==40) beam=0|8; if (slot==10 || slot==50) beam=1|8; @@ -757,30 +756,29 @@ void tx_rf(RU_t *ru,int frame,int slot, uint64_t timestamp) { if (slot==30 || slot==70) beam=3|8; */ flags |= beam<<8; - LOG_D(HW,"slot %d, beam %d\n",slot,ru->common.beam_id[0][slot*fp->symbols_per_slot]); - } - - 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_TRX_WRITE_FLAGS, flags ); VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_TX0_RU, frame ); VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TTI_NUMBER_TX0_RU, slot ); + for (i=0; inb_tx; i++) txp[i] = (void *)&ru->common.txdata[i][fp->get_samples_slot_timestamp(slot,fp,0)-sf_extension]; - - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TST, (timestamp-ru->openair0_cfg.tx_sample_advance)&0xffffffff ); - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE, 1 ); - // prepare tx buffer pointers - txs = ru->rfdevice.trx_write_func(&ru->rfdevice, - timestamp+ru->ts_offset-ru->openair0_cfg.tx_sample_advance-sf_extension, - txp, - siglen+sf_extension, - ru->nb_tx, - flags); - LOG_D(PHY,"[TXPATH] RU %d tx_rf, writing to TS %llu, frame %d, unwrapped_frame %d, slot %di, returned %d\n",ru->idx, - (long long unsigned int)timestamp,frame,proc->frame_tx_unwrap,slot, txs); - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE, 0 ); - //AssertFatal(txs == 0,"trx write function error %d\n", txs); + + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TST, (timestamp-ru->openair0_cfg.tx_sample_advance)&0xffffffff ); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE, 1 ); + // prepare tx buffer pointers + txs = ru->rfdevice.trx_write_func(&ru->rfdevice, + timestamp+ru->ts_offset-ru->openair0_cfg.tx_sample_advance-sf_extension, + txp, + siglen+sf_extension, + ru->nb_tx, + flags); + LOG_D(PHY,"[TXPATH] RU %d tx_rf, writing to TS %llu, frame %d, unwrapped_frame %d, slot %di, returned %d\n",ru->idx, + (long long unsigned int)timestamp,frame,proc->frame_tx_unwrap,slot, txs); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE, 0 ); + //AssertFatal(txs == 0,"trx write function error %d\n", txs); } } @@ -795,179 +793,194 @@ void fill_rf_config(RU_t *ru, char *rf_config_file) { if (mu == NR_MU_0) { switch(N_RB) { - case 270: - if (fp->threequarter_fs) { - cfg->sample_rate=92.16e6; - cfg->samples_per_frame = 921600; - cfg->tx_bw = 50e6; - cfg->rx_bw = 50e6; - } else { - cfg->sample_rate=61.44e6; - cfg->samples_per_frame = 614400; - cfg->tx_bw = 50e6; - cfg->rx_bw = 50e6; - } - case 216: - if (fp->threequarter_fs) { - cfg->sample_rate=46.08e6; - cfg->samples_per_frame = 460800; - cfg->tx_bw = 40e6; - cfg->rx_bw = 40e6; - } - else { - cfg->sample_rate=61.44e6; - cfg->samples_per_frame = 614400; - cfg->tx_bw = 40e6; - cfg->rx_bw = 40e6; - } - break; - case 106: - if (fp->threequarter_fs) { - cfg->sample_rate=23.04e6; - cfg->samples_per_frame = 230400; - cfg->tx_bw = 20e6; - cfg->rx_bw = 20e6; - } - else { - cfg->sample_rate=30.72e6; - cfg->samples_per_frame = 307200; - cfg->tx_bw = 20e6; - cfg->rx_bw = 20e6; - } - break; - case 52: - if (fp->threequarter_fs) { - cfg->sample_rate=11.52e6; - cfg->samples_per_frame = 115200; - cfg->tx_bw = 10e6; - cfg->rx_bw = 10e6; - } - else { - cfg->sample_rate=15.36e6; - cfg->samples_per_frame = 153600; - cfg->tx_bw = 10e6; - cfg->rx_bw = 10e6; - } - case 25: - if (fp->threequarter_fs) { - cfg->sample_rate=5.76e6; - cfg->samples_per_frame = 57600; - cfg->tx_bw = 5e6; - cfg->rx_bw = 5e6; - } - else { - cfg->sample_rate=7.68e6; - cfg->samples_per_frame = 76800; - cfg->tx_bw = 5e6; - cfg->rx_bw = 5e6; - } - break; - default: - AssertFatal(0==1,"N_RB %d not yet supported for numerology %d\n",N_RB,mu); + case 270: + if (fp->threequarter_fs) { + cfg->sample_rate=92.16e6; + cfg->samples_per_frame = 921600; + cfg->tx_bw = 50e6; + cfg->rx_bw = 50e6; + } else { + cfg->sample_rate=61.44e6; + cfg->samples_per_frame = 614400; + cfg->tx_bw = 50e6; + cfg->rx_bw = 50e6; + } + + case 216: + if (fp->threequarter_fs) { + cfg->sample_rate=46.08e6; + cfg->samples_per_frame = 460800; + cfg->tx_bw = 40e6; + cfg->rx_bw = 40e6; + } else { + cfg->sample_rate=61.44e6; + cfg->samples_per_frame = 614400; + cfg->tx_bw = 40e6; + cfg->rx_bw = 40e6; + } + + break; + + case 106: + if (fp->threequarter_fs) { + cfg->sample_rate=23.04e6; + cfg->samples_per_frame = 230400; + cfg->tx_bw = 20e6; + cfg->rx_bw = 20e6; + } else { + cfg->sample_rate=30.72e6; + cfg->samples_per_frame = 307200; + cfg->tx_bw = 20e6; + cfg->rx_bw = 20e6; + } + + break; + + case 52: + if (fp->threequarter_fs) { + cfg->sample_rate=11.52e6; + cfg->samples_per_frame = 115200; + cfg->tx_bw = 10e6; + cfg->rx_bw = 10e6; + } else { + cfg->sample_rate=15.36e6; + cfg->samples_per_frame = 153600; + cfg->tx_bw = 10e6; + cfg->rx_bw = 10e6; + } + + case 25: + if (fp->threequarter_fs) { + cfg->sample_rate=5.76e6; + cfg->samples_per_frame = 57600; + cfg->tx_bw = 5e6; + cfg->rx_bw = 5e6; + } else { + cfg->sample_rate=7.68e6; + cfg->samples_per_frame = 76800; + cfg->tx_bw = 5e6; + cfg->rx_bw = 5e6; + } + + break; + + default: + AssertFatal(0==1,"N_RB %d not yet supported for numerology %d\n",N_RB,mu); } } else if (mu == NR_MU_1) { switch(N_RB) { - case 273: - if (fp->threequarter_fs) { - cfg->sample_rate=184.32e6; - cfg->samples_per_frame = 1843200; - cfg->tx_bw = 100e6; - cfg->rx_bw = 100e6; - } else { - cfg->sample_rate=122.88e6; - cfg->samples_per_frame = 1228800; - cfg->tx_bw = 100e6; - cfg->rx_bw = 100e6; - } - break; - case 217: - if (fp->threequarter_fs) { - cfg->sample_rate=92.16e6; - cfg->samples_per_frame = 921600; - cfg->tx_bw = 80e6; - cfg->rx_bw = 80e6; - } else { - cfg->sample_rate=122.88e6; - cfg->samples_per_frame = 1228800; - cfg->tx_bw = 80e6; - cfg->rx_bw = 80e6; - } - break; - case 106: - if (fp->threequarter_fs) { - cfg->sample_rate=46.08e6; - cfg->samples_per_frame = 460800; - cfg->tx_bw = 40e6; - cfg->rx_bw = 40e6; - } - else { - cfg->sample_rate=61.44e6; - cfg->samples_per_frame = 614400; - cfg->tx_bw = 40e6; - cfg->rx_bw = 40e6; - } - break; - case 51: - if (fp->threequarter_fs) { - cfg->sample_rate=23.04e6; - cfg->samples_per_frame = 230400; - cfg->tx_bw = 20e6; - cfg->rx_bw = 20e6; - } - else { - cfg->sample_rate=30.72e6; - cfg->samples_per_frame = 307200; - cfg->tx_bw = 20e6; - cfg->rx_bw = 20e6; - } - break; - case 24: - if (fp->threequarter_fs) { - cfg->sample_rate=11.52e6; - cfg->samples_per_frame = 115200; - cfg->tx_bw = 10e6; - cfg->rx_bw = 10e6; - } - else { - cfg->sample_rate=15.36e6; - cfg->samples_per_frame = 153600; - cfg->tx_bw = 10e6; - cfg->rx_bw = 10e6; - } - break; - default: - AssertFatal(0==1,"N_RB %d not yet supported for numerology %d\n",N_RB,mu); + case 273: + if (fp->threequarter_fs) { + cfg->sample_rate=184.32e6; + cfg->samples_per_frame = 1843200; + cfg->tx_bw = 100e6; + cfg->rx_bw = 100e6; + } else { + cfg->sample_rate=122.88e6; + cfg->samples_per_frame = 1228800; + cfg->tx_bw = 100e6; + cfg->rx_bw = 100e6; + } + + break; + + case 217: + if (fp->threequarter_fs) { + cfg->sample_rate=92.16e6; + cfg->samples_per_frame = 921600; + cfg->tx_bw = 80e6; + cfg->rx_bw = 80e6; + } else { + cfg->sample_rate=122.88e6; + cfg->samples_per_frame = 1228800; + cfg->tx_bw = 80e6; + cfg->rx_bw = 80e6; + } + + break; + + case 106: + if (fp->threequarter_fs) { + cfg->sample_rate=46.08e6; + cfg->samples_per_frame = 460800; + cfg->tx_bw = 40e6; + cfg->rx_bw = 40e6; + } else { + cfg->sample_rate=61.44e6; + cfg->samples_per_frame = 614400; + cfg->tx_bw = 40e6; + cfg->rx_bw = 40e6; + } + + break; + + case 51: + if (fp->threequarter_fs) { + cfg->sample_rate=23.04e6; + cfg->samples_per_frame = 230400; + cfg->tx_bw = 20e6; + cfg->rx_bw = 20e6; + } else { + cfg->sample_rate=30.72e6; + cfg->samples_per_frame = 307200; + cfg->tx_bw = 20e6; + cfg->rx_bw = 20e6; + } + + break; + + case 24: + if (fp->threequarter_fs) { + cfg->sample_rate=11.52e6; + cfg->samples_per_frame = 115200; + cfg->tx_bw = 10e6; + cfg->rx_bw = 10e6; + } else { + cfg->sample_rate=15.36e6; + cfg->samples_per_frame = 153600; + cfg->tx_bw = 10e6; + cfg->rx_bw = 10e6; + } + + break; + + default: + AssertFatal(0==1,"N_RB %d not yet supported for numerology %d\n",N_RB,mu); } } else if (mu == NR_MU_3) { switch(N_RB) { - case 66: - if (fp->threequarter_fs) { - cfg->sample_rate=184.32e6; - cfg->samples_per_frame = 1843200; - cfg->tx_bw = 100e6; - cfg->rx_bw = 100e6; - } else { - cfg->sample_rate = 122.88e6; - cfg->samples_per_frame = 1228800; - cfg->tx_bw = 100e6; - cfg->rx_bw = 100e6; - } - break; - case 32: - if (fp->threequarter_fs) { - cfg->sample_rate=92.16e6; - cfg->samples_per_frame = 921600; - cfg->tx_bw = 50e6; - cfg->rx_bw = 50e6; - } else { - cfg->sample_rate=61.44e6; - cfg->samples_per_frame = 614400; - cfg->tx_bw = 50e6; - cfg->rx_bw = 50e6; - } - break; - default: - AssertFatal(0==1,"N_RB %d not yet supported for numerology %d\n",N_RB,mu); + case 66: + if (fp->threequarter_fs) { + cfg->sample_rate=184.32e6; + cfg->samples_per_frame = 1843200; + cfg->tx_bw = 100e6; + cfg->rx_bw = 100e6; + } else { + cfg->sample_rate = 122.88e6; + cfg->samples_per_frame = 1228800; + cfg->tx_bw = 100e6; + cfg->rx_bw = 100e6; + } + + break; + + case 32: + if (fp->threequarter_fs) { + cfg->sample_rate=92.16e6; + cfg->samples_per_frame = 921600; + cfg->tx_bw = 50e6; + cfg->rx_bw = 50e6; + } else { + cfg->sample_rate=61.44e6; + cfg->samples_per_frame = 614400; + cfg->tx_bw = 50e6; + cfg->rx_bw = 50e6; + } + + break; + + default: + AssertFatal(0==1,"N_RB %d not yet supported for numerology %d\n",N_RB,mu); } } else { AssertFatal(0 == 1,"Numerology %d not supported for the moment\n",mu); @@ -987,7 +1000,7 @@ void fill_rf_config(RU_t *ru, char *rf_config_file) { if (ru->if_frequency == 0) { cfg->tx_freq[i] = (double)fp->dl_CarrierFreq; cfg->rx_freq[i] = (double)fp->ul_CarrierFreq; - } else if (ru->if_freq_offset){ + } else if (ru->if_freq_offset) { cfg->tx_freq[i] = (double)(ru->if_frequency); cfg->rx_freq[i] = (double)(ru->if_frequency + ru->if_freq_offset); LOG_I(PHY, "Setting IF TX frequency to %lu Hz with IF RX frequency offset %d Hz\n", ru->if_frequency, ru->if_freq_offset); @@ -995,14 +1008,15 @@ void fill_rf_config(RU_t *ru, char *rf_config_file) { cfg->tx_freq[i] = (double)ru->if_frequency; cfg->rx_freq[i] = (double)(ru->if_frequency+fp->ul_CarrierFreq-fp->dl_CarrierFreq); } + cfg->tx_gain[i] = ru->att_tx; cfg->rx_gain[i] = ru->max_rxgain-ru->att_rx; cfg->configFilename = rf_config_file; LOG_I(PHY, "Channel %d: setting tx_gain offset %f, rx_gain offset %f, tx_freq %lu Hz, rx_freq %lu Hz\n", - i, cfg->tx_gain[i], - cfg->rx_gain[i], - (unsigned long)cfg->tx_freq[i], - (unsigned long)cfg->rx_freq[i]); + i, cfg->tx_gain[i], + cfg->rx_gain[i], + (unsigned long)cfg->tx_freq[i], + (unsigned long)cfg->rx_freq[i]); } } @@ -1030,40 +1044,42 @@ int setup_RU_buffers(RU_t *ru) { if (config->cell_config.frame_duplex_type.value == TDD) { int N_TA_offset = config->carrier_config.uplink_frequency.value < 6000000 ? 400 : 431; // reference samples for 25600Tc @ 30.72 Ms/s for FR1, same @ 61.44 Ms/s for FR2 - double factor=1; + switch (mu) { case 0: //15 kHz scs AssertFatal(N_TA_offset == 400, "scs_common 15kHz only for FR1\n"); factor = fp->samples_per_subframe / 30720.0; break; + case 1: //30 kHz sc AssertFatal(N_TA_offset == 400, "scs_common 30kHz only for FR1\n"); factor = fp->samples_per_subframe / 30720.0; break; + case 2: //60 kHz scs AssertFatal(1==0, "scs_common should not be 60 kHz\n"); break; + case 3: //120 kHz scs AssertFatal(N_TA_offset == 431, "scs_common 120kHz only for FR2\n"); factor = fp->samples_per_subframe / 61440.0; break; + case 4: //240 kHz scs AssertFatal(N_TA_offset == 431, "scs_common 240kHz only for FR2\n"); factor = fp->samples_per_subframe / 61440.0; break; + default: AssertFatal(1==0, "Invalid scs_common!\n"); } ru->N_TA_offset = (int)(N_TA_offset * factor); - LOG_I(PHY,"RU %d Setting N_TA_offset to %d samples (factor %f, UL Freq %d, N_RB %d, mu %d)\n",ru->idx,ru->N_TA_offset,factor, - config->carrier_config.uplink_frequency.value, N_RB, mu); - } - else ru->N_TA_offset = 0; + config->carrier_config.uplink_frequency.value, N_RB, mu); + } else ru->N_TA_offset = 0; - if (ru->openair0_cfg.mmapped_dma == 1) { // replace RX signal buffers with mmaped HW versions for (i=0; inb_rx; i++) { @@ -1108,7 +1124,6 @@ void *ru_stats_thread(void *param) { sleep(1); if (opp_enabled == 1) { - if (ru->feprx) print_meas(&ru->ofdm_demod_stats,"feprx",NULL,NULL); if (ru->feptx_ofdm) { @@ -1121,6 +1136,7 @@ void *ru_stats_thread(void *param) { if (ru->fh_north_asynch_in) print_meas(&ru->rx_fhaul,"rx_fhaul",NULL,NULL); 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); @@ -1132,7 +1148,6 @@ void *ru_stats_thread(void *param) { } 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; @@ -1155,14 +1170,11 @@ void ru_tx_func(void *param) { } else { if(frame_tx == print_frame) { for (int i=0; inb_tx; 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); } @@ -1199,18 +1211,13 @@ void *ru_thread( void *param ) { int frame = 1023; char threadname[40]; int aa; - nfapi_nr_config_request_scf_t *cfg = &ru->config; - // set default return value ru_thread_status = 0; // set default return value sprintf(threadname,"ru_thread %u",ru->idx); - - LOG_I(PHY,"Starting RU %d (%s,%s),\n",ru->idx,NB_functions[ru->function],NB_timing[ru->if_timing]); - - memcpy((void*)&ru->config,(void*)&RC.gNB[0]->gNB_config,sizeof(ru->config)); + memcpy((void *)&ru->config,(void *)&RC.gNB[0]->gNB_config,sizeof(ru->config)); if(emulate_rf) { fill_rf_config(ru,ru->rf_config_file); @@ -1256,12 +1263,11 @@ void *ru_thread( void *param ) { pthread_cond_signal(&RC.ru_cond); pthread_mutex_unlock(&RC.ru_mutex); wait_sync("ru_thread"); - notifiedFIFO_elt_t *msg = newNotifiedFIFO_elt(sizeof(processingData_L1_t),0,gNB->resp_L1,rx_func); notifiedFIFO_elt_t *msgL1Tx = newNotifiedFIFO_elt(sizeof(processingData_L1_t),0,gNB->resp_L1_tx,tx_func); notifiedFIFO_elt_t *msgRUTx = newNotifiedFIFO_elt(sizeof(processingData_L1_t),0,gNB->resp_RU_tx,ru_tx_func); processingData_L1_t *syncMsg; - notifiedFIFO_elt_t *res; + notifiedFIFO_elt_t *res; pushNotifiedFIFO(gNB->resp_L1,msg); // to unblock the process in the beginning pushNotifiedFIFO(gNB->resp_L1_tx,msgL1Tx); // to unblock the process in the beginning pushNotifiedFIFO(gNB->resp_RU_tx,msgRUTx); // to unblock the process in the beginning @@ -1275,12 +1281,11 @@ void *ru_thread( void *param ) { } else LOG_I(PHY,"RU %d no rf device\n",ru->idx); // start trx write thread - if(usrp_tx_thread == 1){ - if (ru->start_write_thread){ - if(ru->start_write_thread(ru) != 0){ + 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{ + } else { LOG_I(PHY,"tx write thread ready\n"); } } @@ -1301,76 +1306,75 @@ 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"); proc->timestamp_tx = proc->timestamp_rx + (sf_ahead*fp->samples_per_subframe); proc->frame_tx = (proc->tti_rx > (fp->slots_per_frame-1-(fp->slots_per_subframe*sf_ahead))) ? (proc->frame_rx+1)&1023 : proc->frame_rx; proc->tti_tx = (proc->tti_rx + (fp->slots_per_subframe*sf_ahead))%fp->slots_per_frame; - LOG_D(PHY,"AFTER fh_south_in - SFN/SL:%d%d RU->proc[RX:%d.%d TX:%d.%d] RC.gNB[0]:[RX:%d%d TX(SFN):%d]\n", frame,slot, proc->frame_rx,proc->tti_rx, proc->frame_tx,proc->tti_tx, RC.gNB[0]->proc.frame_rx,RC.gNB[0]->proc.slot_rx, - RC.gNB[0]->proc.frame_tx); + RC.gNB[0]->proc.frame_tx); if (ru->idx!=0) proc->frame_tx = (proc->frame_tx+proc->frame_offset)&1023; // do RX front-end processing (frequency-shift, dft) if needed - int slot_type = nr_slot_select(cfg,proc->frame_rx,proc->tti_rx); + if (slot_type == NR_UPLINK_SLOT || slot_type == NR_MIXED_SLOT) { - if (ru->feprx) { - ru->feprx(ru,proc->tti_rx); - //LOG_M("rxdata.m","rxs",ru->common.rxdata[0],1228800,1,1); + ru->feprx(ru,proc->tti_rx); + //LOG_M("rxdata.m","rxs",ru->common.rxdata[0],1228800,1,1); + LOG_D(PHY,"RU proc: frame_rx = %d, tti_rx = %d\n", proc->frame_rx, proc->tti_rx); + LOG_D(PHY,"Copying rxdataF from RU to gNB\n"); - LOG_D(PHY,"RU proc: frame_rx = %d, tti_rx = %d\n", proc->frame_rx, proc->tti_rx); - LOG_D(PHY,"Copying rxdataF from RU to gNB\n"); - - for (aa=0;aanb_rx;aa++) - memcpy((void*)RC.gNB[0]->common_vars.rxdataF[aa], - (void*)ru->common.rxdataF[aa], fp->symbols_per_slot*fp->ofdm_symbol_size*sizeof(int32_t)); - if (IS_SOFTMODEM_DOSCOPE && RC.gNB[0]->scopeData) - ((scopeData_t*)RC.gNB[0]->scopeData)->slotFunc(ru->common.rxdataF[0],proc->tti_rx, RC.gNB[0]->scopeData); - // Do PRACH RU processing + for (aa=0; aanb_rx; aa++) + memcpy((void *)RC.gNB[0]->common_vars.rxdataF[aa], + (void *)ru->common.rxdataF[aa], fp->symbols_per_slot*fp->ofdm_symbol_size*sizeof(int32_t)); - int prach_id=find_nr_prach_ru(ru,proc->frame_rx,proc->tti_rx,SEARCH_EXIST); - uint8_t prachStartSymbol,N_dur; - if (prach_id>=0) { + if (IS_SOFTMODEM_DOSCOPE && RC.gNB[0]->scopeData) + ((scopeData_t *)RC.gNB[0]->scopeData)->slotFunc(ru->common.rxdataF[0],proc->tti_rx, RC.gNB[0]->scopeData); - T(T_GNB_PHY_PRACH_INPUT_SIGNAL, T_INT(proc->frame_rx), T_INT(proc->tti_rx), T_INT(0), - T_BUFFER(&ru->common.rxdata[0][fp->get_samples_slot_timestamp(proc->tti_rx-1,fp,0)]/*-ru->N_TA_offset*/, fp->get_samples_per_slot(proc->tti_rx,fp)*4*2)); + // Do PRACH RU processing + int prach_id=find_nr_prach_ru(ru,proc->frame_rx,proc->tti_rx,SEARCH_EXIST); + uint8_t prachStartSymbol,N_dur; - N_dur = get_nr_prach_duration(ru->prach_list[prach_id].fmt); - /* - get_nr_prach_info_from_index(ru->config.prach_config.prach_ConfigurationIndex.value, - proc->frame_rx,proc->tti_rx, - ru->config.carrier_config.dl_frequency.value, - fp->numerology_index, - fp->frame_type, - &format, - &start_symbol, - &N_t_slot, - &N_dur, - &RA_sfn_index, - &N_RA_slot, - &config_period); - */ - for (int prach_oc = 0; prach_ocprach_list[prach_id].num_prach_ocas; prach_oc++) { - prachStartSymbol = ru->prach_list[prach_id].prachStartSymbol+prach_oc*N_dur; - //comment FK: the standard 38.211 section 5.3.2 has one extra term +14*N_RA_slot. This is because there prachStartSymbol is given wrt to start of the 15kHz slot or 60kHz slot. Here we work slot based, so this function is anyway only called in slots where there is PRACH. Its up to the MAC to schedule another PRACH PDU in the case there are there N_RA_slot \in {0,1}. + if (prach_id>=0) { + T(T_GNB_PHY_PRACH_INPUT_SIGNAL, T_INT(proc->frame_rx), T_INT(proc->tti_rx), T_INT(0), + T_BUFFER(&ru->common.rxdata[0][fp->get_samples_slot_timestamp(proc->tti_rx-1,fp,0)]/*-ru->N_TA_offset*/, fp->get_samples_per_slot(proc->tti_rx,fp)*4*2)); + N_dur = get_nr_prach_duration(ru->prach_list[prach_id].fmt); - rx_nr_prach_ru(ru, - ru->prach_list[prach_id].fmt, //could also use format - ru->prach_list[prach_id].numRA, - prachStartSymbol, - prach_oc, - proc->frame_rx,proc->tti_rx); - } - free_nr_ru_prach_entry(ru,prach_id); - } + /* + get_nr_prach_info_from_index(ru->config.prach_config.prach_ConfigurationIndex.value, + proc->frame_rx,proc->tti_rx, + ru->config.carrier_config.dl_frequency.value, + fp->numerology_index, + fp->frame_type, + &format, + &start_symbol, + &N_t_slot, + &N_dur, + &RA_sfn_index, + &N_RA_slot, + &config_period); + */ + for (int prach_oc = 0; prach_ocprach_list[prach_id].num_prach_ocas; prach_oc++) { + prachStartSymbol = ru->prach_list[prach_id].prachStartSymbol+prach_oc*N_dur; + //comment FK: the standard 38.211 section 5.3.2 has one extra term +14*N_RA_slot. This is because there prachStartSymbol is given wrt to start of the 15kHz slot or 60kHz slot. Here we work slot based, so this function is anyway only called in slots where there is PRACH. Its up to the MAC to schedule another PRACH PDU in the case there are there N_RA_slot \in {0,1}. + rx_nr_prach_ru(ru, + ru->prach_list[prach_id].fmt, //could also use format + ru->prach_list[prach_id].numRA, + prachStartSymbol, + prach_oc, + proc->frame_rx,proc->tti_rx); + } + + free_nr_ru_prach_entry(ru,prach_id); + } } } @@ -1385,7 +1389,6 @@ void *ru_thread( void *param ) { syncMsg->timestamp_tx = proc->timestamp_tx; res->key = proc->tti_rx; pushTpool(gNB->threadPool, res); - } printf( "Exiting ru_thread \n"); @@ -1399,7 +1402,6 @@ void *ru_thread( void *param ) { delNotifiedFIFO_elt(msg); delNotifiedFIFO_elt(msgL1Tx); delNotifiedFIFO_elt(msgRUTx); - ru_thread_status = 0; return &ru_thread_status; } @@ -1490,8 +1492,7 @@ void kill_NR_RU_proc(int inst) { } } -int check_capabilities(RU_t *ru,RRU_capabilities_t *cap) -{ +int check_capabilities(RU_t *ru,RRU_capabilities_t *cap) { FH_fmt_options_t fmt = cap->FH_fmt; int i; int found_band=0; @@ -1547,8 +1548,7 @@ char rru_formats[3][20] = {"OAI_IF5","MBP_IF5","OAI_IF4p5"}; char ru_if_formats[4][20] = {"LOCAL_RF","REMOTE_OAI_IF5","REMOTE_MBP_IF5","REMOTE_OAI_IF4p5"}; void configure_ru(int idx, - void *arg) -{ + void *arg) { RU_t *ru = RC.ru[idx]; RRU_config_t *config = (RRU_config_t *)arg; RRU_capabilities_t *capabilities = (RRU_capabilities_t *)arg; @@ -1721,26 +1721,25 @@ void set_function_spec_param(RU_t *ru) { ru->fh_north_out = NULL; // no outgoing fronthaul to north ru->nr_start_if = NULL; // no if interface ru->rfdevice.host_type = RAU_HOST; - - ru->fh_south_in = rx_rf; // local synchronous RF RX - ru->fh_south_out = tx_rf; // local synchronous RF TX - ru->start_rf = start_rf; // need to start the local RF interface - ru->stop_rf = stop_rf; - ru->start_write_thread = start_write_thread; // starting RF TX in different thread - printf("configuring ru_id %u (start_rf %p)\n", ru->idx, start_rf); + ru->fh_south_in = rx_rf; // local synchronous RF RX + ru->fh_south_out = tx_rf; // local synchronous RF TX + ru->start_rf = start_rf; // need to start the local RF interface + ru->stop_rf = stop_rf; + ru->start_write_thread = start_write_thread; // starting RF TX in different thread + printf("configuring ru_id %u (start_rf %p)\n", ru->idx, start_rf); } /* - printf("configuring ru_id %u (start_rf %p)\n", ru->idx, start_rf); - fill_rf_config(ru,rf_config_file); - init_frame_parms(&ru->frame_parms,1); - nr_phy_init_RU(ru); + printf("configuring ru_id %u (start_rf %p)\n", ru->idx, start_rf); + 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) { - printf("Exiting, cannot initialize RU Buffers\n"); - exit(-1); - } + ret = openair0_device_load(&ru->rfdevice,&ru->openair0_cfg); + if (setup_RU_buffers(ru)!=0) { + printf("Exiting, cannot initialize RU Buffers\n"); + exit(-1); + } */ break; @@ -1796,9 +1795,12 @@ void set_function_spec_param(RU_t *ru) { if (ru->ifdevice.get_internal_parameter != NULL) { 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; } @@ -1812,8 +1814,7 @@ void set_function_spec_param(RU_t *ru) { } // switch on interface type } -void init_NR_RU(char *rf_config_file) -{ +void init_NR_RU(char *rf_config_file) { int ru_id; RU_t *ru; PHY_VARS_gNB *gNB_RC; @@ -1828,7 +1829,6 @@ void init_NR_RU(char *rf_config_file) printf("configuring RU from file\n"); NRRCconfig_RU(); 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_idopenair0_cfg.clock_source = internal; } @@ -1965,10 +1962,9 @@ static void NRRCconfig_RU(void) } else { LOG_E(PHY, "Erroneous RU time source in the provided configuration file: '%s'\n", *(RUParamList.paramarray[j][RU_SDR_CLK_SRC].strptr)); } - } - else { + } else { LOG_I(PHY,"Setting time source to internal\n"); - RC.ru[j]->openair0_cfg.time_source = internal; + RC.ru[j]->openair0_cfg.time_source = internal; } if (strcmp(*(RUParamList.paramarray[j][RU_LOCAL_RF_IDX].strptr), "yes") == 0) { @@ -2052,8 +2048,10 @@ static void NRRCconfig_RU(void) if (config_isparamset(RUParamList.paramarray[j], RU_BF_WEIGHTS_LIST_IDX)) { RC.ru[j]->nb_bfw = RUParamList.paramarray[j][RU_BF_WEIGHTS_LIST_IDX].numelt; + for (i=0; inum_gNB; i++) { RC.ru[j]->bw_list[i] = (int32_t *)malloc16_clear((RC.ru[j]->nb_bfw)*sizeof(int32_t)); + for (int b=0; bnb_bfw; b++) RC.ru[j]->bw_list[i][b] = RUParamList.paramarray[j][RU_BF_WEIGHTS_LIST_IDX].iptr[b]; } } diff --git a/executables/nr-softmodem.c b/executables/nr-softmodem.c index 4727d09b04..5afc576bbb 100644 --- a/executables/nr-softmodem.c +++ b/executables/nr-softmodem.c @@ -170,8 +170,9 @@ int split73=0; void sendFs6Ul(PHY_VARS_eNB *eNB, int UE_id, int harq_pid, int segmentID, int16_t *data, int dataLen, int r_offset) { AssertFatal(false, "Must not be called in this context\n"); } -void sendFs6Ulharq(enum pckType type, int UEid, PHY_VARS_eNB *eNB, LTE_eNB_UCI *uci, int frame, int subframe, uint8_t *harq_ack, uint8_t tdd_mapping_mode, uint16_t tdd_multiplexing_mask, uint16_t rnti, int32_t stat) { - AssertFatal(false, "Must not be called in this context\n"); +void sendFs6Ulharq(enum pckType type, int UEid, PHY_VARS_eNB *eNB, LTE_eNB_UCI *uci, int frame, int subframe, uint8_t *harq_ack, uint8_t tdd_mapping_mode, uint16_t tdd_multiplexing_mask, + uint16_t rnti, int32_t stat) { + AssertFatal(false, "Must not be called in this context\n"); } @@ -307,44 +308,40 @@ int create_gNB_tasks(uint32_t gnb_nb) { LOG_D(GNB_APP, "%s(gnb_nb:%d)\n", __FUNCTION__, gnb_nb); itti_wait_ready(1); - if (gnb_nb > 0) { /* Last task to create, others task must be ready before its start */ /*if (itti_create_task (TASK_GNB_APP, gNB_app_task, NULL) < 0) { LOG_E(GNB_APP, "Create task for gNB APP failed\n"); return -1; }*/ - if(itti_create_task(TASK_SCTP, sctp_eNB_task, NULL) < 0){ + if(itti_create_task(TASK_SCTP, sctp_eNB_task, NULL) < 0) { LOG_E(SCTP, "Create task for SCTP failed\n"); return -1; } + if (is_x2ap_enabled()) { - if(itti_create_task(TASK_X2AP, x2ap_task, NULL) < 0){ - LOG_E(X2AP, "Create task for X2AP failed\n"); - } - } - else { + if(itti_create_task(TASK_X2AP, x2ap_task, NULL) < 0) { + LOG_E(X2AP, "Create task for X2AP failed\n"); + } + } else { LOG_I(X2AP, "X2AP is disabled.\n"); } } - + paramdef_t NETParams[] = GNBNETPARAMS_DESC; char aprefix[MAX_OPTNAME_SIZE*2 + 8]; sprintf(aprefix,"%s.[%i].%s",GNB_CONFIG_STRING_GNB_LIST,0,GNB_CONFIG_STRING_NETWORK_INTERFACES_CONFIG); - config_get( NETParams,sizeof(NETParams)/sizeof(paramdef_t),aprefix); + config_get( NETParams,sizeof(NETParams)/sizeof(paramdef_t),aprefix); - for(int i = GNB_INTERFACE_NAME_FOR_NG_AMF_IDX; i <= GNB_IPV4_ADDRESS_FOR_NG_AMF_IDX; i++){ - if( NETParams[i].strptr == NULL){ + for(int i = GNB_INTERFACE_NAME_FOR_NG_AMF_IDX; i <= GNB_IPV4_ADDRESS_FOR_NG_AMF_IDX; i++) { + if( NETParams[i].strptr == NULL) { LOG_E(NGAP, "No configuration in the file.\n"); - NGAP_CONF_MODE = 0; - } - else { + NGAP_CONF_MODE = 0; + } else { LOG_D(NGAP, "Configuration in the file: %s.\n",*NETParams[i].strptr); } - } - if (AMF_MODE_ENABLED) { if (gnb_nb > 0) { /* @@ -353,17 +350,16 @@ int create_gNB_tasks(uint32_t gnb_nb) { return -1; } */ - if(NGAP_CONF_MODE){ + if(NGAP_CONF_MODE) { if (itti_create_task (TASK_NGAP, ngap_gNB_task, NULL) < 0) { LOG_E(NGAP, "Create task for NGAP failed\n"); return -1; } } else { - LOG_E(NGAP, "Ngap task not created\n"); + LOG_E(NGAP, "Ngap task not created\n"); } - - if(!emulate_rf){ + if(!emulate_rf) { if (itti_create_task (TASK_UDP, udp_eNB_task, NULL) < 0) { LOG_E(UDP_, "Create task for UDP failed\n"); return -1; @@ -384,12 +380,14 @@ int create_gNB_tasks(uint32_t gnb_nb) { } LOG_I(NR_RRC,"Creating NR RRC gNB Task\n"); + if (itti_create_task (TASK_RRC_GNB, rrc_gnb_task, NULL) < 0) { LOG_E(NR_RRC, "Create task for NR RRC gNB failed\n"); return -1; } - //Use check on x2ap to consider the NSA scenario and check on AMF_MODE_ENABLED for the SA scenario - if(is_x2ap_enabled() || AMF_MODE_ENABLED){ + + //Use check on x2ap to consider the NSA scenario and check on AMF_MODE_ENABLED for the SA scenario + if(is_x2ap_enabled() || AMF_MODE_ENABLED) { if (itti_create_task (TASK_GTPV1_U, &nr_gtpv1u_gNB_task, NULL) < 0) { LOG_E(GTPU, "Create task for GTPV1U failed\n"); return -1; @@ -402,18 +400,12 @@ int create_gNB_tasks(uint32_t gnb_nb) { static void get_options(void) { - - paramdef_t cmdline_params[] = CMDLINE_PARAMS_DESC_GNB ; - CONFIG_SETRTFLAG(CONFIG_NOEXITONHELP); get_common_options(SOFTMODEM_GNB_BIT ); config_process_cmdline( cmdline_params,sizeof(cmdline_params)/sizeof(paramdef_t),NULL); CONFIG_CLEARRTFLAG(CONFIG_NOEXITONHELP); - - - if ( !(CONFIG_ISFLAGSET(CONFIG_ABORT)) ) { memset((void *)&RC,0,sizeof(RC)); /* Read RC configuration file */ @@ -426,13 +418,11 @@ static void get_options(void) { if(parallel_config != NULL) set_parallel_conf(parallel_config); if(worker_config != NULL) set_worker_conf(worker_config); - } void set_default_frame_parms(nfapi_nr_config_request_scf_t *config[MAX_NUM_CCs], - NR_DL_FRAME_PARMS *frame_parms[MAX_NUM_CCs]) -{ + NR_DL_FRAME_PARMS *frame_parms[MAX_NUM_CCs]) { for (int CC_id=0; CC_idconfigured==0) { - waiting=1; - break; + waiting=1; + break; } } } @@ -567,11 +556,8 @@ int stop_L1L2(module_id_t gnb_id) { LOG_I(GNB_APP, "calling kill_NR_RU_proc() for instance %d\n", gnb_id); kill_NR_RU_proc(gnb_id); oai_exit = 0; - - //free_transport(RC.gNB[gnb_id]); + //free_transport(RC.gNB[gnb_id]); phy_free_nr_gNB(RC.gNB[gnb_id]); - - nr_phy_free_RU(RC.ru[gnb_id]); free_lte_top(); return 0; @@ -586,17 +572,13 @@ int restart_L1L2(module_id_t gnb_id) { LOG_W(GNB_APP, "restarting nr-softmodem\n"); /* block threads */ sync_var = -1; - RC.gNB[gnb_id]->configured = 0; - - RC.ru_mask |= (1 << ru->idx); set_function_spec_param(RC.ru[gnb_id]); LOG_I(GNB_APP, "attempting to create ITTI tasks\n"); // No more rrc thread, as many race conditions are hidden behind rrc_enb_init(); itti_mark_task_ready(TASK_RRC_ENB); - /* pass a reconfiguration request which will configure everything down to * RC.eNB[i][j]->frame_parms, too */ msg_p = itti_alloc_new_message(TASK_ENB_APP, 0, RRC_CONFIGURATION_REQ); @@ -633,7 +615,8 @@ void init_pdcp(void) { if (!NODE_IS_DU(RC.nrrrc[0]->node_type)) { // pdcp_layer_init(); uint32_t pdcp_initmask = (IS_SOFTMODEM_NOS1) ? - (PDCP_USE_NETLINK_BIT | LINK_ENB_PDCP_TO_IP_DRIVER_BIT) : LINK_ENB_PDCP_TO_GTPV1U_BIT; + (PDCP_USE_NETLINK_BIT | LINK_ENB_PDCP_TO_IP_DRIVER_BIT) : LINK_ENB_PDCP_TO_GTPV1U_BIT; + if (IS_SOFTMODEM_NOS1) { printf("IS_SOFTMODEM_NOS1 option enabled \n"); pdcp_initmask = pdcp_initmask | ENB_NAS_USE_TUN_BIT | SOFTMODEM_NOKRNMOD_BIT; @@ -656,16 +639,15 @@ void init_pdcp(void) { } -int main( int argc, char **argv ) -{ +int main( int argc, char **argv ) { int ru_id, CC_id = 0; - start_background_system(); ///static configuration for NR at the moment if ( load_configmodule(argc,argv,CONFIG_ENABLECMDLINEONLY) == NULL) { exit_fun("[SOFTMODEM] Error, configuration module init failed\n"); } + set_softmodem_sighandler(); #ifdef DEBUG_CONSOLE setvbuf(stdout, NULL, _IONBF, 0); @@ -709,19 +691,16 @@ int main( int argc, char **argv ) itti_init(TASK_MAX, tasks_info); // initialize mscgen log after ITTI MSC_INIT(MSC_E_UTRAN, ADDED_QUEUES_MAX+TASK_MAX); - - init_opt(); - - #ifdef PDCP_USE_NETLINK -if(!IS_SOFTMODEM_NOS1) - netlink_init(); + + if(!IS_SOFTMODEM_NOS1) + netlink_init(); + #if defined(PDCP_USE_NETLINK_QUEUES) pdcp_netlink_init(); #endif #endif - #ifndef PACKAGE_VERSION # define PACKAGE_VERSION "UNKNOWN-EXPERIMENTAL" #endif @@ -730,9 +709,8 @@ if(!IS_SOFTMODEM_NOS1) if (RC.nb_nr_L1_inst > 0) RCconfig_NR_L1(); - // don't create if node doesn't connect to RRC/S1/GTP - AssertFatal(create_gNB_tasks(1) == 0,"cannot create ITTI tasks\n"); - + // don't create if node doesn't connect to RRC/S1/GTP + AssertFatal(create_gNB_tasks(1) == 0,"cannot create ITTI tasks\n"); /* Start the agent. If it is turned off in the configuration, it won't start */ /* RCconfig_nr_flexran(); @@ -740,15 +718,13 @@ if(!IS_SOFTMODEM_NOS1) for (i = 0; i < RC.nb_nr_L1_inst; i++) { flexran_agent_start(i); } -*/ - + */ // init UE_PF_PO and mutex lock pthread_mutex_init(&ue_pf_po_mutex, NULL); memset (&UE_PF_PO[0][0], 0, sizeof(UE_PF_PO_t)*NUMBER_OF_UE_MAX*MAX_NUM_CCs); mlockall(MCL_CURRENT | MCL_FUTURE); pthread_cond_init(&sync_cond,NULL); pthread_mutex_init(&sync_mutex, NULL); - usleep(1000); if (NFAPI_MODE) { @@ -819,6 +795,7 @@ if(!IS_SOFTMODEM_NOS1) printf("RC.nb_RU:%d\n", RC.nb_RU); // once all RUs are ready initialize the rest of the gNBs ((dependence on final RU parameters after configuration) printf("ALL RUs ready - init gNBs\n"); + if(IS_SOFTMODEM_DOSCOPE) { sleep(1); scopeParms_t p; @@ -844,6 +821,7 @@ if(!IS_SOFTMODEM_NOS1) pthread_cond_broadcast(&sync_cond); pthread_mutex_unlock(&sync_mutex); } + printf("About to call end_configmodule() from %s() %s:%d\n", __FUNCTION__, __FILE__, __LINE__); end_configmodule(); printf("Called end_configmodule() from %s() %s:%d\n", __FUNCTION__, __FILE__, __LINE__); @@ -855,7 +833,6 @@ if(!IS_SOFTMODEM_NOS1) printf("Returned from ITTI signal handler\n"); oai_exit=1; printf("oai_exit=%d\n",oai_exit); - // stop threads /*#ifdef XFORMS @@ -889,8 +866,8 @@ if(!IS_SOFTMODEM_NOS1) /* release memory used by the RU/gNB threads (incomplete), after all * threads have been stopped (they partially use the same memory) */ for (int inst = 0; inst < NB_gNB_INST; inst++) { - //free_transport(RC.gNB[inst]); - phy_free_nr_gNB(RC.gNB[inst]); + //free_transport(RC.gNB[inst]); + phy_free_nr_gNB(RC.gNB[inst]); } for (int inst = 0; inst < NB_RU; inst++) { @@ -914,7 +891,6 @@ if(!IS_SOFTMODEM_NOS1) RC.ru[ru_id]->ifdevice.trx_end_func(&RC.ru[ru_id]->ifdevice); } - logClean(); printf("Bye.\n"); return 0; diff --git a/nfapi/open-nFAPI/nfapi/public_inc/nfapi_interface.h b/nfapi/open-nFAPI/nfapi/public_inc/nfapi_interface.h index 0eb77a9d26..ea459138e1 100644 --- a/nfapi/open-nFAPI/nfapi/public_inc/nfapi_interface.h +++ b/nfapi/open-nFAPI/nfapi/public_inc/nfapi_interface.h @@ -2727,7 +2727,7 @@ typedef struct { } nfapi_cqi_indication_rel8_t; #define NFAPI_CQI_INDICATION_REL8_TAG 0x202f -#define NFAPI_CC_MAX 4 +#define NFAPI_CC_MAX MAX_NUM_CCs typedef struct { nfapi_tl_t tl; uint16_t length; diff --git a/nfapi/open-nFAPI/nfapi/src/nfapi.c b/nfapi/open-nFAPI/nfapi/src/nfapi.c index ba800c3634..63dd8a16ae 100644 --- a/nfapi/open-nFAPI/nfapi/src/nfapi.c +++ b/nfapi/open-nFAPI/nfapi/src/nfapi.c @@ -1,969 +1,783 @@ -/* - * Copyright (c) 2001-2016, Cisco Systems, Inc. - * All rights reserved. - * - * 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 following disclaimer. - * - * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials provided - * with the distribution. - * - * Neither the name of the Cisco Systems, Inc. nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * 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 HOLDERS 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. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - - -// Fundamental routines - -uint8_t push8(uint8_t in, uint8_t **out, uint8_t *end) -{ - uint8_t *pOut = *out; - - if((end - pOut) >= 1) - { - pOut[0] = in; - - (*out)+=1; - - return 1; - } - else - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s no space in buffer\n", __FUNCTION__); - return 0; - } - -} - -uint8_t pushs8(int8_t in, uint8_t **out, uint8_t *end) -{ - uint8_t *pOut = *out; - - if((end - pOut) >= 1) - { - pOut[0] = in; - - (*out)+=1; - - return 1; - } - else - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s no space in buffer\n", __FUNCTION__); - return 0; - } -} - -uint8_t push16(uint16_t in, uint8_t **out, uint8_t *end) -{ - uint8_t *pOut = *out; - - if((end - pOut) >= 2) - { - pOut[0] = (in & 0xFF00) >> 8; - pOut[1] = (in & 0xFF); - - (*out)+=2; - - return 2; - } - else - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s no space in buffer\n", __FUNCTION__); - return 0; - } -} - -uint8_t pushs16(int16_t in, uint8_t **out, uint8_t *end) -{ - uint8_t *pOut = *out; - - if((end - pOut) >= 2) - { - pOut[0] = (in & 0xFF00) >> 8; - pOut[1] = (in & 0xFF); - - (*out)+=2; - - return 2; - } - else - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s no space in buffer\n", __FUNCTION__); - return 0; - } -} - -uint8_t push32(uint32_t in, uint8_t **out, uint8_t *end) -{ - uint8_t *pOut = *out; - if((end - pOut) >= 4) - { - pOut[0] = (in & 0xFF000000) >> 24; - pOut[1] = (in & 0xFF0000) >> 16; - pOut[2] = (in & 0xFF00) >> 8; - pOut[3] = (in & 0xFF); - - (*out)+=4; - - return 4; - } - else - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s no space in buffer\n", __FUNCTION__); - return 0; - } -} - -uint8_t pushs32(int32_t in, uint8_t **out, uint8_t *end) -{ - uint8_t *pOut = *out; - - if((end - pOut) >= 4) - { - pOut[0] = (in & 0xFF000000) >> 24; - pOut[1] = (in & 0xFF0000) >> 16; - pOut[2] = (in & 0xFF00) >> 8; - pOut[3] = (in & 0xFF); - - (*out)+=4; - - return 4; - } - else - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s no space in buffer\n", __FUNCTION__); - return 0; - } -} - -uint8_t pull8(uint8_t **in, uint8_t *out, uint8_t *end) -{ - uint8_t *pIn = *in; - - if((end - pIn) >= 1 ) - { - *out = *pIn; - - (*in)+=1; - - return 1; - } - else - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s no space in buffer\n", __FUNCTION__); - return 0; - } -} - -uint8_t pulls8(uint8_t **in, int8_t *out, uint8_t *end) -{ - uint8_t *pIn = *in; - - if((end - pIn) >= 1 ) - { - *out = *pIn; - - (*in)+=1; - - return 1; - } - else - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s no space in buffer\n", __FUNCTION__); - return 0; - } -} - -uint8_t pull16(uint8_t **in, uint16_t *out, uint8_t *end) -{ - uint8_t *pIn = *in; - - if((end - pIn) >=2 ) - { - *out = ((pIn[0]) << 8) | pIn[1]; - (*in)+=2; - - return 2; - } - else - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s no space in buffer\n", __FUNCTION__); - return 0; - } -} - -uint8_t pulls16(uint8_t **in, int16_t *out, uint8_t *end) -{ - uint8_t *pIn = *in; - - if((end - pIn) >=2 ) - { - *out = ((pIn[0]) << 8) | pIn[1]; - - (*in)+=2; - - return 2; - } - else - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s no space in buffer\n", __FUNCTION__); - return 0; - } -} - -uint8_t pull32(uint8_t **in, uint32_t *out, uint8_t *end) -{ - uint8_t *pIn = *in; - - if((end - pIn) >=4 ) - { - *out = (pIn[0] << 24) | (pIn[1] << 16) | (pIn[2] << 8) | pIn[3]; - - (*in)+=4; - - return 4; - } - else - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s no space in buffer\n", __FUNCTION__); - return 0; - } -} - -uint8_t pulls32(uint8_t **in, int32_t *out, uint8_t *end) -{ - uint8_t *pIn = *in; - - if((end - pIn) >=4 ) - { - *out = (pIn[0] << 24) | (pIn[1] << 16) | (pIn[2] << 8) | pIn[3]; - - (*in)+=4; - - return 4; - } - else - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s no space in buffer\n", __FUNCTION__); - return 0; - } -} - -/* -inline void pusharray16(uint8_t **, uint16_t, uint32_t len) -{ -} -*/ - -uint32_t pullarray16(uint8_t **in, uint16_t out[], uint32_t max_len, uint32_t len, uint8_t *end) -{ - if(len == 0) - return 1; - - if(len > max_len) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s exceed array size (%d > %d)\n", __FUNCTION__, len, max_len); - return 0; - } - - if((end - (*in)) >= sizeof(uint16_t) * len) - { - uint32_t idx; - for(idx = 0; idx < len; ++idx) - { - if(!pull16(in, &out[idx], end)) - return 0; - } - - return sizeof(uint16_t) * len; - } - else - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s no space in buffer\n", __FUNCTION__); - return 0; - } -} - -uint32_t pullarrays16(uint8_t **in, int16_t out[], uint32_t max_len, uint32_t len, uint8_t *end) -{ - if(len == 0) - return 1; - - if(len > max_len) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s exceed array size (%d > %d)\n", __FUNCTION__, len, max_len); - return 0; - } - - if((end - (*in)) >= sizeof(uint16_t) * len) - { - uint32_t idx; - for(idx = 0; idx < len; ++idx) - { - if(!pulls16(in, &out[idx], end)) - return 0; - } - - return sizeof(uint16_t) * len; - } - else - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s no space in buffer\n", __FUNCTION__); - return 0; - } -} -uint32_t pusharray16(uint16_t in[], uint32_t max_len, uint32_t len, uint8_t **out, uint8_t *end) -{ - if(len == 0) - return 1; - - if(len > max_len) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s exceed array size (%d > %d)\n", __FUNCTION__, len, max_len); - return 0; - } - - if((end - (*out)) >= sizeof(uint16_t) * len) - { - uint32_t idx; - for(idx = 0; idx < len; ++idx) - { - if(!push16(in[idx], out, end)) - return 0; - } - return sizeof(uint16_t) * len; - } - else - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s no space in buffer\n", __FUNCTION__); - return 0; - } -} -uint32_t pusharrays16(int16_t in[], uint32_t max_len, uint32_t len, uint8_t **out, uint8_t *end) -{ - if(len == 0) - return 1; - - if(len > max_len) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s exceed array size (%d > %d)\n", __FUNCTION__, len, max_len); - return 0; - } - - if((end - (*out)) >= sizeof(uint16_t) * len) - { - uint32_t idx; - for(idx = 0; idx < len; ++idx) - { - pushs16(in[idx], out, end); - } - return sizeof(uint16_t) * len; - } - else - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s no space in buffer\n", __FUNCTION__); - return 0; - } -} -uint32_t pullarray32(uint8_t **in, uint32_t out[], uint32_t max_len, uint32_t len, uint8_t *end) -{ - if(len == 0) - return 1; - - if(len > max_len) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s exceed array size (%d > %d)\n", __FUNCTION__, len, max_len); - return 0; - } - - if((end - (*in)) >= sizeof(uint32_t) * len) - { - uint32_t idx; - for(idx = 0; idx < len; ++idx) - { - if(!pull32(in, &out[idx], end)) - return 0; - } - - return sizeof(uint32_t) * len; - } - else - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s no space in buffer\n", __FUNCTION__); - return 0; - } -} - -uint32_t pullarrays32(uint8_t **in, int32_t out[], uint32_t max_len, uint32_t len, uint8_t *end) -{ - if(len == 0) - return 1; - - if(len > max_len) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s exceed array size (%d > %d)\n", __FUNCTION__, len, max_len); - return 0; - } - - if((end - (*in)) >= sizeof(uint32_t) * len) - { - uint32_t idx; - for(idx = 0; idx < len; ++idx) - { - if(!pulls32(in, &out[idx], end)) - return 0; - } - - return sizeof(uint32_t) * len; - } - else - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s no space in buffer\n", __FUNCTION__); - return 0; - } -} -uint32_t pusharray32(uint32_t in[], uint32_t max_len, uint32_t len, uint8_t **out, uint8_t *end) -{ - if(len == 0) - return 1; - - if(len > max_len) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s exceed array size (%d > %d)\n", __FUNCTION__, len, max_len); - return 0; - } - - if((end - (*out)) >= sizeof(uint32_t) * len) - { - uint32_t idx; - for(idx = 0; idx < len; ++idx) - { - if(!push32(in[idx], out, end)) - return 0; - } - return sizeof(uint32_t) * len; - } - else - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s no space in buffer\n", __FUNCTION__); - return 0; - } -} -uint32_t pusharrays32(int32_t in[], uint32_t max_len, uint32_t len, uint8_t **out, uint8_t *end) -{ - if(len == 0) - return 1; - - if(len > max_len) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s exceed array size (%d > %d)\n", __FUNCTION__, len, max_len); - return 0; - } - - if((end - (*out)) >= sizeof(uint32_t) * len) - { - uint32_t idx; - for(idx = 0; idx < len; ++idx) - { - pushs32(in[idx], out, end); - } - return sizeof(uint32_t) * len; - } - else - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s no space in buffer\n", __FUNCTION__); - return 0; - } -} -uint32_t pullarray8(uint8_t **in, uint8_t out[], uint32_t max_len, uint32_t len, uint8_t *end) -{ - if(len == 0) - return 1; - - if(len > max_len) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s exceed array size (%d > %d)\n", __FUNCTION__, len, max_len); - return 0; - } - - if((end - (*in)) >= sizeof(uint8_t) * len) - { - memcpy(out, (*in), len); - (*in)+=len; - - return sizeof(uint8_t) * len; - } - else - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s no space in buffer\n", __FUNCTION__); - return 0; - } -} - -uint32_t pusharray8(uint8_t in[], uint32_t max_len, uint32_t len, uint8_t **out, uint8_t *end) -{ - if(len == 0) - return 1; - - if(len > max_len) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s exceed array size (%d > %d)\n", __FUNCTION__, len, max_len); - return 0; - } - - if((end - (*out)) >= sizeof(uint8_t) * len) - { - memcpy((*out), in, len); - (*out)+=len; - - return sizeof(uint8_t) * len; - } - else - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s no space in buffer\n", __FUNCTION__); - return 0; - } -} - -uint8_t packarray(void* array, uint16_t array_element_size, uint16_t max_count, uint16_t count, uint8_t **ppwritepackedmsg, uint8_t *end, pack_array_elem_fn fn) -{ - if(count > max_count) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s exceed array size (%d > %d)\n", __FUNCTION__, count, max_count); - return 0; - } - - uint16_t i = 0; - for(i = 0; i < count; ++i) - { - if((fn)(array, ppwritepackedmsg, end) == 0) - return 0; - - array += array_element_size; - } - - return 1; -} - -uint8_t unpackarray(uint8_t **ppReadPackedMsg, void* array, uint16_t array_element_size, uint16_t max_count, uint16_t count, uint8_t *end, unpack_array_elem_fn fn) -{ - if(count > max_count) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s exceed array size (%d > %d)\n", __FUNCTION__, count, max_count); - return 0; - } - - uint16_t i = 0; - for(i = 0; i < count; ++i) - { - if((fn)(array, ppReadPackedMsg, end) == 0) - return 0; - - array += array_element_size; - } - - return 1; -} - - -uint32_t pack_vendor_extension_tlv(nfapi_tl_t* ve, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t* config) -{ - if(ve != 0 && config != 0) - { - if(config->pack_vendor_extension_tlv) - { - - uint8_t* pStartOfTlv = *ppWritePackedMsg; - if(pack_tl(ve, ppWritePackedMsg, end) == 0) - return 0; - - uint8_t* pStartOfValue = *ppWritePackedMsg; - if((config->pack_vendor_extension_tlv)(ve, ppWritePackedMsg, end, config) == 0) - return 0; - - ve->length = (*ppWritePackedMsg) - pStartOfValue; - - pack_tl(ve, &pStartOfTlv, end); - - return 1; - - } - } - return 1; -} - -uint32_t unpack_vendor_extension_tlv(nfapi_tl_t* tl, uint8_t **ppReadPackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t* config, nfapi_tl_t** ve_tlv) -{ - if(ve_tlv != 0 && config != 0) - { - if(config->unpack_vendor_extension_tlv) - { - return (config->unpack_vendor_extension_tlv)(tl, ppReadPackedMsg, end, (void**)ve_tlv, config); - } - } - return 1; -} - -uint32_t pack_p7_vendor_extension_tlv(nfapi_tl_t *ve, uint8_t **ppWritePackedMsg, uint8_t *end ,nfapi_p7_codec_config_t* config) -{ - if(ve != 0 && config != 0) - { - if(config->pack_vendor_extension_tlv) - { - uint8_t* pStartOfTlv = *ppWritePackedMsg; - if(pack_tl(ve, ppWritePackedMsg, end) == 0) - return 0; - - uint8_t* pStartOfValue = *ppWritePackedMsg; - if((config->pack_vendor_extension_tlv)(ve, ppWritePackedMsg, end, config) == 0) - return 0; - - ve->length = (*ppWritePackedMsg) - pStartOfValue; - - pack_tl(ve, &pStartOfTlv, end); - - return 1; - - } - } - return 1; -} - -int unpack_p7_vendor_extension_tlv(nfapi_tl_t* tl, uint8_t **ppReadPackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config, nfapi_tl_t** ve_tlv) -{ - if(ve_tlv != 0 && config != 0) - { - if(config->unpack_vendor_extension_tlv) - { - return (config->unpack_vendor_extension_tlv)(tl, ppReadPackedMsg, end, (void**)ve_tlv, config); - } - } - return 1; -} - - -uint8_t pack_tl(nfapi_tl_t *tl, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - return (push16(tl->tag, ppWritePackedMsg, end) && - push16(tl->length, ppWritePackedMsg, end)); -} - -uint8_t unpack_tl(uint8_t **ppReadPackedMsg, nfapi_tl_t *tl, uint8_t *end) -{ - return (pull16(ppReadPackedMsg, &tl->tag, end) && - pull16(ppReadPackedMsg, &tl->length, end)); -} - -int unpack_tlv_list(unpack_tlv_t unpack_fns[], uint16_t size, uint8_t **ppReadPackedMsg, uint8_t* end, nfapi_p4_p5_codec_config_t* config, nfapi_tl_t** ve) -{ - nfapi_tl_t generic_tl; - uint8_t numBadTags = 0; - uint16_t idx = 0; - - while ((uint8_t*)(*ppReadPackedMsg) < end) - { - // unpack the tl and process the values accordingly - if(unpack_tl(ppReadPackedMsg, &generic_tl, end) == 0) - return 0; - - uint8_t tagMatch = 0; - - uint8_t* pStartOfValue = *ppReadPackedMsg; - - for(idx = 0; idx < size; ++idx) - { - if(unpack_fns[idx].tag == generic_tl.tag) // match the extracted tag value with all the tags in unpack_fn list - { - tagMatch = 1; - nfapi_tl_t* tl = (nfapi_tl_t*)(unpack_fns[idx].tlv); - tl->tag = generic_tl.tag; - tl->length = generic_tl.length; - - int result = (*unpack_fns[idx].unpack_func)(tl, ppReadPackedMsg, end); - - if(result == 0) - { - return 0; - } - - // check if the length was right; - if(tl->length != (*ppReadPackedMsg - pStartOfValue)) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "Warning tlv tag 0x%x length %d not equal to unpack %d\n", tl->tag, tl->length, (*ppReadPackedMsg - pStartOfValue)); - } - } - } - - if(tagMatch == 0) - { - - if(generic_tl.tag >= NFAPI_VENDOR_EXTENSION_MIN_TAG_VALUE && - generic_tl.tag <= NFAPI_VENDOR_EXTENSION_MAX_TAG_VALUE) - { - int result = unpack_vendor_extension_tlv(&generic_tl, ppReadPackedMsg, end, config, ve); - if(result == 0) - { - // got tot the end. - return 0; - } - else if(result < 0) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "Unknown VE TAG value: 0x%04x\n", generic_tl.tag); - - if (++numBadTags > MAX_BAD_TAG) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "Supplied message has had too many bad tags\n"); - return 0; - } - - if((end - *ppReadPackedMsg) >= generic_tl.length) - { - // Advance past the unknown TLV - (*ppReadPackedMsg) += generic_tl.length; - } - else - { - // go to the end - return 0; - } - } - } - else - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "Unknown TAG value: 0x%04x\n", generic_tl.tag); - - if (++numBadTags > MAX_BAD_TAG) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "Supplied message has had too many bad tags\n"); - return 0; - } - - if((end - *ppReadPackedMsg) >= generic_tl.length) - { - // Advance past the unknown TLV - (*ppReadPackedMsg) += generic_tl.length; - } - else - { - // go to the end - return 0; - } - } - - } - } - - return 1; -} -int unpack_p7_tlv_list(unpack_p7_tlv_t unpack_fns[], uint16_t size, uint8_t **ppReadPackedMsg, uint8_t* end, nfapi_p7_codec_config_t* config, nfapi_tl_t** ve) -{ - nfapi_tl_t generic_tl; - uint8_t numBadTags = 0; - uint16_t idx = 0; - - while ((uint8_t*)(*ppReadPackedMsg) < end) - { - // unpack the tl and process the values accordingly - if(unpack_tl(ppReadPackedMsg, &generic_tl, end) == 0) - return 0; - - uint8_t tagMatch = 0; - - uint8_t* pStartOfValue = *ppReadPackedMsg; - - for(idx = 0; idx < size; ++idx) - { - if(unpack_fns[idx].tag == generic_tl.tag) - { - tagMatch = 1; - nfapi_tl_t* tl = (nfapi_tl_t*)(unpack_fns[idx].tlv); - tl->tag = generic_tl.tag; - tl->length = generic_tl.length; - - int result = (*unpack_fns[idx].unpack_func)(tl, ppReadPackedMsg, end , config); - - if(result == 0) - { - return 0; - } - - // check if the length was right; - if(tl->length != (*ppReadPackedMsg - pStartOfValue)) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "Warning tlv tag 0x%x length %d not equal to unpack %d\n", tl->tag, tl->length, (*ppReadPackedMsg - pStartOfValue)); - } - } - } - - if(tagMatch == 0) - { - - if(generic_tl.tag >= NFAPI_VENDOR_EXTENSION_MIN_TAG_VALUE && - generic_tl.tag <= NFAPI_VENDOR_EXTENSION_MAX_TAG_VALUE) - { - int result = unpack_p7_vendor_extension_tlv(&generic_tl, ppReadPackedMsg, end, config, ve); - if(result == 0) - { - // got to end - return 0; - } - else if(result < 0) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "Unknown TAG value: 0x%04x\n", generic_tl.tag); - - if (++numBadTags > MAX_BAD_TAG) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "Supplied message has had too many bad tags\n"); - return -1; - } - - if((end - *ppReadPackedMsg) >= generic_tl.length) - { - // Advance past the unknown TLV - (*ppReadPackedMsg) += generic_tl.length; - } - else - { - // got ot the dn - return 0; - } - } - } - else - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "Unknown TAG value: 0x%04x\n", generic_tl.tag); - - if (++numBadTags > MAX_BAD_TAG) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "Supplied message has had too many bad tags\n"); - return -1; - } - - if((end - *ppReadPackedMsg) >= generic_tl.length) - { - // Advance past the unknown TLV - (*ppReadPackedMsg) += generic_tl.length; - } - else - { - // got ot the dn - return 0; - } - - } - - } - } - - return 1; -} - -// This intermediate function deals with calculating the length of the value -// and writing into the tlv header. -uint8_t pack_tlv(uint16_t tag, void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end, pack_tlv_fn fn) -{ - nfapi_tl_t* tl = (nfapi_tl_t*)tlv; - - // If the tag is defined - if(tl->tag == tag) - { - uint8_t* pStartOfTlv = *ppWritePackedMsg; - - // write a dumy tlv header - if(pack_tl(tl, ppWritePackedMsg, end) == 0) - return 0; - - // Record the start of the value - uint8_t* pStartOfValue = *ppWritePackedMsg; - - // pack the tlv value - if(fn(tlv, ppWritePackedMsg, end) == 0) - return 0; - - // calculate the length of the value and rewrite the tl header - tl->length = (*ppWritePackedMsg) - pStartOfValue; - - // rewrite the header with the correct length - pack_tl(tl, &pStartOfTlv, end); - } - else - { - if(tl->tag != 0) - { - NFAPI_TRACE(NFAPI_TRACE_WARN, "Warning pack_tlv tag 0x%x does not match expected 0x%x\n", tl->tag, tag); - } - else - { - //NFAPI_TRACE(NFAPI_TRACE_ERROR, "Warning pack_tlv tag 0x%x ZERO does not match expected 0x%x\n", tl->tag, tag); - } - } - - return 1; -} - -const char* nfapi_error_code_to_str(nfapi_error_code_e value) -{ - switch(value) - { - case NFAPI_MSG_OK: - return "NFAPI_MSG_OK"; - case NFAPI_MSG_INVALID_STATE: - return "NFAPI_MSG_INVALID_STATE"; - case NFAPI_MSG_INVALID_CONFIG: - return "NFAPI_MSG_INVALID_CONFIG"; - case NFAPI_SFN_OUT_OF_SYNC: - return "NFAPI_SFN_OUT_OF_SYNC"; - case NFAPI_MSG_SUBFRAME_ERR: - return "NFAPI_MSG_SUBFRAME_ERR"; - case NFAPI_MSG_BCH_MISSING: - return "NFAPI_MSG_BCH_MISSING"; - case NFAPI_MSG_INVALID_SFN: - return "NFAPI_MSG_INVALID_SFN"; - case NFAPI_MSG_HI_ERR: - return "NFAPI_MSG_HI_ERR"; - case NFAPI_MSG_TX_ERR: - return "NFAPI_MSG_TX_ERR"; - default: - return "UNKNOWN"; - } -} +/* + * Copyright (c) 2001-2016, Cisco Systems, Inc. + * All rights reserved. + * + * 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 following disclaimer. + * + * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * Neither the name of the Cisco Systems, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * 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 HOLDERS 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. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + + +// Fundamental routines + +uint8_t push8(uint8_t in, uint8_t **out, uint8_t *end) { + uint8_t *pOut = *out; + + if((end - pOut) >= 1) { + pOut[0] = in; + (*out)+=1; + return 1; + } else { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s no space in buffer\n", __FUNCTION__); + return 0; + } +} + +uint8_t pushs8(int8_t in, uint8_t **out, uint8_t *end) { + uint8_t *pOut = *out; + + if((end - pOut) >= 1) { + pOut[0] = in; + (*out)+=1; + return 1; + } else { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s no space in buffer\n", __FUNCTION__); + return 0; + } +} + +uint8_t push16(uint16_t in, uint8_t **out, uint8_t *end) { + uint8_t *pOut = *out; + + if((end - pOut) >= 2) { + pOut[0] = (in & 0xFF00) >> 8; + pOut[1] = (in & 0xFF); + (*out)+=2; + return 2; + } else { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s no space in buffer\n", __FUNCTION__); + return 0; + } +} + +uint8_t pushs16(int16_t in, uint8_t **out, uint8_t *end) { + uint8_t *pOut = *out; + + if((end - pOut) >= 2) { + pOut[0] = (in & 0xFF00) >> 8; + pOut[1] = (in & 0xFF); + (*out)+=2; + return 2; + } else { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s no space in buffer\n", __FUNCTION__); + return 0; + } +} + +uint8_t push32(uint32_t in, uint8_t **out, uint8_t *end) { + uint8_t *pOut = *out; + + if((end - pOut) >= 4) { + pOut[0] = (in & 0xFF000000) >> 24; + pOut[1] = (in & 0xFF0000) >> 16; + pOut[2] = (in & 0xFF00) >> 8; + pOut[3] = (in & 0xFF); + (*out)+=4; + return 4; + } else { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s no space in buffer\n", __FUNCTION__); + return 0; + } +} + +uint8_t pushs32(int32_t in, uint8_t **out, uint8_t *end) { + uint8_t *pOut = *out; + + if((end - pOut) >= 4) { + pOut[0] = (in & 0xFF000000) >> 24; + pOut[1] = (in & 0xFF0000) >> 16; + pOut[2] = (in & 0xFF00) >> 8; + pOut[3] = (in & 0xFF); + (*out)+=4; + return 4; + } else { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s no space in buffer\n", __FUNCTION__); + return 0; + } +} + +uint8_t pull8(uint8_t **in, uint8_t *out, uint8_t *end) { + uint8_t *pIn = *in; + + if((end - pIn) >= 1 ) { + *out = *pIn; + (*in)+=1; + return 1; + } else { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s no space in buffer\n", __FUNCTION__); + return 0; + } +} + +uint8_t pulls8(uint8_t **in, int8_t *out, uint8_t *end) { + uint8_t *pIn = *in; + + if((end - pIn) >= 1 ) { + *out = *pIn; + (*in)+=1; + return 1; + } else { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s no space in buffer\n", __FUNCTION__); + return 0; + } +} + +uint8_t pull16(uint8_t **in, uint16_t *out, uint8_t *end) { + uint8_t *pIn = *in; + + if((end - pIn) >=2 ) { + *out = ((pIn[0]) << 8) | pIn[1]; + (*in)+=2; + return 2; + } else { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s no space in buffer\n", __FUNCTION__); + return 0; + } +} + +uint8_t pulls16(uint8_t **in, int16_t *out, uint8_t *end) { + uint8_t *pIn = *in; + + if((end - pIn) >=2 ) { + *out = ((pIn[0]) << 8) | pIn[1]; + (*in)+=2; + return 2; + } else { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s no space in buffer\n", __FUNCTION__); + return 0; + } +} + +uint8_t pull32(uint8_t **in, uint32_t *out, uint8_t *end) { + uint8_t *pIn = *in; + + if((end - pIn) >=4 ) { + *out = (pIn[0] << 24) | (pIn[1] << 16) | (pIn[2] << 8) | pIn[3]; + (*in)+=4; + return 4; + } else { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s no space in buffer\n", __FUNCTION__); + return 0; + } +} + +uint8_t pulls32(uint8_t **in, int32_t *out, uint8_t *end) { + uint8_t *pIn = *in; + + if((end - pIn) >=4 ) { + *out = (pIn[0] << 24) | (pIn[1] << 16) | (pIn[2] << 8) | pIn[3]; + (*in)+=4; + return 4; + } else { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s no space in buffer\n", __FUNCTION__); + return 0; + } +} + +/* +inline void pusharray16(uint8_t **, uint16_t, uint32_t len) +{ +} +*/ + +uint32_t pullarray16(uint8_t **in, uint16_t out[], uint32_t max_len, uint32_t len, uint8_t *end) { + if(len == 0) + return 1; + + if(len > max_len) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s exceed array size (%d > %d)\n", __FUNCTION__, len, max_len); + return 0; + } + + if((end - (*in)) >= sizeof(uint16_t) * len) { + uint32_t idx; + + for(idx = 0; idx < len; ++idx) { + if(!pull16(in, &out[idx], end)) + return 0; + } + + return sizeof(uint16_t) * len; + } else { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s no space in buffer\n", __FUNCTION__); + return 0; + } +} + +uint32_t pullarrays16(uint8_t **in, int16_t out[], uint32_t max_len, uint32_t len, uint8_t *end) { + if(len == 0) + return 1; + + if(len > max_len) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s exceed array size (%d > %d)\n", __FUNCTION__, len, max_len); + return 0; + } + + if((end - (*in)) >= sizeof(uint16_t) * len) { + uint32_t idx; + + for(idx = 0; idx < len; ++idx) { + if(!pulls16(in, &out[idx], end)) + return 0; + } + + return sizeof(uint16_t) * len; + } else { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s no space in buffer\n", __FUNCTION__); + return 0; + } +} +uint32_t pusharray16(uint16_t in[], uint32_t max_len, uint32_t len, uint8_t **out, uint8_t *end) { + if(len == 0) + return 1; + + if(len > max_len) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s exceed array size (%d > %d)\n", __FUNCTION__, len, max_len); + return 0; + } + + if((end - (*out)) >= sizeof(uint16_t) * len) { + uint32_t idx; + + for(idx = 0; idx < len; ++idx) { + if(!push16(in[idx], out, end)) + return 0; + } + + return sizeof(uint16_t) * len; + } else { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s no space in buffer\n", __FUNCTION__); + return 0; + } +} +uint32_t pusharrays16(int16_t in[], uint32_t max_len, uint32_t len, uint8_t **out, uint8_t *end) { + if(len == 0) + return 1; + + if(len > max_len) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s exceed array size (%d > %d)\n", __FUNCTION__, len, max_len); + return 0; + } + + if((end - (*out)) >= sizeof(uint16_t) * len) { + uint32_t idx; + + for(idx = 0; idx < len; ++idx) { + pushs16(in[idx], out, end); + } + + return sizeof(uint16_t) * len; + } else { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s no space in buffer\n", __FUNCTION__); + return 0; + } +} +uint32_t pullarray32(uint8_t **in, uint32_t out[], uint32_t max_len, uint32_t len, uint8_t *end) { + if(len == 0) + return 1; + + if(len > max_len) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s exceed array size (%d > %d)\n", __FUNCTION__, len, max_len); + return 0; + } + + if((end - (*in)) >= sizeof(uint32_t) * len) { + uint32_t idx; + + for(idx = 0; idx < len; ++idx) { + if(!pull32(in, &out[idx], end)) + return 0; + } + + return sizeof(uint32_t) * len; + } else { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s no space in buffer\n", __FUNCTION__); + return 0; + } +} + +uint32_t pullarrays32(uint8_t **in, int32_t out[], uint32_t max_len, uint32_t len, uint8_t *end) { + if(len == 0) + return 1; + + if(len > max_len) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s exceed array size (%d > %d)\n", __FUNCTION__, len, max_len); + return 0; + } + + if((end - (*in)) >= sizeof(uint32_t) * len) { + uint32_t idx; + + for(idx = 0; idx < len; ++idx) { + if(!pulls32(in, &out[idx], end)) + return 0; + } + + return sizeof(uint32_t) * len; + } else { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s no space in buffer\n", __FUNCTION__); + return 0; + } +} +uint32_t pusharray32(uint32_t in[], uint32_t max_len, uint32_t len, uint8_t **out, uint8_t *end) { + if(len == 0) + return 1; + + if(len > max_len) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s exceed array size (%d > %d)\n", __FUNCTION__, len, max_len); + return 0; + } + + if((end - (*out)) >= sizeof(uint32_t) * len) { + uint32_t idx; + + for(idx = 0; idx < len; ++idx) { + if(!push32(in[idx], out, end)) + return 0; + } + + return sizeof(uint32_t) * len; + } else { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s no space in buffer\n", __FUNCTION__); + return 0; + } +} +uint32_t pusharrays32(int32_t in[], uint32_t max_len, uint32_t len, uint8_t **out, uint8_t *end) { + if(len == 0) + return 1; + + if(len > max_len) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s exceed array size (%d > %d)\n", __FUNCTION__, len, max_len); + return 0; + } + + if((end - (*out)) >= sizeof(uint32_t) * len) { + uint32_t idx; + + for(idx = 0; idx < len; ++idx) { + pushs32(in[idx], out, end); + } + + return sizeof(uint32_t) * len; + } else { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s no space in buffer\n", __FUNCTION__); + return 0; + } +} +uint32_t pullarray8(uint8_t **in, uint8_t out[], uint32_t max_len, uint32_t len, uint8_t *end) { + if(len == 0) + return 1; + + if(len > max_len) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s exceed array size (%d > %d)\n", __FUNCTION__, len, max_len); + return 0; + } + + if((end - (*in)) >= sizeof(uint8_t) * len) { + memcpy(out, (*in), len); + (*in)+=len; + return sizeof(uint8_t) * len; + } else { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s no space in buffer\n", __FUNCTION__); + return 0; + } +} + +uint32_t pusharray8(uint8_t in[], uint32_t max_len, uint32_t len, uint8_t **out, uint8_t *end) { + if(len == 0) + return 1; + + if(len > max_len) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s exceed array size (%d > %d)\n", __FUNCTION__, len, max_len); + return 0; + } + + if((end - (*out)) >= sizeof(uint8_t) * len) { + memcpy((*out), in, len); + (*out)+=len; + return sizeof(uint8_t) * len; + } else { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s no space in buffer\n", __FUNCTION__); + return 0; + } +} + +uint8_t packarray(void *array, uint16_t array_element_size, uint16_t max_count, uint16_t count, uint8_t **ppwritepackedmsg, uint8_t *end, pack_array_elem_fn fn) { + if(count > max_count) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s exceed array size (%d > %d)\n", __FUNCTION__, count, max_count); + return 0; + } + + uint16_t i = 0; + + for(i = 0; i < count; ++i) { + if((fn)(array, ppwritepackedmsg, end) == 0) + return 0; + + array += array_element_size; + } + + return 1; +} + +uint8_t unpackarray(uint8_t **ppReadPackedMsg, void *array, uint16_t array_element_size, uint16_t max_count, uint16_t count, uint8_t *end, unpack_array_elem_fn fn) { + if(count > max_count) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s exceed array size (%d > %d)\n", __FUNCTION__, count, max_count); + return 0; + } + + uint16_t i = 0; + + for(i = 0; i < count; ++i) { + if((fn)(array, ppReadPackedMsg, end) == 0) + return 0; + + array += array_element_size; + } + + return 1; +} + + +uint32_t pack_vendor_extension_tlv(nfapi_tl_t *ve, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t *config) { + if(ve != 0 && config != 0) { + if(config->pack_vendor_extension_tlv) { + uint8_t *pStartOfTlv = *ppWritePackedMsg; + + if(pack_tl(ve, ppWritePackedMsg, end) == 0) + return 0; + + uint8_t *pStartOfValue = *ppWritePackedMsg; + + if((config->pack_vendor_extension_tlv)(ve, ppWritePackedMsg, end, config) == 0) + return 0; + + ve->length = (*ppWritePackedMsg) - pStartOfValue; + pack_tl(ve, &pStartOfTlv, end); + return 1; + } + } + + return 1; +} + +uint32_t unpack_vendor_extension_tlv(nfapi_tl_t *tl, uint8_t **ppReadPackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t *config, nfapi_tl_t **ve_tlv) { + if(ve_tlv != 0 && config != 0) { + if(config->unpack_vendor_extension_tlv) { + return (config->unpack_vendor_extension_tlv)(tl, ppReadPackedMsg, end, (void **)ve_tlv, config); + } + } + + return 1; +} + +uint32_t pack_p7_vendor_extension_tlv(nfapi_tl_t *ve, uint8_t **ppWritePackedMsg, uint8_t *end,nfapi_p7_codec_config_t *config) { + if(ve != 0 && config != 0) { + if(config->pack_vendor_extension_tlv) { + uint8_t *pStartOfTlv = *ppWritePackedMsg; + + if(pack_tl(ve, ppWritePackedMsg, end) == 0) + return 0; + + uint8_t *pStartOfValue = *ppWritePackedMsg; + + if((config->pack_vendor_extension_tlv)(ve, ppWritePackedMsg, end, config) == 0) + return 0; + + ve->length = (*ppWritePackedMsg) - pStartOfValue; + pack_tl(ve, &pStartOfTlv, end); + return 1; + } + } + + return 1; +} + +int unpack_p7_vendor_extension_tlv(nfapi_tl_t *tl, uint8_t **ppReadPackedMsg, uint8_t *end, nfapi_p7_codec_config_t *config, nfapi_tl_t **ve_tlv) { + if(ve_tlv != 0 && config != 0) { + if(config->unpack_vendor_extension_tlv) { + return (config->unpack_vendor_extension_tlv)(tl, ppReadPackedMsg, end, (void **)ve_tlv, config); + } + } + + return 1; +} + + +uint8_t pack_tl(nfapi_tl_t *tl, uint8_t **ppWritePackedMsg, uint8_t *end) { + return (push16(tl->tag, ppWritePackedMsg, end) && + push16(tl->length, ppWritePackedMsg, end)); +} + +uint8_t unpack_tl(uint8_t **ppReadPackedMsg, nfapi_tl_t *tl, uint8_t *end) { + return (pull16(ppReadPackedMsg, &tl->tag, end) && + pull16(ppReadPackedMsg, &tl->length, end)); +} + +int unpack_tlv_list(unpack_tlv_t unpack_fns[], uint16_t size, uint8_t **ppReadPackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t *config, nfapi_tl_t **ve) { + nfapi_tl_t generic_tl; + uint8_t numBadTags = 0; + uint16_t idx = 0; + + while ((uint8_t *)(*ppReadPackedMsg) < end) { + // unpack the tl and process the values accordingly + if(unpack_tl(ppReadPackedMsg, &generic_tl, end) == 0) + return 0; + + uint8_t tagMatch = 0; + uint8_t *pStartOfValue = *ppReadPackedMsg; + + for(idx = 0; idx < size; ++idx) { + if(unpack_fns[idx].tag == generic_tl.tag) { // match the extracted tag value with all the tags in unpack_fn list + tagMatch = 1; + nfapi_tl_t *tl = (nfapi_tl_t *)(unpack_fns[idx].tlv); + tl->tag = generic_tl.tag; + tl->length = generic_tl.length; + int result = (*unpack_fns[idx].unpack_func)(tl, ppReadPackedMsg, end); + + if(result == 0) { + return 0; + } + + // check if the length was right; + if(tl->length != (*ppReadPackedMsg - pStartOfValue)) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "Warning tlv tag 0x%x length %d not equal to unpack %d\n", tl->tag, tl->length, (*ppReadPackedMsg - pStartOfValue)); + } + } + } + + if(tagMatch == 0) { + if(generic_tl.tag >= NFAPI_VENDOR_EXTENSION_MIN_TAG_VALUE && + generic_tl.tag <= NFAPI_VENDOR_EXTENSION_MAX_TAG_VALUE) { + int result = unpack_vendor_extension_tlv(&generic_tl, ppReadPackedMsg, end, config, ve); + + if(result == 0) { + // got tot the end. + return 0; + } else if(result < 0) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "Unknown VE TAG value: 0x%04x\n", generic_tl.tag); + + if (++numBadTags > MAX_BAD_TAG) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "Supplied message has had too many bad tags\n"); + return 0; + } + + if((end - *ppReadPackedMsg) >= generic_tl.length) { + // Advance past the unknown TLV + (*ppReadPackedMsg) += generic_tl.length; + } else { + // go to the end + return 0; + } + } + } else { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "Unknown TAG value: 0x%04x\n", generic_tl.tag); + + if (++numBadTags > MAX_BAD_TAG) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "Supplied message has had too many bad tags\n"); + return 0; + } + + if((end - *ppReadPackedMsg) >= generic_tl.length) { + // Advance past the unknown TLV + (*ppReadPackedMsg) += generic_tl.length; + } else { + // go to the end + return 0; + } + } + } + } + + return 1; +} +int unpack_p7_tlv_list(unpack_p7_tlv_t unpack_fns[], uint16_t size, uint8_t **ppReadPackedMsg, uint8_t *end, nfapi_p7_codec_config_t *config, nfapi_tl_t **ve) { + nfapi_tl_t generic_tl; + uint8_t numBadTags = 0; + uint16_t idx = 0; + + while ((uint8_t *)(*ppReadPackedMsg) < end) { + // unpack the tl and process the values accordingly + if(unpack_tl(ppReadPackedMsg, &generic_tl, end) == 0) + return 0; + + uint8_t tagMatch = 0; + uint8_t *pStartOfValue = *ppReadPackedMsg; + + for(idx = 0; idx < size; ++idx) { + if(unpack_fns[idx].tag == generic_tl.tag) { + tagMatch = 1; + nfapi_tl_t *tl = (nfapi_tl_t *)(unpack_fns[idx].tlv); + tl->tag = generic_tl.tag; + tl->length = generic_tl.length; + int result = (*unpack_fns[idx].unpack_func)(tl, ppReadPackedMsg, end, config); + + if(result == 0) { + return 0; + } + + // check if the length was right; + if(tl->length != (*ppReadPackedMsg - pStartOfValue)) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "Warning tlv tag 0x%x length %d not equal to unpack %d\n", tl->tag, tl->length, (*ppReadPackedMsg - pStartOfValue)); + } + } + } + + if(tagMatch == 0) { + if(generic_tl.tag >= NFAPI_VENDOR_EXTENSION_MIN_TAG_VALUE && + generic_tl.tag <= NFAPI_VENDOR_EXTENSION_MAX_TAG_VALUE) { + int result = unpack_p7_vendor_extension_tlv(&generic_tl, ppReadPackedMsg, end, config, ve); + + if(result == 0) { + // got to end + return 0; + } else if(result < 0) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "Unknown TAG value: 0x%04x\n", generic_tl.tag); + + if (++numBadTags > MAX_BAD_TAG) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "Supplied message has had too many bad tags\n"); + return -1; + } + + if((end - *ppReadPackedMsg) >= generic_tl.length) { + // Advance past the unknown TLV + (*ppReadPackedMsg) += generic_tl.length; + } else { + // got ot the dn + return 0; + } + } + } else { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "Unknown TAG value: 0x%04x\n", generic_tl.tag); + + if (++numBadTags > MAX_BAD_TAG) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "Supplied message has had too many bad tags\n"); + return -1; + } + + if((end - *ppReadPackedMsg) >= generic_tl.length) { + // Advance past the unknown TLV + (*ppReadPackedMsg) += generic_tl.length; + } else { + // got ot the dn + return 0; + } + } + } + } + + return 1; +} + +// This intermediate function deals with calculating the length of the value +// and writing into the tlv header. +uint8_t pack_tlv(uint16_t tag, void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end, pack_tlv_fn fn) { + nfapi_tl_t *tl = (nfapi_tl_t *)tlv; + + // If the tag is defined + if(tl->tag == tag) { + uint8_t *pStartOfTlv = *ppWritePackedMsg; + + // write a dumy tlv header + if(pack_tl(tl, ppWritePackedMsg, end) == 0) + return 0; + + // Record the start of the value + uint8_t *pStartOfValue = *ppWritePackedMsg; + + // pack the tlv value + if(fn(tlv, ppWritePackedMsg, end) == 0) + return 0; + + // calculate the length of the value and rewrite the tl header + tl->length = (*ppWritePackedMsg) - pStartOfValue; + // rewrite the header with the correct length + pack_tl(tl, &pStartOfTlv, end); + } else { + if(tl->tag != 0) { + NFAPI_TRACE(NFAPI_TRACE_WARN, "Warning pack_tlv tag 0x%x does not match expected 0x%x\n", tl->tag, tag); + } else { + //NFAPI_TRACE(NFAPI_TRACE_ERROR, "Warning pack_tlv tag 0x%x ZERO does not match expected 0x%x\n", tl->tag, tag); + } + } + + return 1; +} + +const char *nfapi_error_code_to_str(nfapi_error_code_e value) { + switch(value) { + case NFAPI_MSG_OK: + return "NFAPI_MSG_OK"; + + case NFAPI_MSG_INVALID_STATE: + return "NFAPI_MSG_INVALID_STATE"; + + case NFAPI_MSG_INVALID_CONFIG: + return "NFAPI_MSG_INVALID_CONFIG"; + + case NFAPI_SFN_OUT_OF_SYNC: + return "NFAPI_SFN_OUT_OF_SYNC"; + + case NFAPI_MSG_SUBFRAME_ERR: + return "NFAPI_MSG_SUBFRAME_ERR"; + + case NFAPI_MSG_BCH_MISSING: + return "NFAPI_MSG_BCH_MISSING"; + + case NFAPI_MSG_INVALID_SFN: + return "NFAPI_MSG_INVALID_SFN"; + + case NFAPI_MSG_HI_ERR: + return "NFAPI_MSG_HI_ERR"; + + case NFAPI_MSG_TX_ERR: + return "NFAPI_MSG_TX_ERR"; + + default: + return "UNKNOWN"; + } +} diff --git a/nfapi/open-nFAPI/nfapi/src/nfapi_p4.c b/nfapi/open-nFAPI/nfapi/src/nfapi_p4.c index b429e0a6ce..dbaa4347d3 100644 --- a/nfapi/open-nFAPI/nfapi/src/nfapi_p4.c +++ b/nfapi/open-nFAPI/nfapi/src/nfapi_p4.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. @@ -27,2059 +27,1804 @@ #include #include -static uint32_t get_packed_msg_len(uintptr_t msgHead, uintptr_t msgEnd) -{ - if (msgEnd < msgHead) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "get_packed_msg_len: Error in pointers supplied %d, %d\n", msgHead, msgEnd); - return 0; - } - - return (msgEnd - msgHead); +static uint32_t get_packed_msg_len(uintptr_t msgHead, uintptr_t msgEnd) { + if (msgEnd < msgHead) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "get_packed_msg_len: Error in pointers supplied %d, %d\n", msgHead, msgEnd); + return 0; + } + + return (msgEnd - msgHead); +} + +static uint8_t pack_opaque_data_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_opaqaue_data_t *value = (nfapi_opaqaue_data_t *)tlv; + return pusharray8(value->value, NFAPI_MAX_OPAQUE_DATA, value->length, ppWritePackedMsg, end); +} + +static uint8_t unpack_opaque_data_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_opaqaue_data_t *value = (nfapi_opaqaue_data_t *)tlv; + value->length = value->tl.length; + + if(value->length <= NFAPI_MAX_OPAQUE_DATA) { + if(!pullarray8(ppReadPackedMsg, value->value, NFAPI_MAX_OPAQUE_DATA, value->length, end)) + return 0; + } else { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "Opaque date to long %d \n", value->length); + return 0; + } + + return 1; +} + +static uint8_t pack_lte_rssi_request_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_lte_rssi_request_t *value = (nfapi_lte_rssi_request_t *)tlv; + return (push8(value->frequency_band_indicator, ppWritePackedMsg, end) && + push16(value->measurement_period, ppWritePackedMsg, end) && + push8(value->bandwidth, ppWritePackedMsg, end) && + push32(value->timeout, ppWritePackedMsg, end) && + push8(value->number_of_earfcns, ppWritePackedMsg, end) && + pusharray16(value->earfcn, NFAPI_MAX_CARRIER_LIST, value->number_of_earfcns, ppWritePackedMsg, end)); +} + +static uint8_t pack_utran_rssi_request_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_utran_rssi_request_t *value = (nfapi_utran_rssi_request_t *)tlv; + return (push8(value->frequency_band_indicator, ppWritePackedMsg, end) && + push16(value->measurement_period, ppWritePackedMsg, end) && + push32(value->timeout, ppWritePackedMsg, end) && + push8(value->number_of_uarfcns, ppWritePackedMsg, end) && + pusharray16(value->uarfcn, NFAPI_MAX_CARRIER_LIST, value->number_of_uarfcns, ppWritePackedMsg, end)); } -static uint8_t pack_opaque_data_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_opaqaue_data_t* value = (nfapi_opaqaue_data_t*)tlv; - return pusharray8(value->value, NFAPI_MAX_OPAQUE_DATA, value->length, ppWritePackedMsg, end); -} +static uint8_t pack_geran_rssi_request_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_geran_rssi_request_t *value = (nfapi_geran_rssi_request_t *)tlv; + uint16_t idx = 0; -static uint8_t unpack_opaque_data_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_opaqaue_data_t* value = (nfapi_opaqaue_data_t*)tlv; - value->length = value->tl.length; - if(value->length <= NFAPI_MAX_OPAQUE_DATA) - { - if(!pullarray8(ppReadPackedMsg, value->value, NFAPI_MAX_OPAQUE_DATA, value->length, end)) - return 0; - } - else - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "Opaque date to long %d \n", value->length); - return 0; - } - - return 1; - -} - -static uint8_t pack_lte_rssi_request_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_lte_rssi_request_t* value = (nfapi_lte_rssi_request_t*)tlv; - - return (push8(value->frequency_band_indicator, ppWritePackedMsg, end) && - push16(value->measurement_period, ppWritePackedMsg, end) && - push8(value->bandwidth, ppWritePackedMsg, end) && - push32(value->timeout, ppWritePackedMsg, end) && - push8(value->number_of_earfcns, ppWritePackedMsg, end) && - pusharray16(value->earfcn, NFAPI_MAX_CARRIER_LIST, value->number_of_earfcns, ppWritePackedMsg, end)); -} - -static uint8_t pack_utran_rssi_request_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_utran_rssi_request_t* value = (nfapi_utran_rssi_request_t*)tlv; - - return (push8(value->frequency_band_indicator, ppWritePackedMsg, end) && - push16(value->measurement_period, ppWritePackedMsg, end) && - push32(value->timeout, ppWritePackedMsg, end) && - push8(value->number_of_uarfcns, ppWritePackedMsg, end) && - pusharray16(value->uarfcn, NFAPI_MAX_CARRIER_LIST, value->number_of_uarfcns, ppWritePackedMsg, end)); -} - -static uint8_t pack_geran_rssi_request_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_geran_rssi_request_t* value = (nfapi_geran_rssi_request_t*)tlv; - uint16_t idx = 0; - - if(!(push8(value->frequency_band_indicator, ppWritePackedMsg, end) && - push16(value->measurement_period, ppWritePackedMsg, end) && - push32(value->timeout, ppWritePackedMsg, end) && - push8(value->number_of_arfcns, ppWritePackedMsg, end))) - return 0; + if(!(push8(value->frequency_band_indicator, ppWritePackedMsg, end) && + push16(value->measurement_period, ppWritePackedMsg, end) && + push32(value->timeout, ppWritePackedMsg, end) && + push8(value->number_of_arfcns, ppWritePackedMsg, end))) + return 0; - for(;idx < value->number_of_arfcns; ++idx) - { - if(!(push16(value->arfcn[idx].arfcn, ppWritePackedMsg, end) && - push8(value->arfcn[idx].direction, ppWritePackedMsg, end))) - return 0; - } - - return 1; + for(; idx < value->number_of_arfcns; ++idx) { + if(!(push16(value->arfcn[idx].arfcn, ppWritePackedMsg, end) && + push8(value->arfcn[idx].direction, ppWritePackedMsg, end))) + return 0; + } + + return 1; } -static uint8_t pack_nb_iot_rssi_request_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_nb_iot_rssi_request_t* value = (nfapi_nb_iot_rssi_request_t*)tlv; - uint16_t idx = 0; +static uint8_t pack_nb_iot_rssi_request_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_nb_iot_rssi_request_t *value = (nfapi_nb_iot_rssi_request_t *)tlv; + uint16_t idx = 0; - if(!(push8(value->frequency_band_indicator, ppWritePackedMsg, end) && - push16(value->measurement_period, ppWritePackedMsg, end) && - push32(value->timeout, ppWritePackedMsg, end) && - push8(value->number_of_earfcns, ppWritePackedMsg, end))) - return 0; + if(!(push8(value->frequency_band_indicator, ppWritePackedMsg, end) && + push16(value->measurement_period, ppWritePackedMsg, end) && + push32(value->timeout, ppWritePackedMsg, end) && + push8(value->number_of_earfcns, ppWritePackedMsg, end))) + return 0; - for(;idx < value->number_of_earfcns; ++idx) - { - if(!(push16(value->earfcn[idx].earfcn, ppWritePackedMsg, end) && - push8(value->earfcn[idx].number_of_ro_dl, ppWritePackedMsg, end))) - return 0; - - uint8_t ro_dl_idx = 0; - for(ro_dl_idx = 0; ro_dl_idx < value->earfcn[idx].number_of_ro_dl; ++ro_dl_idx) - { - if(!push8(value->earfcn[idx].ro_dl[ro_dl_idx], ppWritePackedMsg, end)) - return 0; - } - } + for(; idx < value->number_of_earfcns; ++idx) { + if(!(push16(value->earfcn[idx].earfcn, ppWritePackedMsg, end) && + push8(value->earfcn[idx].number_of_ro_dl, ppWritePackedMsg, end))) + return 0; - return 1; + uint8_t ro_dl_idx = 0; + + for(ro_dl_idx = 0; ro_dl_idx < value->earfcn[idx].number_of_ro_dl; ++ro_dl_idx) { + if(!push8(value->earfcn[idx].ro_dl[ro_dl_idx], ppWritePackedMsg, end)) + return 0; + } + } + + return 1; } -static uint8_t pack_rssi_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t* config) -{ - nfapi_rssi_request_t *pNfapiMsg = (nfapi_rssi_request_t*)msg; +static uint8_t pack_rssi_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t *config) { + nfapi_rssi_request_t *pNfapiMsg = (nfapi_rssi_request_t *)msg; + + if(push8(pNfapiMsg->rat_type, ppWritePackedMsg, end) == 0) + return 0; + + switch(pNfapiMsg->rat_type) { + case NFAPI_RAT_TYPE_LTE: + if(pack_tlv(NFAPI_LTE_RSSI_REQUEST_TAG, &pNfapiMsg->lte_rssi_request, ppWritePackedMsg, end, &pack_lte_rssi_request_value) == 0) + return 0; + + break; + + case NFAPI_RAT_TYPE_UTRAN: + if(pack_tlv(NFAPI_UTRAN_RSSI_REQUEST_TAG, &pNfapiMsg->utran_rssi_request, ppWritePackedMsg, end, &pack_utran_rssi_request_value) == 0) + return 0; + + break; + + case NFAPI_RAT_TYPE_GERAN: + if(pack_tlv(NFAPI_GERAN_RSSI_REQUEST_TAG, &pNfapiMsg->geran_rssi_request, ppWritePackedMsg, end, &pack_geran_rssi_request_value) == 0) + return 0; - if(push8(pNfapiMsg->rat_type, ppWritePackedMsg, end) == 0) - return 0; + break; - switch(pNfapiMsg->rat_type) - { - case NFAPI_RAT_TYPE_LTE: - if(pack_tlv(NFAPI_LTE_RSSI_REQUEST_TAG, &pNfapiMsg->lte_rssi_request, ppWritePackedMsg, end, &pack_lte_rssi_request_value) == 0) - return 0; - break; - case NFAPI_RAT_TYPE_UTRAN: - if(pack_tlv(NFAPI_UTRAN_RSSI_REQUEST_TAG, &pNfapiMsg->utran_rssi_request, ppWritePackedMsg, end, &pack_utran_rssi_request_value) == 0) - return 0; - break; - case NFAPI_RAT_TYPE_GERAN: - if(pack_tlv(NFAPI_GERAN_RSSI_REQUEST_TAG, &pNfapiMsg->geran_rssi_request, ppWritePackedMsg, end, &pack_geran_rssi_request_value) == 0) - return 0; - break; - case NFAPI_RAT_TYPE_NB_IOT: - if(pack_tlv(NFAPI_NB_IOT_RSSI_REQUEST_TAG, &pNfapiMsg->nb_iot_rssi_request, ppWritePackedMsg, end, &pack_nb_iot_rssi_request_value) == 0) - return 0; - break; - } - - return pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config); -} - -static uint8_t pack_rssi_response(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t* config) -{ - nfapi_rssi_response_t *pNfapiMsg = (nfapi_rssi_response_t*)msg; - - return (push32(pNfapiMsg->error_code, ppWritePackedMsg, end) && - pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); -} - -static uint8_t pack_rssi_indication_body_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_rssi_indication_body_t* value = (nfapi_rssi_indication_body_t*)tlv; - - return (push16(value->number_of_rssi, ppWritePackedMsg, end) && - pusharrays16(value->rssi, NFAPI_MAX_RSSI, value->number_of_rssi, ppWritePackedMsg, end)); -} - -static uint8_t pack_rssi_indication(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t* config) -{ - nfapi_rssi_indication_t *pNfapiMsg = (nfapi_rssi_indication_t*)msg; - - return (push32(pNfapiMsg->error_code, ppWritePackedMsg, end) && - pack_tlv(NFAPI_RSSI_INDICATION_TAG, &pNfapiMsg->rssi_indication_body, ppWritePackedMsg, end, &pack_rssi_indication_body_value) && - pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); -} - - -static uint8_t pack_lte_cell_search_request_value(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_lte_cell_search_request_t* value = (nfapi_lte_cell_search_request_t*)msg; - - return (push16(value->earfcn, ppWritePackedMsg, end) && - push8(value->measurement_bandwidth, ppWritePackedMsg, end) && - push8(value->exhaustive_search, ppWritePackedMsg, end) && - push32(value->timeout, ppWritePackedMsg, end) && - push8(value->number_of_pci, ppWritePackedMsg, end) && - pusharray16(value->pci, NFAPI_MAX_PCI_LIST, value->number_of_pci, ppWritePackedMsg, end)); -} - -static uint8_t pack_utran_cell_search_request_value(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_utran_cell_search_request_t* value = (nfapi_utran_cell_search_request_t*)msg; - - return (push16(value->uarfcn, ppWritePackedMsg, end) && - push8(value->exhaustive_search, ppWritePackedMsg, end) && - push32(value->timeout, ppWritePackedMsg, end) && - push8(value->number_of_psc, ppWritePackedMsg, end) && - pusharray16(value->psc, NFAPI_MAX_PSC_LIST, value->number_of_psc, ppWritePackedMsg, end)); -} - -static uint8_t pack_geran_cell_search_request_value(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_geran_cell_search_request_t* value = (nfapi_geran_cell_search_request_t*)msg; - - return (push32(value->timeout, ppWritePackedMsg, end) && - push8(value->number_of_arfcn, ppWritePackedMsg, end) && - pusharray16(value->arfcn, NFAPI_MAX_ARFCN_LIST, value->number_of_arfcn, ppWritePackedMsg, end)); -} - -static uint8_t pack_nb_iot_cell_search_request_value(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_nb_iot_cell_search_request_t* value = (nfapi_nb_iot_cell_search_request_t*)msg; - - return (push16(value->earfcn, ppWritePackedMsg, end) && - push8(value->ro_dl, ppWritePackedMsg, end) && - push8(value->exhaustive_search, ppWritePackedMsg, end) && - push32(value->timeout, ppWritePackedMsg, end) && - push8(value->number_of_pci, ppWritePackedMsg, end) && - pusharray16(value->pci, NFAPI_MAX_PCI_LIST, value->number_of_pci, ppWritePackedMsg, end)); -} - - -static uint8_t pack_cell_search_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t* config) -{ - nfapi_cell_search_request_t *pNfapiMsg = (nfapi_cell_search_request_t*)msg; - - if(push8(pNfapiMsg->rat_type, ppWritePackedMsg, end) == 0) - return 0; - - switch(pNfapiMsg->rat_type) - { - case NFAPI_RAT_TYPE_LTE: - { - if(pack_tlv(NFAPI_LTE_CELL_SEARCH_REQUEST_TAG, &pNfapiMsg->lte_cell_search_request, ppWritePackedMsg, end, &pack_lte_cell_search_request_value) == 0) - return 0; - } - break; - case NFAPI_RAT_TYPE_UTRAN: - { - if(pack_tlv(NFAPI_UTRAN_CELL_SEARCH_REQUEST_TAG, &pNfapiMsg->utran_cell_search_request, ppWritePackedMsg, end, &pack_utran_cell_search_request_value) == 0) - return 0; - } - break; - case NFAPI_RAT_TYPE_GERAN: - { - if(pack_tlv(NFAPI_GERAN_CELL_SEARCH_REQUEST_TAG, &pNfapiMsg->geran_cell_search_request, ppWritePackedMsg, end, &pack_geran_cell_search_request_value) == 0) - return 0; - } - break; - case NFAPI_RAT_TYPE_NB_IOT: - { - if(pack_tlv(NFAPI_NB_IOT_CELL_SEARCH_REQUEST_TAG, &pNfapiMsg->nb_iot_cell_search_request, ppWritePackedMsg, end, &pack_nb_iot_cell_search_request_value) == 0) - return 0; - } - break; - }; - - return (pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); -} - -static uint8_t pack_cell_search_response(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t* config) -{ - nfapi_cell_search_response_t *pNfapiMsg = (nfapi_cell_search_response_t*)msg; - - return (push32(pNfapiMsg->error_code, ppWritePackedMsg, end) && - pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); -} - -static uint8_t pack_lte_cell_search_indication_value(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_lte_cell_search_indication_t* value = (nfapi_lte_cell_search_indication_t*)msg; - uint16_t idx = 0; - - if(push16(value->number_of_lte_cells_found, ppWritePackedMsg, end) == 0) - return 0; - - for(idx = 0; idx < value->number_of_lte_cells_found; ++idx) - { - if(!(push16(value->lte_found_cells[idx].pci, ppWritePackedMsg, end) && - push8(value->lte_found_cells[idx].rsrp, ppWritePackedMsg, end) && - push8(value->lte_found_cells[idx].rsrq, ppWritePackedMsg, end) && - pushs16(value->lte_found_cells[idx].frequency_offset, ppWritePackedMsg, end))) - return 0; - } - return 1; -} - -static uint8_t pack_utran_cell_search_indication_value(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_utran_cell_search_indication_t* value = (nfapi_utran_cell_search_indication_t*)msg; - uint16_t idx = 0; - - if(push16(value->number_of_utran_cells_found, ppWritePackedMsg, end) == 0) - return 0; - - for(idx = 0; idx < value->number_of_utran_cells_found; ++idx) - { - if(!(push16(value->utran_found_cells[idx].psc, ppWritePackedMsg, end) && - push8(value->utran_found_cells[idx].rscp, ppWritePackedMsg, end) && - push8(value->utran_found_cells[idx].ecno, ppWritePackedMsg, end) && - pushs16(value->utran_found_cells[idx].frequency_offset, ppWritePackedMsg, end))) - return 0; - } - - return 1; -} - -static uint8_t pack_geran_cell_search_indication_value(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_geran_cell_search_indication_t* value = (nfapi_geran_cell_search_indication_t*)msg; - uint16_t idx = 0; - - if(push16(value->number_of_gsm_cells_found, ppWritePackedMsg, end) == 0) - return 0; - - for(idx = 0; idx < value->number_of_gsm_cells_found; ++idx) - { - if(!(push16(value->gsm_found_cells[idx].arfcn, ppWritePackedMsg, end) && - push8(value->gsm_found_cells[idx].bsic, ppWritePackedMsg, end) && - push8(value->gsm_found_cells[idx].rxlev, ppWritePackedMsg, end) && - push8(value->gsm_found_cells[idx].rxqual, ppWritePackedMsg, end) && - pushs16(value->gsm_found_cells[idx].frequency_offset, ppWritePackedMsg, end) && - push32(value->gsm_found_cells[idx].sfn_offset, ppWritePackedMsg, end))) - return 0; - } - - return 1; -} - -static uint8_t pack_nb_iot_cell_search_indication_value(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_nb_iot_cell_search_indication_t* value = (nfapi_nb_iot_cell_search_indication_t*)msg; - uint16_t idx = 0; - - if(push16(value->number_of_nb_iot_cells_found, ppWritePackedMsg, end) == 0) - return 0; - - for(idx = 0; idx < value->number_of_nb_iot_cells_found; ++idx) - { - if(!(push16(value->nb_iot_found_cells[idx].pci, ppWritePackedMsg, end) && - push8(value->nb_iot_found_cells[idx].rsrp, ppWritePackedMsg, end) && - push8(value->nb_iot_found_cells[idx].rsrq, ppWritePackedMsg, end) && - pushs16(value->nb_iot_found_cells[idx].frequency_offset, ppWritePackedMsg, end))) - return 0; - } - - return 1; -} -static uint8_t pack_cell_search_indication(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t* config) -{ - nfapi_cell_search_indication_t *pNfapiMsg = (nfapi_cell_search_indication_t*)msg; - - return (push32(pNfapiMsg->error_code, ppWritePackedMsg, end) && - pack_tlv(NFAPI_LTE_CELL_SEARCH_INDICATION_TAG, &pNfapiMsg->lte_cell_search_indication, ppWritePackedMsg, end, &pack_lte_cell_search_indication_value) && - pack_tlv(NFAPI_UTRAN_CELL_SEARCH_INDICATION_TAG, &pNfapiMsg->utran_cell_search_indication, ppWritePackedMsg, end, &pack_utran_cell_search_indication_value) && - pack_tlv(NFAPI_GERAN_CELL_SEARCH_INDICATION_TAG, &pNfapiMsg->geran_cell_search_indication, ppWritePackedMsg, end, &pack_geran_cell_search_indication_value) && - pack_tlv(NFAPI_PNF_CELL_SEARCH_STATE_TAG, &pNfapiMsg->pnf_cell_search_state, ppWritePackedMsg, end, &pack_opaque_data_value) && - pack_tlv(NFAPI_NB_IOT_CELL_SEARCH_INDICATION_TAG, &pNfapiMsg->nb_iot_cell_search_indication, ppWritePackedMsg, end, &pack_nb_iot_cell_search_indication_value) && - pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); - -} - -static uint8_t pack_lte_broadcast_detect_request_value(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_lte_broadcast_detect_request_t* value = (nfapi_lte_broadcast_detect_request_t*)msg; - - return (push16(value->earfcn, ppWritePackedMsg, end) && - push16(value->pci, ppWritePackedMsg, end) && - push32(value->timeout, ppWritePackedMsg, end)); -} - -static uint8_t pack_utran_broadcast_detect_request_value(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_utran_broadcast_detect_request_t* value = (nfapi_utran_broadcast_detect_request_t*)msg; - - return (push16(value->uarfcn, ppWritePackedMsg, end) && - push16(value->psc, ppWritePackedMsg, end) && - push32(value->timeout, ppWritePackedMsg, end)); -} - -static uint8_t pack_nb_iot_broadcast_detect_request_value(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_nb_iot_broadcast_detect_request_t* value = (nfapi_nb_iot_broadcast_detect_request_t*)msg; + case NFAPI_RAT_TYPE_NB_IOT: + if(pack_tlv(NFAPI_NB_IOT_RSSI_REQUEST_TAG, &pNfapiMsg->nb_iot_rssi_request, ppWritePackedMsg, end, &pack_nb_iot_rssi_request_value) == 0) + return 0; - return (push16(value->earfcn, ppWritePackedMsg, end) && - push8(value->ro_dl, ppWritePackedMsg, end) && - push16(value->pci, ppWritePackedMsg, end) && - push32(value->timeout, ppWritePackedMsg, end)); -} - -static uint8_t pack_broadcast_detect_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t * end, nfapi_p4_p5_codec_config_t* config) -{ - nfapi_broadcast_detect_request_t *pNfapiMsg = (nfapi_broadcast_detect_request_t*)msg; + break; + } - if(push8(pNfapiMsg->rat_type, ppWritePackedMsg, end) == 0) - return 0; + return pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config); +} + +static uint8_t pack_rssi_response(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t *config) { + nfapi_rssi_response_t *pNfapiMsg = (nfapi_rssi_response_t *)msg; + return (push32(pNfapiMsg->error_code, ppWritePackedMsg, end) && + pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); +} - switch(pNfapiMsg->rat_type) - { - case NFAPI_RAT_TYPE_LTE: - if(pack_tlv(NFAPI_LTE_BROADCAST_DETECT_REQUEST_TAG, &pNfapiMsg->lte_broadcast_detect_request, ppWritePackedMsg, end ,&pack_lte_broadcast_detect_request_value) == 0) - return 0; - break; - case NFAPI_RAT_TYPE_UTRAN: - if(pack_tlv(NFAPI_UTRAN_BROADCAST_DETECT_REQUEST_TAG, &pNfapiMsg->utran_broadcast_detect_request, ppWritePackedMsg, end, &pack_utran_broadcast_detect_request_value) == 0) - return 0; - break; - case NFAPI_RAT_TYPE_NB_IOT: - if(pack_tlv(NFAPI_NB_IOT_BROADCAST_DETECT_REQUEST_TAG, &pNfapiMsg->nb_iot_broadcast_detect_request, ppWritePackedMsg, end, &pack_nb_iot_broadcast_detect_request_value) == 0) - return 0; - break; - - } - - return (pack_tlv(NFAPI_PNF_CELL_SEARCH_STATE_TAG, &pNfapiMsg->pnf_cell_search_state, ppWritePackedMsg, end, &pack_opaque_data_value) && - pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); +static uint8_t pack_rssi_indication_body_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_rssi_indication_body_t *value = (nfapi_rssi_indication_body_t *)tlv; + return (push16(value->number_of_rssi, ppWritePackedMsg, end) && + pusharrays16(value->rssi, NFAPI_MAX_RSSI, value->number_of_rssi, ppWritePackedMsg, end)); } -static uint8_t pack_broadcast_detect_response(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t* config) -{ - nfapi_broadcast_detect_response_t *pNfapiMsg = (nfapi_broadcast_detect_response_t*)msg; - - return (push32(pNfapiMsg->error_code, ppWritePackedMsg, end) && - pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); +static uint8_t pack_rssi_indication(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t *config) { + nfapi_rssi_indication_t *pNfapiMsg = (nfapi_rssi_indication_t *)msg; + return (push32(pNfapiMsg->error_code, ppWritePackedMsg, end) && + pack_tlv(NFAPI_RSSI_INDICATION_TAG, &pNfapiMsg->rssi_indication_body, ppWritePackedMsg, end, &pack_rssi_indication_body_value) && + pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); } -static uint8_t pack_lte_broadcast_detect_indication_value(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_lte_broadcast_detect_indication_t* value = (nfapi_lte_broadcast_detect_indication_t*)msg; - return (push8(value->number_of_tx_antenna, ppWritePackedMsg, end) && - push16(value->mib_length, ppWritePackedMsg, end) && - pusharray8(value->mib, NFAPI_MAX_MIB_LENGTH, value->mib_length, ppWritePackedMsg, end) && - push32(value->sfn_offset, ppWritePackedMsg, end)); +static uint8_t pack_lte_cell_search_request_value(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_lte_cell_search_request_t *value = (nfapi_lte_cell_search_request_t *)msg; + return (push16(value->earfcn, ppWritePackedMsg, end) && + push8(value->measurement_bandwidth, ppWritePackedMsg, end) && + push8(value->exhaustive_search, ppWritePackedMsg, end) && + push32(value->timeout, ppWritePackedMsg, end) && + push8(value->number_of_pci, ppWritePackedMsg, end) && + pusharray16(value->pci, NFAPI_MAX_PCI_LIST, value->number_of_pci, ppWritePackedMsg, end)); } -static uint8_t pack_utran_broadcast_detect_indication_value(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_utran_broadcast_detect_indication_t* value = (nfapi_utran_broadcast_detect_indication_t*)msg; +static uint8_t pack_utran_cell_search_request_value(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_utran_cell_search_request_t *value = (nfapi_utran_cell_search_request_t *)msg; + return (push16(value->uarfcn, ppWritePackedMsg, end) && + push8(value->exhaustive_search, ppWritePackedMsg, end) && + push32(value->timeout, ppWritePackedMsg, end) && + push8(value->number_of_psc, ppWritePackedMsg, end) && + pusharray16(value->psc, NFAPI_MAX_PSC_LIST, value->number_of_psc, ppWritePackedMsg, end)); +} + +static uint8_t pack_geran_cell_search_request_value(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_geran_cell_search_request_t *value = (nfapi_geran_cell_search_request_t *)msg; + return (push32(value->timeout, ppWritePackedMsg, end) && + push8(value->number_of_arfcn, ppWritePackedMsg, end) && + pusharray16(value->arfcn, NFAPI_MAX_ARFCN_LIST, value->number_of_arfcn, ppWritePackedMsg, end)); +} - return (push16(value->mib_length, ppWritePackedMsg, end) && - pusharray8(value->mib, NFAPI_MAX_MIB_LENGTH, value->mib_length, ppWritePackedMsg, end) && - push32(value->sfn_offset, ppWritePackedMsg, end)); +static uint8_t pack_nb_iot_cell_search_request_value(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_nb_iot_cell_search_request_t *value = (nfapi_nb_iot_cell_search_request_t *)msg; + return (push16(value->earfcn, ppWritePackedMsg, end) && + push8(value->ro_dl, ppWritePackedMsg, end) && + push8(value->exhaustive_search, ppWritePackedMsg, end) && + push32(value->timeout, ppWritePackedMsg, end) && + push8(value->number_of_pci, ppWritePackedMsg, end) && + pusharray16(value->pci, NFAPI_MAX_PCI_LIST, value->number_of_pci, ppWritePackedMsg, end)); } -static uint8_t pack_nb_iot_broadcast_detect_indication_value(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_nb_iot_broadcast_detect_indication_t* value = (nfapi_nb_iot_broadcast_detect_indication_t*)msg; - return (push8(value->number_of_tx_antenna, ppWritePackedMsg, end) && - push16(value->mib_length, ppWritePackedMsg, end) && - pusharray8(value->mib, NFAPI_MAX_MIB_LENGTH, value->mib_length, ppWritePackedMsg, end) && - push32(value->sfn_offset, ppWritePackedMsg, end)); +static uint8_t pack_cell_search_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t *config) { + nfapi_cell_search_request_t *pNfapiMsg = (nfapi_cell_search_request_t *)msg; + + if(push8(pNfapiMsg->rat_type, ppWritePackedMsg, end) == 0) + return 0; + + switch(pNfapiMsg->rat_type) { + case NFAPI_RAT_TYPE_LTE: { + if(pack_tlv(NFAPI_LTE_CELL_SEARCH_REQUEST_TAG, &pNfapiMsg->lte_cell_search_request, ppWritePackedMsg, end, &pack_lte_cell_search_request_value) == 0) + return 0; + } + break; + + case NFAPI_RAT_TYPE_UTRAN: { + if(pack_tlv(NFAPI_UTRAN_CELL_SEARCH_REQUEST_TAG, &pNfapiMsg->utran_cell_search_request, ppWritePackedMsg, end, &pack_utran_cell_search_request_value) == 0) + return 0; + } + break; + + case NFAPI_RAT_TYPE_GERAN: { + if(pack_tlv(NFAPI_GERAN_CELL_SEARCH_REQUEST_TAG, &pNfapiMsg->geran_cell_search_request, ppWritePackedMsg, end, &pack_geran_cell_search_request_value) == 0) + return 0; + } + break; + + case NFAPI_RAT_TYPE_NB_IOT: { + if(pack_tlv(NFAPI_NB_IOT_CELL_SEARCH_REQUEST_TAG, &pNfapiMsg->nb_iot_cell_search_request, ppWritePackedMsg, end, &pack_nb_iot_cell_search_request_value) == 0) + return 0; + } + break; + }; + + return (pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); +} + +static uint8_t pack_cell_search_response(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t *config) { + nfapi_cell_search_response_t *pNfapiMsg = (nfapi_cell_search_response_t *)msg; + return (push32(pNfapiMsg->error_code, ppWritePackedMsg, end) && + pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); } -static uint8_t pack_broadcast_detect_indication(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t* config) -{ - nfapi_broadcast_detect_indication_t *pNfapiMsg = (nfapi_broadcast_detect_indication_t*)msg; +static uint8_t pack_lte_cell_search_indication_value(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_lte_cell_search_indication_t *value = (nfapi_lte_cell_search_indication_t *)msg; + uint16_t idx = 0; - return (push32(pNfapiMsg->error_code, ppWritePackedMsg, end) && - pack_tlv(NFAPI_LTE_BROADCAST_DETECT_INDICATION_TAG, &pNfapiMsg->lte_broadcast_detect_indication, ppWritePackedMsg, end, &pack_lte_broadcast_detect_indication_value) && - pack_tlv(NFAPI_UTRAN_BROADCAST_DETECT_INDICATION_TAG, &pNfapiMsg->utran_broadcast_detect_indication, ppWritePackedMsg, end, &pack_utran_broadcast_detect_indication_value) && - pack_tlv(NFAPI_PNF_CELL_BROADCAST_STATE_TAG, &pNfapiMsg->pnf_cell_broadcast_state, ppWritePackedMsg, end, &pack_opaque_data_value) && - pack_tlv(NFAPI_NB_IOT_BROADCAST_DETECT_INDICATION_TAG, &pNfapiMsg->nb_iot_broadcast_detect_indication, ppWritePackedMsg, end, &pack_nb_iot_broadcast_detect_indication_value) && - pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); + if(push16(value->number_of_lte_cells_found, ppWritePackedMsg, end) == 0) + return 0; + + for(idx = 0; idx < value->number_of_lte_cells_found; ++idx) { + if(!(push16(value->lte_found_cells[idx].pci, ppWritePackedMsg, end) && + push8(value->lte_found_cells[idx].rsrp, ppWritePackedMsg, end) && + push8(value->lte_found_cells[idx].rsrq, ppWritePackedMsg, end) && + pushs16(value->lte_found_cells[idx].frequency_offset, ppWritePackedMsg, end))) + return 0; + } + + return 1; } -static uint8_t pack_lte_system_information_schedule_request_value(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_lte_system_information_schedule_request_t* value = (nfapi_lte_system_information_schedule_request_t*)msg; +static uint8_t pack_utran_cell_search_indication_value(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_utran_cell_search_indication_t *value = (nfapi_utran_cell_search_indication_t *)msg; + uint16_t idx = 0; + + if(push16(value->number_of_utran_cells_found, ppWritePackedMsg, end) == 0) + return 0; - return (push16(value->earfcn, ppWritePackedMsg, end) && - push16(value->pci, ppWritePackedMsg, end) && - push16(value->downlink_channel_bandwidth, ppWritePackedMsg, end) && - push8(value->phich_configuration, ppWritePackedMsg, end) && - push8(value->number_of_tx_antenna, ppWritePackedMsg, end) && - push8(value->retry_count, ppWritePackedMsg, end) && - push32(value->timeout, ppWritePackedMsg, end)); + for(idx = 0; idx < value->number_of_utran_cells_found; ++idx) { + if(!(push16(value->utran_found_cells[idx].psc, ppWritePackedMsg, end) && + push8(value->utran_found_cells[idx].rscp, ppWritePackedMsg, end) && + push8(value->utran_found_cells[idx].ecno, ppWritePackedMsg, end) && + pushs16(value->utran_found_cells[idx].frequency_offset, ppWritePackedMsg, end))) + return 0; + } + + return 1; } -static uint8_t pack_nb_iot_system_information_schedule_request_value(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_nb_iot_system_information_schedule_request_t* value = (nfapi_nb_iot_system_information_schedule_request_t*)msg; +static uint8_t pack_geran_cell_search_indication_value(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_geran_cell_search_indication_t *value = (nfapi_geran_cell_search_indication_t *)msg; + uint16_t idx = 0; + + if(push16(value->number_of_gsm_cells_found, ppWritePackedMsg, end) == 0) + return 0; + + for(idx = 0; idx < value->number_of_gsm_cells_found; ++idx) { + if(!(push16(value->gsm_found_cells[idx].arfcn, ppWritePackedMsg, end) && + push8(value->gsm_found_cells[idx].bsic, ppWritePackedMsg, end) && + push8(value->gsm_found_cells[idx].rxlev, ppWritePackedMsg, end) && + push8(value->gsm_found_cells[idx].rxqual, ppWritePackedMsg, end) && + pushs16(value->gsm_found_cells[idx].frequency_offset, ppWritePackedMsg, end) && + push32(value->gsm_found_cells[idx].sfn_offset, ppWritePackedMsg, end))) + return 0; + } - return (push16(value->earfcn, ppWritePackedMsg, end) && - push8(value->ro_dl, ppWritePackedMsg, end) && - push16(value->pci, ppWritePackedMsg, end) && - push8(value->scheduling_info_sib1_nb, ppWritePackedMsg, end) && - push32(value->timeout, ppWritePackedMsg, end)); + return 1; } +static uint8_t pack_nb_iot_cell_search_indication_value(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_nb_iot_cell_search_indication_t *value = (nfapi_nb_iot_cell_search_indication_t *)msg; + uint16_t idx = 0; -static uint8_t pack_system_information_schedule_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t* config) -{ - nfapi_system_information_schedule_request_t *pNfapiMsg = (nfapi_system_information_schedule_request_t*)msg; + if(push16(value->number_of_nb_iot_cells_found, ppWritePackedMsg, end) == 0) + return 0; - if(push8(pNfapiMsg->rat_type, ppWritePackedMsg, end) == 0) - return 0; + for(idx = 0; idx < value->number_of_nb_iot_cells_found; ++idx) { + if(!(push16(value->nb_iot_found_cells[idx].pci, ppWritePackedMsg, end) && + push8(value->nb_iot_found_cells[idx].rsrp, ppWritePackedMsg, end) && + push8(value->nb_iot_found_cells[idx].rsrq, ppWritePackedMsg, end) && + pushs16(value->nb_iot_found_cells[idx].frequency_offset, ppWritePackedMsg, end))) + return 0; + } - switch(pNfapiMsg->rat_type) - { - case NFAPI_RAT_TYPE_LTE: - if(pack_tlv(NFAPI_LTE_SYSTEM_INFORMATION_SCHEDULE_REQUEST_TAG, &pNfapiMsg->lte_system_information_schedule_request, ppWritePackedMsg, end, &pack_lte_system_information_schedule_request_value) == 0) - return 0; - break; - case NFAPI_RAT_TYPE_NB_IOT: - if(pack_tlv(NFAPI_NB_IOT_SYSTEM_INFORMATION_SCHEDULE_REQUEST_TAG, &pNfapiMsg->nb_iot_system_information_schedule_request, ppWritePackedMsg, end, &pack_nb_iot_system_information_schedule_request_value) == 0) - return 0; - break; - } + return 1; +} +static uint8_t pack_cell_search_indication(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t *config) { + nfapi_cell_search_indication_t *pNfapiMsg = (nfapi_cell_search_indication_t *)msg; + return (push32(pNfapiMsg->error_code, ppWritePackedMsg, end) && + pack_tlv(NFAPI_LTE_CELL_SEARCH_INDICATION_TAG, &pNfapiMsg->lte_cell_search_indication, ppWritePackedMsg, end, &pack_lte_cell_search_indication_value) && + pack_tlv(NFAPI_UTRAN_CELL_SEARCH_INDICATION_TAG, &pNfapiMsg->utran_cell_search_indication, ppWritePackedMsg, end, &pack_utran_cell_search_indication_value) && + pack_tlv(NFAPI_GERAN_CELL_SEARCH_INDICATION_TAG, &pNfapiMsg->geran_cell_search_indication, ppWritePackedMsg, end, &pack_geran_cell_search_indication_value) && + pack_tlv(NFAPI_PNF_CELL_SEARCH_STATE_TAG, &pNfapiMsg->pnf_cell_search_state, ppWritePackedMsg, end, &pack_opaque_data_value) && + pack_tlv(NFAPI_NB_IOT_CELL_SEARCH_INDICATION_TAG, &pNfapiMsg->nb_iot_cell_search_indication, ppWritePackedMsg, end, &pack_nb_iot_cell_search_indication_value) && + pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); +} - return (pack_tlv(NFAPI_PNF_CELL_BROADCAST_STATE_TAG, &pNfapiMsg->pnf_cell_broadcast_state, ppWritePackedMsg, end, &pack_opaque_data_value) && - pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); +static uint8_t pack_lte_broadcast_detect_request_value(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_lte_broadcast_detect_request_t *value = (nfapi_lte_broadcast_detect_request_t *)msg; + return (push16(value->earfcn, ppWritePackedMsg, end) && + push16(value->pci, ppWritePackedMsg, end) && + push32(value->timeout, ppWritePackedMsg, end)); +} +static uint8_t pack_utran_broadcast_detect_request_value(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_utran_broadcast_detect_request_t *value = (nfapi_utran_broadcast_detect_request_t *)msg; + return (push16(value->uarfcn, ppWritePackedMsg, end) && + push16(value->psc, ppWritePackedMsg, end) && + push32(value->timeout, ppWritePackedMsg, end)); } -static uint8_t pack_system_information_schedule_response(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t* config) -{ - nfapi_system_information_schedule_response_t *pNfapiMsg = (nfapi_system_information_schedule_response_t*)msg; - - return (push32(pNfapiMsg->error_code, ppWritePackedMsg, end) && - pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); +static uint8_t pack_nb_iot_broadcast_detect_request_value(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_nb_iot_broadcast_detect_request_t *value = (nfapi_nb_iot_broadcast_detect_request_t *)msg; + return (push16(value->earfcn, ppWritePackedMsg, end) && + push8(value->ro_dl, ppWritePackedMsg, end) && + push16(value->pci, ppWritePackedMsg, end) && + push32(value->timeout, ppWritePackedMsg, end)); } -static uint8_t pack_lte_system_information_indication_value(void* msg, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_lte_system_information_indication_t* value = (nfapi_lte_system_information_indication_t*)msg; +static uint8_t pack_broadcast_detect_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t *config) { + nfapi_broadcast_detect_request_t *pNfapiMsg = (nfapi_broadcast_detect_request_t *)msg; + + if(push8(pNfapiMsg->rat_type, ppWritePackedMsg, end) == 0) + return 0; + + switch(pNfapiMsg->rat_type) { + case NFAPI_RAT_TYPE_LTE: + if(pack_tlv(NFAPI_LTE_BROADCAST_DETECT_REQUEST_TAG, &pNfapiMsg->lte_broadcast_detect_request, ppWritePackedMsg, end,&pack_lte_broadcast_detect_request_value) == 0) + return 0; + + break; + + case NFAPI_RAT_TYPE_UTRAN: + if(pack_tlv(NFAPI_UTRAN_BROADCAST_DETECT_REQUEST_TAG, &pNfapiMsg->utran_broadcast_detect_request, ppWritePackedMsg, end, &pack_utran_broadcast_detect_request_value) == 0) + return 0; + + break; - return (push8(value->sib_type, ppWritePackedMsg, end) && - push16(value->sib_length, ppWritePackedMsg, end) && - pusharray8(value->sib, NFAPI_MAX_SIB_LENGTH, value->sib_length, ppWritePackedMsg, end)); + case NFAPI_RAT_TYPE_NB_IOT: + if(pack_tlv(NFAPI_NB_IOT_BROADCAST_DETECT_REQUEST_TAG, &pNfapiMsg->nb_iot_broadcast_detect_request, ppWritePackedMsg, end, &pack_nb_iot_broadcast_detect_request_value) == 0) + return 0; + + break; + } + + return (pack_tlv(NFAPI_PNF_CELL_SEARCH_STATE_TAG, &pNfapiMsg->pnf_cell_search_state, ppWritePackedMsg, end, &pack_opaque_data_value) && + pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); } -static uint8_t pack_nb_iot_system_information_indication_value(void* msg, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_nb_iot_system_information_indication_t* value = (nfapi_nb_iot_system_information_indication_t*)msg; - - return (push8(value->sib_type, ppWritePackedMsg, end) && - push16(value->sib_length, ppWritePackedMsg, end) && - pusharray8(value->sib, NFAPI_MAX_SIB_LENGTH, value->sib_length, ppWritePackedMsg, end)); -} - -static uint8_t pack_system_information_schedule_indication(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t* config) -{ - nfapi_system_information_schedule_indication_t *pNfapiMsg = (nfapi_system_information_schedule_indication_t*)msg; - - return (push32(pNfapiMsg->error_code, ppWritePackedMsg, end) && - pack_tlv(NFAPI_LTE_SYSTEM_INFORMATION_INDICATION_TAG, &pNfapiMsg->lte_system_information_indication, ppWritePackedMsg, end, &pack_lte_system_information_indication_value) && - pack_tlv(NFAPI_NB_IOT_SYSTEM_INFORMATION_INDICATION_TAG, &pNfapiMsg->nb_iot_system_information_indication, ppWritePackedMsg, end, &pack_nb_iot_system_information_indication_value) && - pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); -} - -static uint8_t pack_lte_system_information_request_value(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_lte_system_information_request_t* value = (nfapi_lte_system_information_request_t*)msg; - uint16_t idx = 0; - - if(!(push16(value->earfcn, ppWritePackedMsg, end) && - push16(value->pci, ppWritePackedMsg, end) && - push16(value->downlink_channel_bandwidth, ppWritePackedMsg, end) && - push8(value->phich_configuration, ppWritePackedMsg, end) && - push8(value->number_of_tx_antenna, ppWritePackedMsg, end) && - push8(value->number_of_si_periodicity, ppWritePackedMsg, end))) - return 0; - - for(idx = 0; idx < value->number_of_si_periodicity; ++idx) - { - if(!(push8(value->si_periodicity[idx].si_periodicity, ppWritePackedMsg, end) && - push8(value->si_periodicity[idx].si_index, ppWritePackedMsg, end))) - return 0; - } - - return (push8(value->si_window_length, ppWritePackedMsg, end) && - push32(value->timeout, ppWritePackedMsg, end)); -} -static uint8_t pack_utran_system_information_request_value(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_utran_system_information_request_t* value = (nfapi_utran_system_information_request_t*)msg; - - return (push16(value->uarfcn, ppWritePackedMsg, end) && - push16(value->psc, ppWritePackedMsg, end) && - push32(value->timeout, ppWritePackedMsg, end)); -} -static uint8_t pack_geran_system_information_request_value(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_geran_system_information_request_t* value = (nfapi_geran_system_information_request_t*)msg; - - return (push16(value->arfcn, ppWritePackedMsg, end) && - push8(value->bsic, ppWritePackedMsg, end) && - push32(value->timeout, ppWritePackedMsg, end)); -} -static uint8_t pack_nb_iot_system_information_request_value(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_nb_iot_system_information_request_t* value = (nfapi_nb_iot_system_information_request_t*)msg; - uint16_t idx = 0; - - if(!(push16(value->earfcn, ppWritePackedMsg, end) && - push8(value->ro_dl, ppWritePackedMsg, end) && - push16(value->pci, ppWritePackedMsg, end) && - push8(value->number_of_si_periodicity, ppWritePackedMsg, end))) - return 0; - - for(idx = 0; idx < value->number_of_si_periodicity; ++idx) - { - if(!(push8(value->si_periodicity[idx].si_periodicity, ppWritePackedMsg, end) && - push8(value->si_periodicity[idx].si_repetition_pattern, ppWritePackedMsg, end) && - push8(value->si_periodicity[idx].si_tb_size, ppWritePackedMsg, end) && - push8(value->si_periodicity[idx].number_of_si_index, ppWritePackedMsg, end))) - return 0; - - uint8_t si_idx; - for(si_idx = 0; si_idx < value->si_periodicity[idx].number_of_si_index; ++si_idx) - { - if(!(push8(value->si_periodicity[idx].si_index[si_idx], ppWritePackedMsg, end))) - return 0; - } - } - - return (push8(value->si_window_length, ppWritePackedMsg, end) && - push32(value->timeout, ppWritePackedMsg, end)); -} - - -static uint8_t pack_system_information_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t* config) -{ - nfapi_system_information_request_t *pNfapiMsg = (nfapi_system_information_request_t*)msg; - - if(push8(pNfapiMsg->rat_type, ppWritePackedMsg, end) == 0) - return 0; - - switch(pNfapiMsg->rat_type) - { - case NFAPI_RAT_TYPE_LTE: - if(pack_tlv(NFAPI_LTE_SYSTEM_INFORMATION_REQUEST_TAG, &pNfapiMsg->lte_system_information_request, ppWritePackedMsg, end, &pack_lte_system_information_request_value) == 0) - return 0; - break; - case NFAPI_RAT_TYPE_UTRAN: - if(pack_tlv(NFAPI_UTRAN_SYSTEM_INFORMATION_REQUEST_TAG, &pNfapiMsg->utran_system_information_request, ppWritePackedMsg, end, &pack_utran_system_information_request_value) == 0) - return 0; - break; - case NFAPI_RAT_TYPE_GERAN: - if(pack_tlv(NFAPI_GERAN_SYSTEM_INFORMATION_REQUEST_TAG, &pNfapiMsg->geran_system_information_request, ppWritePackedMsg, end, &pack_geran_system_information_request_value) == 0) - return 0; - break; - case NFAPI_RAT_TYPE_NB_IOT: - if(pack_tlv(NFAPI_NB_IOT_SYSTEM_INFORMATION_REQUEST_TAG, &pNfapiMsg->nb_iot_system_information_request, ppWritePackedMsg, end, &pack_nb_iot_system_information_request_value) == 0) - return 0; - break; - } - - return (pack_tlv(NFAPI_PNF_CELL_BROADCAST_STATE_TAG, &pNfapiMsg->pnf_cell_broadcast_state, ppWritePackedMsg, end, &pack_opaque_data_value) && - pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); -} - -static uint8_t pack_system_information_response(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t* config) -{ - nfapi_system_information_response_t *pNfapiMsg = (nfapi_system_information_response_t*)msg; - - return (push32(pNfapiMsg->error_code, ppWritePackedMsg, end) && - pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); -} - -static uint8_t pack_utran_system_information_indication_value(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_utran_system_information_indication_t* value = (nfapi_utran_system_information_indication_t*)msg; - - return (push16(value->sib_length, ppWritePackedMsg, end) && - pusharray8(value->sib, NFAPI_MAX_SIB_LENGTH, value->sib_length, ppWritePackedMsg, end)); -} - -static uint8_t pack_geran_system_information_indication_value(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_geran_system_information_indication_t* value = (nfapi_geran_system_information_indication_t*)msg; - - return (push16(value->si_length, ppWritePackedMsg, end) && - pusharray8(value->si, NFAPI_MAX_SIB_LENGTH, value->si_length, ppWritePackedMsg, end)); -} - -static uint8_t pack_system_information_indication(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t* config) -{ - nfapi_system_information_indication_t *pNfapiMsg = (nfapi_system_information_indication_t*)msg; - - return (push32(pNfapiMsg->error_code, ppWritePackedMsg, end) && - pack_tlv(NFAPI_LTE_SYSTEM_INFORMATION_INDICATION_TAG, &pNfapiMsg->lte_system_information_indication, ppWritePackedMsg, end, &pack_lte_system_information_indication_value) && - pack_tlv(NFAPI_UTRAN_SYSTEM_INFORMATION_INDICATION_TAG, &pNfapiMsg->utran_system_information_indication, ppWritePackedMsg, end, &pack_utran_system_information_indication_value) && - pack_tlv(NFAPI_GERAN_SYSTEM_INFORMATION_INDICATION_TAG, &pNfapiMsg->geran_system_information_indication, ppWritePackedMsg, end, &pack_geran_system_information_indication_value) && - pack_tlv(NFAPI_NB_IOT_SYSTEM_INFORMATION_INDICATION_TAG, &pNfapiMsg->nb_iot_system_information_indication, ppWritePackedMsg, end, &pack_nb_iot_system_information_indication_value) && - pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); -} - -static uint8_t pack_nmm_stop_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t* config) -{ - nfapi_nmm_stop_request_t *pNfapiMsg = (nfapi_nmm_stop_request_t*)msg; - - return (pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); -} - -static uint8_t pack_nmm_stop_response(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t* config) -{ - nfapi_nmm_stop_response_t *pNfapiMsg = (nfapi_nmm_stop_response_t*)msg; - - return (push32(pNfapiMsg->error_code, ppWritePackedMsg, end) && - pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); -} - -static uint8_t unpack_lte_rssi_request_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - //int result = 0; - nfapi_lte_rssi_request_t* value = (nfapi_lte_rssi_request_t*)tlv; - - if(!(pull8(ppReadPackedMsg, &value->frequency_band_indicator, end) && - pull16(ppReadPackedMsg, &value->measurement_period, end) && - pull8(ppReadPackedMsg, &value->bandwidth, end) && - pull32(ppReadPackedMsg, &value->timeout, end) && - pull8(ppReadPackedMsg, &value->number_of_earfcns, end))) - return 0; - - if(value->number_of_earfcns <= NFAPI_MAX_CARRIER_LIST) - { - if(pullarray16(ppReadPackedMsg, value->earfcn, NFAPI_MAX_CARRIER_LIST, value->number_of_earfcns, end) == 0) - return 0; - } - else - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "More EARFCN's than we can decode %d \n", value->number_of_earfcns); - return 0; - } - - return 1; - -} - -static uint8_t unpack_utran_rssi_request_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_utran_rssi_request_t* value = (nfapi_utran_rssi_request_t*)tlv; - - if(!(pull8(ppReadPackedMsg, &value->frequency_band_indicator, end) && - pull16(ppReadPackedMsg, &value->measurement_period, end) && - pull32(ppReadPackedMsg, &value->timeout, end) && - pull8(ppReadPackedMsg, &value->number_of_uarfcns, end))) - return 0; - - if(value->number_of_uarfcns <= NFAPI_MAX_CARRIER_LIST) - { - if(pullarray16(ppReadPackedMsg, value->uarfcn, NFAPI_MAX_CARRIER_LIST, value->number_of_uarfcns, end) == 0) - return 0; - } - else - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "More UARFCN's than we can decode %d \n", value->number_of_uarfcns); - return 0; - } - - return 1; -} - -static uint8_t unpack_geran_rssi_request_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_geran_rssi_request_t* value = (nfapi_geran_rssi_request_t*)tlv; - uint16_t idx = 0; - - if(!(pull8(ppReadPackedMsg, &value->frequency_band_indicator, end) && - pull16(ppReadPackedMsg, &value->measurement_period, end) && - pull32(ppReadPackedMsg, &value->timeout, end) && - pull8(ppReadPackedMsg, &value->number_of_arfcns, end))) - return 0; - - if(value->number_of_arfcns <= NFAPI_MAX_CARRIER_LIST) - { - for(idx = 0; idx < value->number_of_arfcns; ++idx) - { - if(!(pull16(ppReadPackedMsg, &value->arfcn[idx].arfcn, end) && - pull8(ppReadPackedMsg, &value->arfcn[idx].direction, end))) - return 0; - } - } - else - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "More ARFCN's than we can decode %d \n", value->number_of_arfcns); - return 0; - } - - return 1; -} - -static uint8_t unpack_nb_iot_rssi_request_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_nb_iot_rssi_request_t* value = (nfapi_nb_iot_rssi_request_t*)tlv; - uint16_t idx = 0; - - if(!(pull8(ppReadPackedMsg, &value->frequency_band_indicator, end) && - pull16(ppReadPackedMsg, &value->measurement_period, end) && - pull32(ppReadPackedMsg, &value->timeout, end) && - pull8(ppReadPackedMsg, &value->number_of_earfcns, end))) - return 0; - - if(value->number_of_earfcns <= NFAPI_MAX_CARRIER_LIST) - { - for(idx = 0; idx < value->number_of_earfcns; ++idx) - { - if(!(pull16(ppReadPackedMsg, &value->earfcn[idx].earfcn, end) && - pull8(ppReadPackedMsg, &value->earfcn[idx].number_of_ro_dl, end))) - return 0; - - if(value->earfcn[idx].number_of_ro_dl <= NFAPI_MAX_RO_DL) - { - uint8_t ro_dl_idx = 0; - for(ro_dl_idx = 0; ro_dl_idx < value->earfcn[idx].number_of_ro_dl; ++ro_dl_idx) - { - if(!pull8(ppReadPackedMsg, &value->earfcn[idx].ro_dl[ro_dl_idx], end)) - return 0; - } - } - else - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "More ROdl's than we can decode %d \n", value->earfcn[idx].number_of_ro_dl); - return 0; - } - - } - } - else - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "More EARFCN's than we can decode %d \n", value->number_of_earfcns); - return 0; - } - - return 1; -} - -static uint8_t unpack_rssi_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t* config) -{ - nfapi_rssi_request_t *pNfapiMsg = (nfapi_rssi_request_t*)msg; - - unpack_tlv_t unpack_fns[] = - { - { NFAPI_LTE_RSSI_REQUEST_TAG, &pNfapiMsg->lte_rssi_request, &unpack_lte_rssi_request_value}, - { NFAPI_UTRAN_RSSI_REQUEST_TAG, &pNfapiMsg->utran_rssi_request, &unpack_utran_rssi_request_value}, - { NFAPI_GERAN_RSSI_REQUEST_TAG, &pNfapiMsg->geran_rssi_request, &unpack_geran_rssi_request_value}, - { NFAPI_NB_IOT_RSSI_REQUEST_TAG, &pNfapiMsg->nb_iot_rssi_request, &unpack_nb_iot_rssi_request_value}, - }; - - int result = 0; - - result = (pull8(ppReadPackedMsg, &pNfapiMsg->rat_type, end) && - unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &(pNfapiMsg->vendor_extension))); - - - // Verify that the rat type and the tlv match - if(result == 1 && - !((pNfapiMsg->rat_type == NFAPI_RAT_TYPE_LTE && pNfapiMsg->lte_rssi_request.tl.tag == NFAPI_LTE_RSSI_REQUEST_TAG) || - (pNfapiMsg->rat_type == NFAPI_RAT_TYPE_UTRAN && pNfapiMsg->utran_rssi_request.tl.tag == NFAPI_UTRAN_RSSI_REQUEST_TAG) || - (pNfapiMsg->rat_type == NFAPI_RAT_TYPE_GERAN && pNfapiMsg->geran_rssi_request.tl.tag == NFAPI_GERAN_RSSI_REQUEST_TAG) || - (pNfapiMsg->rat_type == NFAPI_RAT_TYPE_NB_IOT && pNfapiMsg->nb_iot_rssi_request.tl.tag == NFAPI_NB_IOT_RSSI_REQUEST_TAG))) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "Mismatch RAT Type: %d and TAG value: 0x%04x \n", pNfapiMsg->rat_type, pNfapiMsg->lte_rssi_request.tl.tag); - result = 0; - } - - return result; -} - -static uint8_t unpack_rssi_response(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t* config) -{ - nfapi_rssi_response_t *pNfapiMsg = (nfapi_rssi_response_t*)msg; - - unpack_tlv_t unpack_fns[] = - { - }; - - return (pull32(ppReadPackedMsg, &pNfapiMsg->error_code, end) && - unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &(pNfapiMsg->vendor_extension))); -} - -static uint8_t unpack_rssi_indication_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_rssi_indication_body_t* value = (nfapi_rssi_indication_body_t*)tlv; - - if(pull16(ppReadPackedMsg, &value->number_of_rssi, end) == 0) - return 0; - - if(value->number_of_rssi <= NFAPI_MAX_RSSI) - { - if(pullarrays16(ppReadPackedMsg, value->rssi, NFAPI_MAX_RSSI, value->number_of_rssi, end) == 0) - return 0; - } - else - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "More RSSI's than we can decode %d \n", value->number_of_rssi); - return 0; - } - - return 1; -} - -static uint8_t unpack_rssi_indication(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t* config) -{ - nfapi_rssi_indication_t *pNfapiMsg = (nfapi_rssi_indication_t*)msg; - - unpack_tlv_t unpack_fns[] = - { - { NFAPI_RSSI_INDICATION_TAG, &pNfapiMsg->rssi_indication_body, &unpack_rssi_indication_value}, - }; - - return (pull32(ppReadPackedMsg, &pNfapiMsg->error_code, end) && - unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); -} - -static uint8_t unpack_lte_cell_search_request_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_lte_cell_search_request_t* value = (nfapi_lte_cell_search_request_t*)tlv; - - if(!(pull16(ppReadPackedMsg, &value->earfcn, end) && - pull8(ppReadPackedMsg, &value->measurement_bandwidth, end) && - pull8(ppReadPackedMsg, &value->exhaustive_search, end) && - pull32(ppReadPackedMsg, &value->timeout, end) && - pull8(ppReadPackedMsg, &value->number_of_pci, end))) - return 0; - - if(value->number_of_pci <= NFAPI_MAX_PCI_LIST) - { - if(pullarray16(ppReadPackedMsg, value->pci, NFAPI_MAX_PCI_LIST, value->number_of_pci, end) == 0) - return 0; - } - else - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "More PCI's than we can decode %d \n", value->number_of_pci); - return 0; - } - return 1; -} - -static uint8_t unpack_utran_cell_search_request_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_utran_cell_search_request_t* value = (nfapi_utran_cell_search_request_t*)tlv; - - if(!(pull16(ppReadPackedMsg, &value->uarfcn, end) && - pull8(ppReadPackedMsg, &value->exhaustive_search, end) && - pull32(ppReadPackedMsg, &value->timeout, end) && - pull8(ppReadPackedMsg, &value->number_of_psc, end))) - return 0; - - if(value->number_of_psc <= NFAPI_MAX_PSC_LIST) - { - if(pullarray16(ppReadPackedMsg, value->psc, NFAPI_MAX_PSC_LIST, value->number_of_psc, end) == 0) - return 0; - } - else - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "More PSC's than we can decode %d \n", value->number_of_psc); - return 0; - } - return 1; -} - -static uint8_t unpack_geran_cell_search_request_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_geran_cell_search_request_t* value = (nfapi_geran_cell_search_request_t*)tlv; - - if(!(pull32(ppReadPackedMsg, &value->timeout, end) && - pull8(ppReadPackedMsg, &value->number_of_arfcn, end))) - return 0; - - if(value->number_of_arfcn <= NFAPI_MAX_ARFCN_LIST) - { - if(pullarray16(ppReadPackedMsg, value->arfcn, NFAPI_MAX_ARFCN_LIST, value->number_of_arfcn, end) == 0) - return 0; - } - else - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "More ARFCN's than we can decode %d \n", value->number_of_arfcn); - return 0; - } - return 1; -} - -static uint8_t unpack_nb_iot_cell_search_request_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_nb_iot_cell_search_request_t* value = (nfapi_nb_iot_cell_search_request_t*)tlv; - - if(!(pull16(ppReadPackedMsg, &value->earfcn, end) && - pull8(ppReadPackedMsg, &value->ro_dl, end) && - pull8(ppReadPackedMsg, &value->exhaustive_search, end) && - pull32(ppReadPackedMsg, &value->timeout, end) && - pull8(ppReadPackedMsg, &value->number_of_pci, end))) - return 0; - - if(value->number_of_pci <= NFAPI_MAX_PCI_LIST) - { - if(pullarray16(ppReadPackedMsg, value->pci, NFAPI_MAX_PCI_LIST, value->number_of_pci, end) == 0) - return 0; - } - else - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "More PCI's than we can decode %d \n", value->number_of_pci); - return 0; - } - return 1; -} - -static uint8_t unpack_cell_search_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t* config) -{ - nfapi_cell_search_request_t *pNfapiMsg = (nfapi_cell_search_request_t*)msg; - - unpack_tlv_t unpack_fns[] = - { - { NFAPI_LTE_CELL_SEARCH_REQUEST_TAG, &pNfapiMsg->lte_cell_search_request, &unpack_lte_cell_search_request_value}, - { NFAPI_UTRAN_CELL_SEARCH_REQUEST_TAG, &pNfapiMsg->utran_cell_search_request, &unpack_utran_cell_search_request_value}, - { NFAPI_GERAN_CELL_SEARCH_REQUEST_TAG, &pNfapiMsg->geran_cell_search_request, &unpack_geran_cell_search_request_value}, - { NFAPI_NB_IOT_CELL_SEARCH_REQUEST_TAG, &pNfapiMsg->nb_iot_cell_search_request, &unpack_nb_iot_cell_search_request_value}, - }; - - int result = (pull8(ppReadPackedMsg, &pNfapiMsg->rat_type, end) && - unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); - - // Verify that the rat type and the tlv match - if(result == 1 && - !((pNfapiMsg->rat_type == NFAPI_RAT_TYPE_LTE && pNfapiMsg->lte_cell_search_request.tl.tag == NFAPI_LTE_CELL_SEARCH_REQUEST_TAG) || - (pNfapiMsg->rat_type == NFAPI_RAT_TYPE_UTRAN && pNfapiMsg->utran_cell_search_request.tl.tag == NFAPI_UTRAN_CELL_SEARCH_REQUEST_TAG) || - (pNfapiMsg->rat_type == NFAPI_RAT_TYPE_GERAN && pNfapiMsg->geran_cell_search_request.tl.tag == NFAPI_GERAN_CELL_SEARCH_REQUEST_TAG) || - (pNfapiMsg->rat_type == NFAPI_RAT_TYPE_NB_IOT && pNfapiMsg->nb_iot_cell_search_request.tl.tag == NFAPI_NB_IOT_CELL_SEARCH_REQUEST_TAG))) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "Mismatch RAT Type: %d and TAG value: 0x%04x \n", pNfapiMsg->rat_type, pNfapiMsg->lte_cell_search_request.tl.tag); - result = 0; - } - - return result; -} - -static uint8_t unpack_cell_search_response(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t* config) -{ - nfapi_cell_search_response_t *pNfapiMsg = (nfapi_cell_search_response_t*)msg; - - unpack_tlv_t unpack_fns[] = - { - }; - - return (pull32(ppReadPackedMsg, &pNfapiMsg->error_code, end) && - unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); -} - -static uint8_t unpack_lte_cell_search_indication_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_lte_cell_search_indication_t* value = (nfapi_lte_cell_search_indication_t*)tlv; - - uint16_t idx = 0; - if(pull16(ppReadPackedMsg, &value->number_of_lte_cells_found, end) == 0) - return 0; - - if(value->number_of_lte_cells_found <= NFAPI_MAX_LTE_CELLS_FOUND) - { - for(idx = 0; idx < value->number_of_lte_cells_found; ++idx) - { - if(!(pull16(ppReadPackedMsg, &value->lte_found_cells[idx].pci, end) && - pull8(ppReadPackedMsg, &value->lte_found_cells[idx].rsrp, end) && - pull8(ppReadPackedMsg, &value->lte_found_cells[idx].rsrq, end) && - pulls16(ppReadPackedMsg, &value->lte_found_cells[idx].frequency_offset, end))) - return 0; - } - } - else - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "More found LTE cells than we can decode %d \n", value->number_of_lte_cells_found); - return 0; - } - return 1; -} - -static uint8_t unpack_utran_cell_search_indication_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_utran_cell_search_indication_t* value = (nfapi_utran_cell_search_indication_t*)tlv; - - uint16_t idx = 0; - if(pull16(ppReadPackedMsg, &value->number_of_utran_cells_found, end) == 0) - return 0; - - if(value->number_of_utran_cells_found <= NFAPI_MAX_UTRAN_CELLS_FOUND) - { - for(idx = 0; idx < value->number_of_utran_cells_found; ++idx) - { - if(!(pull16(ppReadPackedMsg, &value->utran_found_cells[idx].psc, end) && - pull8(ppReadPackedMsg, &value->utran_found_cells[idx].rscp, end) && - pull8(ppReadPackedMsg, &value->utran_found_cells[idx].ecno, end) && - pulls16(ppReadPackedMsg, &value->utran_found_cells[idx].frequency_offset, end))) - return 0; - } - } - else - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "More found UTRAN cells than we can decode %d \n", value->number_of_utran_cells_found); - return 0; - } - return 1; -} - -static uint8_t unpack_geran_cell_search_indication_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_geran_cell_search_indication_t* value = (nfapi_geran_cell_search_indication_t*)tlv; - - uint16_t idx = 0; - if(pull16(ppReadPackedMsg, &value->number_of_gsm_cells_found, end) == 0) - return 0; - - if(value->number_of_gsm_cells_found <= NFAPI_MAX_GSM_CELLS_FOUND) - { - for(idx = 0; idx < value->number_of_gsm_cells_found; ++idx) - { - if(!(pull16(ppReadPackedMsg, &value->gsm_found_cells[idx].arfcn, end) && - pull8(ppReadPackedMsg, &value->gsm_found_cells[idx].bsic, end) && - pull8(ppReadPackedMsg, &value->gsm_found_cells[idx].rxlev, end) && - pull8(ppReadPackedMsg, &value->gsm_found_cells[idx].rxqual, end) && - pulls16(ppReadPackedMsg, &value->gsm_found_cells[idx].frequency_offset, end) && - pull32(ppReadPackedMsg, &value->gsm_found_cells[idx].sfn_offset, end))) - return 0; - } - } - else - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "More found GSM cells than we can decode %d \n", value->number_of_gsm_cells_found); - return 0; - } - return 1; -} - -static uint8_t unpack_nb_iot_cell_search_indication_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_nb_iot_cell_search_indication_t* value = (nfapi_nb_iot_cell_search_indication_t*)tlv; - - uint16_t idx = 0; - if(pull16(ppReadPackedMsg, &value->number_of_nb_iot_cells_found, end) == 0) - return 0; - - if(value->number_of_nb_iot_cells_found <= NFAPI_MAX_NB_IOT_CELLS_FOUND) - { - for(idx = 0; idx < value->number_of_nb_iot_cells_found; ++idx) - { - if(!(pull16(ppReadPackedMsg, &value->nb_iot_found_cells[idx].pci, end) && - pull8(ppReadPackedMsg, &value->nb_iot_found_cells[idx].rsrp, end) && - pull8(ppReadPackedMsg, &value->nb_iot_found_cells[idx].rsrq, end) && - pulls16(ppReadPackedMsg, &value->nb_iot_found_cells[idx].frequency_offset, end))) - return 0; - } - } - else - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "More found NB_IOT cells than we can decode %d \n", value->number_of_nb_iot_cells_found); - return 0; - } - return 1; -} - -static uint8_t unpack_cell_search_indication(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t* config) -{ - nfapi_cell_search_indication_t *pNfapiMsg = (nfapi_cell_search_indication_t*)msg; - - unpack_tlv_t unpack_fns[] = - { - { NFAPI_LTE_CELL_SEARCH_INDICATION_TAG, &pNfapiMsg->lte_cell_search_indication, &unpack_lte_cell_search_indication_value}, - { NFAPI_UTRAN_CELL_SEARCH_INDICATION_TAG, &pNfapiMsg->utran_cell_search_indication, &unpack_utran_cell_search_indication_value}, - { NFAPI_GERAN_CELL_SEARCH_INDICATION_TAG, &pNfapiMsg->geran_cell_search_indication, &unpack_geran_cell_search_indication_value}, - { NFAPI_PNF_CELL_SEARCH_STATE_TAG, &pNfapiMsg->pnf_cell_search_state, &unpack_opaque_data_value}, - { NFAPI_NB_IOT_CELL_SEARCH_INDICATION_TAG, &pNfapiMsg->nb_iot_cell_search_indication, &unpack_nb_iot_cell_search_indication_value}, - }; - - return (pull32(ppReadPackedMsg, &pNfapiMsg->error_code, end) && - unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); - -} - -static uint8_t unpack_lte_broadcast_detect_request_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_lte_broadcast_detect_request_t* value = (nfapi_lte_broadcast_detect_request_t*)tlv; - - return (pull16(ppReadPackedMsg, &value->earfcn, end) && - pull16(ppReadPackedMsg, &value->pci, end) && - pull32(ppReadPackedMsg, &value->timeout, end)); -} - -static uint8_t unpack_utran_broadcast_detect_request_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_utran_broadcast_detect_request_t* value = (nfapi_utran_broadcast_detect_request_t*)tlv; - - return (pull16(ppReadPackedMsg, &value->uarfcn, end) && - pull16(ppReadPackedMsg, &value->psc, end) && - pull32(ppReadPackedMsg, &value->timeout, end)); -} - -static uint8_t unpack_nb_iot_broadcast_detect_request_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_nb_iot_broadcast_detect_request_t* value = (nfapi_nb_iot_broadcast_detect_request_t*)tlv; - - return (pull16(ppReadPackedMsg, &value->earfcn, end) && - pull8(ppReadPackedMsg, &value->ro_dl, end) && - pull16(ppReadPackedMsg, &value->pci, end) && - pull32(ppReadPackedMsg, &value->timeout, end)); -} - -static uint8_t unpack_broadcast_detect_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t* config) -{ - nfapi_broadcast_detect_request_t *pNfapiMsg = (nfapi_broadcast_detect_request_t*)msg; - - unpack_tlv_t unpack_fns[] = - { - { NFAPI_LTE_BROADCAST_DETECT_REQUEST_TAG, &pNfapiMsg->lte_broadcast_detect_request, &unpack_lte_broadcast_detect_request_value}, - { NFAPI_UTRAN_BROADCAST_DETECT_REQUEST_TAG, &pNfapiMsg->utran_broadcast_detect_request, &unpack_utran_broadcast_detect_request_value}, - { NFAPI_PNF_CELL_SEARCH_STATE_TAG, &pNfapiMsg->pnf_cell_search_state, &unpack_opaque_data_value}, - { NFAPI_NB_IOT_BROADCAST_DETECT_REQUEST_TAG, &pNfapiMsg->nb_iot_broadcast_detect_request, &unpack_nb_iot_broadcast_detect_request_value} - }; - - return (pull8(ppReadPackedMsg, &pNfapiMsg->rat_type, end) && - unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); -} - -static uint8_t unpack_broadcast_detect_response(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t* config) -{ - nfapi_broadcast_detect_response_t *pNfapiMsg = (nfapi_broadcast_detect_response_t*)msg; +static uint8_t pack_broadcast_detect_response(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t *config) { + nfapi_broadcast_detect_response_t *pNfapiMsg = (nfapi_broadcast_detect_response_t *)msg; + return (push32(pNfapiMsg->error_code, ppWritePackedMsg, end) && + pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); +} + +static uint8_t pack_lte_broadcast_detect_indication_value(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_lte_broadcast_detect_indication_t *value = (nfapi_lte_broadcast_detect_indication_t *)msg; + return (push8(value->number_of_tx_antenna, ppWritePackedMsg, end) && + push16(value->mib_length, ppWritePackedMsg, end) && + pusharray8(value->mib, NFAPI_MAX_MIB_LENGTH, value->mib_length, ppWritePackedMsg, end) && + push32(value->sfn_offset, ppWritePackedMsg, end)); +} - unpack_tlv_t unpack_fns[] = - { - }; +static uint8_t pack_utran_broadcast_detect_indication_value(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_utran_broadcast_detect_indication_t *value = (nfapi_utran_broadcast_detect_indication_t *)msg; + return (push16(value->mib_length, ppWritePackedMsg, end) && + pusharray8(value->mib, NFAPI_MAX_MIB_LENGTH, value->mib_length, ppWritePackedMsg, end) && + push32(value->sfn_offset, ppWritePackedMsg, end)); +} - return (pull32(ppReadPackedMsg, &pNfapiMsg->error_code, end) && - unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); +static uint8_t pack_nb_iot_broadcast_detect_indication_value(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_nb_iot_broadcast_detect_indication_t *value = (nfapi_nb_iot_broadcast_detect_indication_t *)msg; + return (push8(value->number_of_tx_antenna, ppWritePackedMsg, end) && + push16(value->mib_length, ppWritePackedMsg, end) && + pusharray8(value->mib, NFAPI_MAX_MIB_LENGTH, value->mib_length, ppWritePackedMsg, end) && + push32(value->sfn_offset, ppWritePackedMsg, end)); } -static uint8_t unpack_lte_broadcast_detect_indication_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_lte_broadcast_detect_indication_t* value = (nfapi_lte_broadcast_detect_indication_t*)tlv; +static uint8_t pack_broadcast_detect_indication(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t *config) { + nfapi_broadcast_detect_indication_t *pNfapiMsg = (nfapi_broadcast_detect_indication_t *)msg; + return (push32(pNfapiMsg->error_code, ppWritePackedMsg, end) && + pack_tlv(NFAPI_LTE_BROADCAST_DETECT_INDICATION_TAG, &pNfapiMsg->lte_broadcast_detect_indication, ppWritePackedMsg, end, &pack_lte_broadcast_detect_indication_value) && + pack_tlv(NFAPI_UTRAN_BROADCAST_DETECT_INDICATION_TAG, &pNfapiMsg->utran_broadcast_detect_indication, ppWritePackedMsg, end, &pack_utran_broadcast_detect_indication_value) && + pack_tlv(NFAPI_PNF_CELL_BROADCAST_STATE_TAG, &pNfapiMsg->pnf_cell_broadcast_state, ppWritePackedMsg, end, &pack_opaque_data_value) && + pack_tlv(NFAPI_NB_IOT_BROADCAST_DETECT_INDICATION_TAG, &pNfapiMsg->nb_iot_broadcast_detect_indication, ppWritePackedMsg, end, &pack_nb_iot_broadcast_detect_indication_value) && + pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); +} - if(!(pull8(ppReadPackedMsg, &value->number_of_tx_antenna, end) && - pull16(ppReadPackedMsg, &value->mib_length, end))) - return 0; +static uint8_t pack_lte_system_information_schedule_request_value(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_lte_system_information_schedule_request_t *value = (nfapi_lte_system_information_schedule_request_t *)msg; + return (push16(value->earfcn, ppWritePackedMsg, end) && + push16(value->pci, ppWritePackedMsg, end) && + push16(value->downlink_channel_bandwidth, ppWritePackedMsg, end) && + push8(value->phich_configuration, ppWritePackedMsg, end) && + push8(value->number_of_tx_antenna, ppWritePackedMsg, end) && + push8(value->retry_count, ppWritePackedMsg, end) && + push32(value->timeout, ppWritePackedMsg, end)); +} - if(value->mib_length > NFAPI_MAX_MIB_LENGTH) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "MIB too long %d \n", value->mib_length); - return 0; - } - - return (pullarray8(ppReadPackedMsg, value->mib, NFAPI_MAX_MIB_LENGTH, value->mib_length, end) && - pull32(ppReadPackedMsg, &value->sfn_offset, end)); +static uint8_t pack_nb_iot_system_information_schedule_request_value(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_nb_iot_system_information_schedule_request_t *value = (nfapi_nb_iot_system_information_schedule_request_t *)msg; + return (push16(value->earfcn, ppWritePackedMsg, end) && + push8(value->ro_dl, ppWritePackedMsg, end) && + push16(value->pci, ppWritePackedMsg, end) && + push8(value->scheduling_info_sib1_nb, ppWritePackedMsg, end) && + push32(value->timeout, ppWritePackedMsg, end)); } -static uint8_t unpack_utran_broadcast_detect_indication_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_utran_broadcast_detect_indication_t* value = (nfapi_utran_broadcast_detect_indication_t*)tlv; - if(pull16(ppReadPackedMsg, &value->mib_length, end) == 0) - return 0; +static uint8_t pack_system_information_schedule_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t *config) { + nfapi_system_information_schedule_request_t *pNfapiMsg = (nfapi_system_information_schedule_request_t *)msg; + + if(push8(pNfapiMsg->rat_type, ppWritePackedMsg, end) == 0) + return 0; + + switch(pNfapiMsg->rat_type) { + case NFAPI_RAT_TYPE_LTE: + if(pack_tlv(NFAPI_LTE_SYSTEM_INFORMATION_SCHEDULE_REQUEST_TAG, &pNfapiMsg->lte_system_information_schedule_request, ppWritePackedMsg, end, &pack_lte_system_information_schedule_request_value) == 0) + return 0; + + break; - if(value->mib_length > NFAPI_MAX_MIB_LENGTH) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "MIB too long %d \n", value->mib_length); - return 0; - } + case NFAPI_RAT_TYPE_NB_IOT: + if(pack_tlv(NFAPI_NB_IOT_SYSTEM_INFORMATION_SCHEDULE_REQUEST_TAG, &pNfapiMsg->nb_iot_system_information_schedule_request, ppWritePackedMsg, end, + &pack_nb_iot_system_information_schedule_request_value) == 0) + return 0; - return (pullarray8(ppReadPackedMsg, value->mib, NFAPI_MAX_MIB_LENGTH, value->mib_length, end) && - pull32(ppReadPackedMsg, &value->sfn_offset, end)); + break; + } + + return (pack_tlv(NFAPI_PNF_CELL_BROADCAST_STATE_TAG, &pNfapiMsg->pnf_cell_broadcast_state, ppWritePackedMsg, end, &pack_opaque_data_value) && + pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); } -static uint8_t unpack_nb_iot_broadcast_detect_indication_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_nb_iot_broadcast_detect_indication_t* value = (nfapi_nb_iot_broadcast_detect_indication_t*)tlv; +static uint8_t pack_system_information_schedule_response(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t *config) { + nfapi_system_information_schedule_response_t *pNfapiMsg = (nfapi_system_information_schedule_response_t *)msg; + return (push32(pNfapiMsg->error_code, ppWritePackedMsg, end) && + pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); +} - if(!(pull8(ppReadPackedMsg, &value->number_of_tx_antenna, end) && - pull16(ppReadPackedMsg, &value->mib_length, end))) - return 0; +static uint8_t pack_lte_system_information_indication_value(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_lte_system_information_indication_t *value = (nfapi_lte_system_information_indication_t *)msg; + return (push8(value->sib_type, ppWritePackedMsg, end) && + push16(value->sib_length, ppWritePackedMsg, end) && + pusharray8(value->sib, NFAPI_MAX_SIB_LENGTH, value->sib_length, ppWritePackedMsg, end)); +} - if(value->mib_length > NFAPI_MAX_MIB_LENGTH) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "MIB too long %d \n", value->mib_length); - return 0; - } +static uint8_t pack_nb_iot_system_information_indication_value(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_nb_iot_system_information_indication_t *value = (nfapi_nb_iot_system_information_indication_t *)msg; + return (push8(value->sib_type, ppWritePackedMsg, end) && + push16(value->sib_length, ppWritePackedMsg, end) && + pusharray8(value->sib, NFAPI_MAX_SIB_LENGTH, value->sib_length, ppWritePackedMsg, end)); +} - return (pullarray8(ppReadPackedMsg, value->mib, NFAPI_MAX_MIB_LENGTH, value->mib_length, end) && - pull32(ppReadPackedMsg, &value->sfn_offset, end)); +static uint8_t pack_system_information_schedule_indication(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t *config) { + nfapi_system_information_schedule_indication_t *pNfapiMsg = (nfapi_system_information_schedule_indication_t *)msg; + return (push32(pNfapiMsg->error_code, ppWritePackedMsg, end) && + pack_tlv(NFAPI_LTE_SYSTEM_INFORMATION_INDICATION_TAG, &pNfapiMsg->lte_system_information_indication, ppWritePackedMsg, end, &pack_lte_system_information_indication_value) && + pack_tlv(NFAPI_NB_IOT_SYSTEM_INFORMATION_INDICATION_TAG, &pNfapiMsg->nb_iot_system_information_indication, ppWritePackedMsg, end, &pack_nb_iot_system_information_indication_value) && + pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); } -static uint8_t unpack_broadcast_detect_indication(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t* config) -{ - nfapi_broadcast_detect_indication_t *pNfapiMsg = (nfapi_broadcast_detect_indication_t*)msg; +static uint8_t pack_lte_system_information_request_value(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_lte_system_information_request_t *value = (nfapi_lte_system_information_request_t *)msg; + uint16_t idx = 0; + + if(!(push16(value->earfcn, ppWritePackedMsg, end) && + push16(value->pci, ppWritePackedMsg, end) && + push16(value->downlink_channel_bandwidth, ppWritePackedMsg, end) && + push8(value->phich_configuration, ppWritePackedMsg, end) && + push8(value->number_of_tx_antenna, ppWritePackedMsg, end) && + push8(value->number_of_si_periodicity, ppWritePackedMsg, end))) + return 0; - unpack_tlv_t unpack_fns[] = - { - { NFAPI_LTE_BROADCAST_DETECT_INDICATION_TAG, &pNfapiMsg->lte_broadcast_detect_indication, &unpack_lte_broadcast_detect_indication_value}, - { NFAPI_UTRAN_BROADCAST_DETECT_INDICATION_TAG, &pNfapiMsg->utran_broadcast_detect_indication, &unpack_utran_broadcast_detect_indication_value}, - { NFAPI_NB_IOT_BROADCAST_DETECT_INDICATION_TAG, &pNfapiMsg->nb_iot_broadcast_detect_indication, &unpack_nb_iot_broadcast_detect_indication_value}, - { NFAPI_PNF_CELL_BROADCAST_STATE_TAG, &pNfapiMsg->pnf_cell_broadcast_state, &unpack_opaque_data_value} - }; + for(idx = 0; idx < value->number_of_si_periodicity; ++idx) { + if(!(push8(value->si_periodicity[idx].si_periodicity, ppWritePackedMsg, end) && + push8(value->si_periodicity[idx].si_index, ppWritePackedMsg, end))) + return 0; + } - return (pull32(ppReadPackedMsg, &pNfapiMsg->error_code, end) && - unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); + return (push8(value->si_window_length, ppWritePackedMsg, end) && + push32(value->timeout, ppWritePackedMsg, end)); } +static uint8_t pack_utran_system_information_request_value(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_utran_system_information_request_t *value = (nfapi_utran_system_information_request_t *)msg; + return (push16(value->uarfcn, ppWritePackedMsg, end) && + push16(value->psc, ppWritePackedMsg, end) && + push32(value->timeout, ppWritePackedMsg, end)); +} +static uint8_t pack_geran_system_information_request_value(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_geran_system_information_request_t *value = (nfapi_geran_system_information_request_t *)msg; + return (push16(value->arfcn, ppWritePackedMsg, end) && + push8(value->bsic, ppWritePackedMsg, end) && + push32(value->timeout, ppWritePackedMsg, end)); +} +static uint8_t pack_nb_iot_system_information_request_value(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_nb_iot_system_information_request_t *value = (nfapi_nb_iot_system_information_request_t *)msg; + uint16_t idx = 0; + + if(!(push16(value->earfcn, ppWritePackedMsg, end) && + push8(value->ro_dl, ppWritePackedMsg, end) && + push16(value->pci, ppWritePackedMsg, end) && + push8(value->number_of_si_periodicity, ppWritePackedMsg, end))) + return 0; -static uint8_t unpack_lte_system_information_schedule_request_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_lte_system_information_schedule_request_t* value = (nfapi_lte_system_information_schedule_request_t*)tlv; + for(idx = 0; idx < value->number_of_si_periodicity; ++idx) { + if(!(push8(value->si_periodicity[idx].si_periodicity, ppWritePackedMsg, end) && + push8(value->si_periodicity[idx].si_repetition_pattern, ppWritePackedMsg, end) && + push8(value->si_periodicity[idx].si_tb_size, ppWritePackedMsg, end) && + push8(value->si_periodicity[idx].number_of_si_index, ppWritePackedMsg, end))) + return 0; - return (pull16(ppReadPackedMsg, &value->earfcn, end) && - pull16(ppReadPackedMsg, &value->pci, end) && - pull16(ppReadPackedMsg, &value->downlink_channel_bandwidth, end) && - pull8(ppReadPackedMsg, &value->phich_configuration, end) && - pull8(ppReadPackedMsg, &value->number_of_tx_antenna, end) && - pull8(ppReadPackedMsg, &value->retry_count, end) && - pull32(ppReadPackedMsg, &value->timeout, end)); + uint8_t si_idx; + + for(si_idx = 0; si_idx < value->si_periodicity[idx].number_of_si_index; ++si_idx) { + if(!(push8(value->si_periodicity[idx].si_index[si_idx], ppWritePackedMsg, end))) + return 0; + } + } + + return (push8(value->si_window_length, ppWritePackedMsg, end) && + push32(value->timeout, ppWritePackedMsg, end)); } -static uint8_t unpack_nb_iot_system_information_schedule_request_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_nb_iot_system_information_schedule_request_t* value = (nfapi_nb_iot_system_information_schedule_request_t*)tlv; - return (pull16(ppReadPackedMsg, &value->earfcn, end) && - pull8(ppReadPackedMsg, &value->ro_dl, end) && - pull16(ppReadPackedMsg, &value->pci, end) && - pull8(ppReadPackedMsg, &value->scheduling_info_sib1_nb, end) && - pull32(ppReadPackedMsg, &value->timeout, end)); +static uint8_t pack_system_information_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t *config) { + nfapi_system_information_request_t *pNfapiMsg = (nfapi_system_information_request_t *)msg; + + if(push8(pNfapiMsg->rat_type, ppWritePackedMsg, end) == 0) + return 0; + + switch(pNfapiMsg->rat_type) { + case NFAPI_RAT_TYPE_LTE: + if(pack_tlv(NFAPI_LTE_SYSTEM_INFORMATION_REQUEST_TAG, &pNfapiMsg->lte_system_information_request, ppWritePackedMsg, end, &pack_lte_system_information_request_value) == 0) + return 0; + + break; + + case NFAPI_RAT_TYPE_UTRAN: + if(pack_tlv(NFAPI_UTRAN_SYSTEM_INFORMATION_REQUEST_TAG, &pNfapiMsg->utran_system_information_request, ppWritePackedMsg, end, &pack_utran_system_information_request_value) == 0) + return 0; + + break; + + case NFAPI_RAT_TYPE_GERAN: + if(pack_tlv(NFAPI_GERAN_SYSTEM_INFORMATION_REQUEST_TAG, &pNfapiMsg->geran_system_information_request, ppWritePackedMsg, end, &pack_geran_system_information_request_value) == 0) + return 0; + + break; + + case NFAPI_RAT_TYPE_NB_IOT: + if(pack_tlv(NFAPI_NB_IOT_SYSTEM_INFORMATION_REQUEST_TAG, &pNfapiMsg->nb_iot_system_information_request, ppWritePackedMsg, end, &pack_nb_iot_system_information_request_value) == 0) + return 0; + + break; + } + + return (pack_tlv(NFAPI_PNF_CELL_BROADCAST_STATE_TAG, &pNfapiMsg->pnf_cell_broadcast_state, ppWritePackedMsg, end, &pack_opaque_data_value) && + pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); } -static uint8_t unpack_system_information_schedule_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t* config) -{ - nfapi_system_information_schedule_request_t *pNfapiMsg = (nfapi_system_information_schedule_request_t*)msg; +static uint8_t pack_system_information_response(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t *config) { + nfapi_system_information_response_t *pNfapiMsg = (nfapi_system_information_response_t *)msg; + return (push32(pNfapiMsg->error_code, ppWritePackedMsg, end) && + pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); +} - unpack_tlv_t unpack_fns[] = - { - { NFAPI_LTE_SYSTEM_INFORMATION_SCHEDULE_REQUEST_TAG, &pNfapiMsg->lte_system_information_schedule_request, &unpack_lte_system_information_schedule_request_value}, - { NFAPI_NB_IOT_SYSTEM_INFORMATION_SCHEDULE_REQUEST_TAG, &pNfapiMsg->nb_iot_system_information_schedule_request, &unpack_nb_iot_system_information_schedule_request_value}, - { NFAPI_PNF_CELL_BROADCAST_STATE_TAG, &pNfapiMsg->pnf_cell_broadcast_state, &unpack_opaque_data_value} - }; +static uint8_t pack_utran_system_information_indication_value(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_utran_system_information_indication_t *value = (nfapi_utran_system_information_indication_t *)msg; + return (push16(value->sib_length, ppWritePackedMsg, end) && + pusharray8(value->sib, NFAPI_MAX_SIB_LENGTH, value->sib_length, ppWritePackedMsg, end)); +} - return (pull8(ppReadPackedMsg, &pNfapiMsg->rat_type, end) && - unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); +static uint8_t pack_geran_system_information_indication_value(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_geran_system_information_indication_t *value = (nfapi_geran_system_information_indication_t *)msg; + return (push16(value->si_length, ppWritePackedMsg, end) && + pusharray8(value->si, NFAPI_MAX_SIB_LENGTH, value->si_length, ppWritePackedMsg, end)); } -static uint8_t unpack_system_information_schedule_response(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t* config) -{ - nfapi_system_information_schedule_response_t *pNfapiMsg = (nfapi_system_information_schedule_response_t*)msg; +static uint8_t pack_system_information_indication(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t *config) { + nfapi_system_information_indication_t *pNfapiMsg = (nfapi_system_information_indication_t *)msg; + return (push32(pNfapiMsg->error_code, ppWritePackedMsg, end) && + pack_tlv(NFAPI_LTE_SYSTEM_INFORMATION_INDICATION_TAG, &pNfapiMsg->lte_system_information_indication, ppWritePackedMsg, end, &pack_lte_system_information_indication_value) && + pack_tlv(NFAPI_UTRAN_SYSTEM_INFORMATION_INDICATION_TAG, &pNfapiMsg->utran_system_information_indication, ppWritePackedMsg, end, &pack_utran_system_information_indication_value) && + pack_tlv(NFAPI_GERAN_SYSTEM_INFORMATION_INDICATION_TAG, &pNfapiMsg->geran_system_information_indication, ppWritePackedMsg, end, &pack_geran_system_information_indication_value) && + pack_tlv(NFAPI_NB_IOT_SYSTEM_INFORMATION_INDICATION_TAG, &pNfapiMsg->nb_iot_system_information_indication, ppWritePackedMsg, end, &pack_nb_iot_system_information_indication_value) && + pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); +} - unpack_tlv_t unpack_fns[] = - { - }; +static uint8_t pack_nmm_stop_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t *config) { + nfapi_nmm_stop_request_t *pNfapiMsg = (nfapi_nmm_stop_request_t *)msg; + return (pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); +} - return (pull32(ppReadPackedMsg, &pNfapiMsg->error_code, end) && - unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); +static uint8_t pack_nmm_stop_response(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t *config) { + nfapi_nmm_stop_response_t *pNfapiMsg = (nfapi_nmm_stop_response_t *)msg; + return (push32(pNfapiMsg->error_code, ppWritePackedMsg, end) && + pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); } -static uint8_t unpack_lte_system_information_indication_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_lte_system_information_indication_t* value = (nfapi_lte_system_information_indication_t*)tlv; +static uint8_t unpack_lte_rssi_request_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + //int result = 0; + nfapi_lte_rssi_request_t *value = (nfapi_lte_rssi_request_t *)tlv; - if(!(pull8(ppReadPackedMsg, &value->sib_type, end) && - pull16(ppReadPackedMsg, &value->sib_length, end))) - return 0; + if(!(pull8(ppReadPackedMsg, &value->frequency_band_indicator, end) && + pull16(ppReadPackedMsg, &value->measurement_period, end) && + pull8(ppReadPackedMsg, &value->bandwidth, end) && + pull32(ppReadPackedMsg, &value->timeout, end) && + pull8(ppReadPackedMsg, &value->number_of_earfcns, end))) + return 0; - if(value->sib_length > NFAPI_MAX_SIB_LENGTH) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "SIB too long %d \n", value->sib_length); - return 0; - } - - if(pullarray8(ppReadPackedMsg, value->sib, NFAPI_MAX_SIB_LENGTH, value->sib_length, end) == 0) - return 0; + if(value->number_of_earfcns <= NFAPI_MAX_CARRIER_LIST) { + if(pullarray16(ppReadPackedMsg, value->earfcn, NFAPI_MAX_CARRIER_LIST, value->number_of_earfcns, end) == 0) + return 0; + } else { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "More EARFCN's than we can decode %d \n", value->number_of_earfcns); + return 0; + } - return 1; + return 1; } -static uint8_t unpack_nb_iot_system_information_indication_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_nb_iot_system_information_indication_t* value = (nfapi_nb_iot_system_information_indication_t*)tlv; +static uint8_t unpack_utran_rssi_request_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_utran_rssi_request_t *value = (nfapi_utran_rssi_request_t *)tlv; + + if(!(pull8(ppReadPackedMsg, &value->frequency_band_indicator, end) && + pull16(ppReadPackedMsg, &value->measurement_period, end) && + pull32(ppReadPackedMsg, &value->timeout, end) && + pull8(ppReadPackedMsg, &value->number_of_uarfcns, end))) + return 0; + + if(value->number_of_uarfcns <= NFAPI_MAX_CARRIER_LIST) { + if(pullarray16(ppReadPackedMsg, value->uarfcn, NFAPI_MAX_CARRIER_LIST, value->number_of_uarfcns, end) == 0) + return 0; + } else { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "More UARFCN's than we can decode %d \n", value->number_of_uarfcns); + return 0; + } - if(!(pull8(ppReadPackedMsg, &value->sib_type, end) && - pull16(ppReadPackedMsg, &value->sib_length, end))) - return 0; + return 1; +} - if(value->sib_length > NFAPI_MAX_SIB_LENGTH) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "SIB too long %d \n", value->sib_length); - return 0; - } - - if(pullarray8(ppReadPackedMsg, value->sib, NFAPI_MAX_SIB_LENGTH, value->sib_length, end) == 0) - return 0; - - return 1; -} - -static uint8_t unpack_system_information_schedule_indication(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t* config) -{ - nfapi_system_information_schedule_indication_t *pNfapiMsg = (nfapi_system_information_schedule_indication_t*)msg; - - unpack_tlv_t unpack_fns[] = - { - { NFAPI_LTE_SYSTEM_INFORMATION_INDICATION_TAG, &pNfapiMsg->lte_system_information_indication, &unpack_lte_system_information_indication_value}, - { NFAPI_NB_IOT_SYSTEM_INFORMATION_INDICATION_TAG, &pNfapiMsg->nb_iot_system_information_indication, &unpack_nb_iot_system_information_indication_value}, - }; - - return (pull32(ppReadPackedMsg, &pNfapiMsg->error_code, end) && - unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); -} - -static uint8_t unpack_lte_system_information_request_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_lte_system_information_request_t* value = (nfapi_lte_system_information_request_t*)tlv; - uint16_t idx = 0; - - if(!(pull16(ppReadPackedMsg, &value->earfcn, end) && - pull16(ppReadPackedMsg, &value->pci, end) && - pull16(ppReadPackedMsg, &value->downlink_channel_bandwidth, end) && - pull8(ppReadPackedMsg, &value->phich_configuration, end) && - pull8(ppReadPackedMsg, &value->number_of_tx_antenna, end) && - pull8(ppReadPackedMsg, &value->number_of_si_periodicity, end))) - return 0; - - if(value->number_of_si_periodicity > NFAPI_MAX_SI_PERIODICITY) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "More found SI periodicity than we can decode %d \n", value->number_of_si_periodicity); - return 0; - } - - for(idx = 0; idx < value->number_of_si_periodicity; ++idx) - { - if(!(pull8(ppReadPackedMsg, &value->si_periodicity[idx].si_periodicity, end) && - pull8(ppReadPackedMsg, &value->si_periodicity[idx].si_index, end))) - return 0; - } - - if(!(pull8(ppReadPackedMsg, &value->si_window_length, end) && - pull32(ppReadPackedMsg, &value->timeout, end))) - return 0; - - return 1; -} - -static uint8_t unpack_utran_system_information_request_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_utran_system_information_request_t* value = (nfapi_utran_system_information_request_t*)tlv; - - return (pull16(ppReadPackedMsg, &value->uarfcn, end) && - pull16(ppReadPackedMsg, &value->psc, end) && - pull32(ppReadPackedMsg, &value->timeout, end)); -} - -static uint8_t unpack_geran_system_information_request_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_geran_system_information_request_t* value = (nfapi_geran_system_information_request_t*)tlv; - - return (pull16(ppReadPackedMsg, &value->arfcn, end) && - pull8(ppReadPackedMsg, &value->bsic, end) && - pull32(ppReadPackedMsg, &value->timeout, end)); -} - -static uint8_t unpack_nb_iot_system_information_request_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_nb_iot_system_information_request_t* value = (nfapi_nb_iot_system_information_request_t*)tlv; - uint16_t idx = 0; - - if(!(pull16(ppReadPackedMsg, &value->earfcn, end) && - pull8(ppReadPackedMsg, &value->ro_dl, end) && - pull16(ppReadPackedMsg, &value->pci, end) && - pull8(ppReadPackedMsg, &value->number_of_si_periodicity, end))) - return 0; - - if(value->number_of_si_periodicity > NFAPI_MAX_SI_PERIODICITY) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "More found SI periodicity than we can decode %d \n", value->number_of_si_periodicity); - return 0; - } - - for(idx = 0; idx < value->number_of_si_periodicity; ++idx) - { - if(!(pull8(ppReadPackedMsg, &value->si_periodicity[idx].si_periodicity, end) && - pull8(ppReadPackedMsg, &value->si_periodicity[idx].si_repetition_pattern, end) && - pull8(ppReadPackedMsg, &value->si_periodicity[idx].si_tb_size, end) && - pull8(ppReadPackedMsg, &value->si_periodicity[idx].number_of_si_index, end))) - return 0; - - uint8_t si_idx; - for(si_idx = 0; si_idx < value->si_periodicity[idx].number_of_si_index; ++si_idx) - { - if(!(pull8(ppReadPackedMsg, &value->si_periodicity[idx].si_index[si_idx], end))) - return 0; - - } - } - - if(!(pull8(ppReadPackedMsg, &value->si_window_length, end) && - pull32(ppReadPackedMsg, &value->timeout, end))) - return 0; +static uint8_t unpack_geran_rssi_request_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_geran_rssi_request_t *value = (nfapi_geran_rssi_request_t *)tlv; + uint16_t idx = 0; + + if(!(pull8(ppReadPackedMsg, &value->frequency_band_indicator, end) && + pull16(ppReadPackedMsg, &value->measurement_period, end) && + pull32(ppReadPackedMsg, &value->timeout, end) && + pull8(ppReadPackedMsg, &value->number_of_arfcns, end))) + return 0; + + if(value->number_of_arfcns <= NFAPI_MAX_CARRIER_LIST) { + for(idx = 0; idx < value->number_of_arfcns; ++idx) { + if(!(pull16(ppReadPackedMsg, &value->arfcn[idx].arfcn, end) && + pull8(ppReadPackedMsg, &value->arfcn[idx].direction, end))) + return 0; + } + } else { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "More ARFCN's than we can decode %d \n", value->number_of_arfcns); + return 0; + } + + return 1; +} + +static uint8_t unpack_nb_iot_rssi_request_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_nb_iot_rssi_request_t *value = (nfapi_nb_iot_rssi_request_t *)tlv; + uint16_t idx = 0; + + if(!(pull8(ppReadPackedMsg, &value->frequency_band_indicator, end) && + pull16(ppReadPackedMsg, &value->measurement_period, end) && + pull32(ppReadPackedMsg, &value->timeout, end) && + pull8(ppReadPackedMsg, &value->number_of_earfcns, end))) + return 0; + + if(value->number_of_earfcns <= NFAPI_MAX_CARRIER_LIST) { + for(idx = 0; idx < value->number_of_earfcns; ++idx) { + if(!(pull16(ppReadPackedMsg, &value->earfcn[idx].earfcn, end) && + pull8(ppReadPackedMsg, &value->earfcn[idx].number_of_ro_dl, end))) + return 0; + + if(value->earfcn[idx].number_of_ro_dl <= NFAPI_MAX_RO_DL) { + uint8_t ro_dl_idx = 0; + + for(ro_dl_idx = 0; ro_dl_idx < value->earfcn[idx].number_of_ro_dl; ++ro_dl_idx) { + if(!pull8(ppReadPackedMsg, &value->earfcn[idx].ro_dl[ro_dl_idx], end)) + return 0; + } + } else { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "More ROdl's than we can decode %d \n", value->earfcn[idx].number_of_ro_dl); + return 0; + } + } + } else { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "More EARFCN's than we can decode %d \n", value->number_of_earfcns); + return 0; + } + + return 1; +} + +static uint8_t unpack_rssi_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t *config) { + nfapi_rssi_request_t *pNfapiMsg = (nfapi_rssi_request_t *)msg; + unpack_tlv_t unpack_fns[] = { + { NFAPI_LTE_RSSI_REQUEST_TAG, &pNfapiMsg->lte_rssi_request, &unpack_lte_rssi_request_value}, + { NFAPI_UTRAN_RSSI_REQUEST_TAG, &pNfapiMsg->utran_rssi_request, &unpack_utran_rssi_request_value}, + { NFAPI_GERAN_RSSI_REQUEST_TAG, &pNfapiMsg->geran_rssi_request, &unpack_geran_rssi_request_value}, + { NFAPI_NB_IOT_RSSI_REQUEST_TAG, &pNfapiMsg->nb_iot_rssi_request, &unpack_nb_iot_rssi_request_value}, + }; + int result = 0; + result = (pull8(ppReadPackedMsg, &pNfapiMsg->rat_type, end) && + unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &(pNfapiMsg->vendor_extension))); + + // Verify that the rat type and the tlv match + if(result == 1 && + !((pNfapiMsg->rat_type == NFAPI_RAT_TYPE_LTE && pNfapiMsg->lte_rssi_request.tl.tag == NFAPI_LTE_RSSI_REQUEST_TAG) || + (pNfapiMsg->rat_type == NFAPI_RAT_TYPE_UTRAN && pNfapiMsg->utran_rssi_request.tl.tag == NFAPI_UTRAN_RSSI_REQUEST_TAG) || + (pNfapiMsg->rat_type == NFAPI_RAT_TYPE_GERAN && pNfapiMsg->geran_rssi_request.tl.tag == NFAPI_GERAN_RSSI_REQUEST_TAG) || + (pNfapiMsg->rat_type == NFAPI_RAT_TYPE_NB_IOT && pNfapiMsg->nb_iot_rssi_request.tl.tag == NFAPI_NB_IOT_RSSI_REQUEST_TAG))) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "Mismatch RAT Type: %d and TAG value: 0x%04x \n", pNfapiMsg->rat_type, pNfapiMsg->lte_rssi_request.tl.tag); + result = 0; + } + + return result; +} + +static uint8_t unpack_rssi_response(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t *config) { + nfapi_rssi_response_t *pNfapiMsg = (nfapi_rssi_response_t *)msg; + return (pull32(ppReadPackedMsg, &pNfapiMsg->error_code, end) && + unpack_tlv_list(NULL, 0, ppReadPackedMsg, end, config, &(pNfapiMsg->vendor_extension))); +} + +static uint8_t unpack_rssi_indication_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_rssi_indication_body_t *value = (nfapi_rssi_indication_body_t *)tlv; + + if(pull16(ppReadPackedMsg, &value->number_of_rssi, end) == 0) + return 0; + + if(value->number_of_rssi <= NFAPI_MAX_RSSI) { + if(pullarrays16(ppReadPackedMsg, value->rssi, NFAPI_MAX_RSSI, value->number_of_rssi, end) == 0) + return 0; + } else { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "More RSSI's than we can decode %d \n", value->number_of_rssi); + return 0; + } + + return 1; +} + +static uint8_t unpack_rssi_indication(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t *config) { + nfapi_rssi_indication_t *pNfapiMsg = (nfapi_rssi_indication_t *)msg; + unpack_tlv_t unpack_fns[] = { + { NFAPI_RSSI_INDICATION_TAG, &pNfapiMsg->rssi_indication_body, &unpack_rssi_indication_value}, + }; + return (pull32(ppReadPackedMsg, &pNfapiMsg->error_code, end) && + unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); +} + +static uint8_t unpack_lte_cell_search_request_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_lte_cell_search_request_t *value = (nfapi_lte_cell_search_request_t *)tlv; + + if(!(pull16(ppReadPackedMsg, &value->earfcn, end) && + pull8(ppReadPackedMsg, &value->measurement_bandwidth, end) && + pull8(ppReadPackedMsg, &value->exhaustive_search, end) && + pull32(ppReadPackedMsg, &value->timeout, end) && + pull8(ppReadPackedMsg, &value->number_of_pci, end))) + return 0; + + if(value->number_of_pci <= NFAPI_MAX_PCI_LIST) { + if(pullarray16(ppReadPackedMsg, value->pci, NFAPI_MAX_PCI_LIST, value->number_of_pci, end) == 0) + return 0; + } else { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "More PCI's than we can decode %d \n", value->number_of_pci); + return 0; + } + + return 1; +} + +static uint8_t unpack_utran_cell_search_request_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_utran_cell_search_request_t *value = (nfapi_utran_cell_search_request_t *)tlv; + + if(!(pull16(ppReadPackedMsg, &value->uarfcn, end) && + pull8(ppReadPackedMsg, &value->exhaustive_search, end) && + pull32(ppReadPackedMsg, &value->timeout, end) && + pull8(ppReadPackedMsg, &value->number_of_psc, end))) + return 0; + + if(value->number_of_psc <= NFAPI_MAX_PSC_LIST) { + if(pullarray16(ppReadPackedMsg, value->psc, NFAPI_MAX_PSC_LIST, value->number_of_psc, end) == 0) + return 0; + } else { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "More PSC's than we can decode %d \n", value->number_of_psc); + return 0; + } + + return 1; +} + +static uint8_t unpack_geran_cell_search_request_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_geran_cell_search_request_t *value = (nfapi_geran_cell_search_request_t *)tlv; + + if(!(pull32(ppReadPackedMsg, &value->timeout, end) && + pull8(ppReadPackedMsg, &value->number_of_arfcn, end))) + return 0; + + if(value->number_of_arfcn <= NFAPI_MAX_ARFCN_LIST) { + if(pullarray16(ppReadPackedMsg, value->arfcn, NFAPI_MAX_ARFCN_LIST, value->number_of_arfcn, end) == 0) + return 0; + } else { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "More ARFCN's than we can decode %d \n", value->number_of_arfcn); + return 0; + } + + return 1; +} + +static uint8_t unpack_nb_iot_cell_search_request_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_nb_iot_cell_search_request_t *value = (nfapi_nb_iot_cell_search_request_t *)tlv; + + if(!(pull16(ppReadPackedMsg, &value->earfcn, end) && + pull8(ppReadPackedMsg, &value->ro_dl, end) && + pull8(ppReadPackedMsg, &value->exhaustive_search, end) && + pull32(ppReadPackedMsg, &value->timeout, end) && + pull8(ppReadPackedMsg, &value->number_of_pci, end))) + return 0; + + if(value->number_of_pci <= NFAPI_MAX_PCI_LIST) { + if(pullarray16(ppReadPackedMsg, value->pci, NFAPI_MAX_PCI_LIST, value->number_of_pci, end) == 0) + return 0; + } else { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "More PCI's than we can decode %d \n", value->number_of_pci); + return 0; + } + + return 1; +} + +static uint8_t unpack_cell_search_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t *config) { + nfapi_cell_search_request_t *pNfapiMsg = (nfapi_cell_search_request_t *)msg; + unpack_tlv_t unpack_fns[] = { + { NFAPI_LTE_CELL_SEARCH_REQUEST_TAG, &pNfapiMsg->lte_cell_search_request, &unpack_lte_cell_search_request_value}, + { NFAPI_UTRAN_CELL_SEARCH_REQUEST_TAG, &pNfapiMsg->utran_cell_search_request, &unpack_utran_cell_search_request_value}, + { NFAPI_GERAN_CELL_SEARCH_REQUEST_TAG, &pNfapiMsg->geran_cell_search_request, &unpack_geran_cell_search_request_value}, + { NFAPI_NB_IOT_CELL_SEARCH_REQUEST_TAG, &pNfapiMsg->nb_iot_cell_search_request, &unpack_nb_iot_cell_search_request_value}, + }; + int result = (pull8(ppReadPackedMsg, &pNfapiMsg->rat_type, end) && + unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); + + // Verify that the rat type and the tlv match + if(result == 1 && + !((pNfapiMsg->rat_type == NFAPI_RAT_TYPE_LTE && pNfapiMsg->lte_cell_search_request.tl.tag == NFAPI_LTE_CELL_SEARCH_REQUEST_TAG) || + (pNfapiMsg->rat_type == NFAPI_RAT_TYPE_UTRAN && pNfapiMsg->utran_cell_search_request.tl.tag == NFAPI_UTRAN_CELL_SEARCH_REQUEST_TAG) || + (pNfapiMsg->rat_type == NFAPI_RAT_TYPE_GERAN && pNfapiMsg->geran_cell_search_request.tl.tag == NFAPI_GERAN_CELL_SEARCH_REQUEST_TAG) || + (pNfapiMsg->rat_type == NFAPI_RAT_TYPE_NB_IOT && pNfapiMsg->nb_iot_cell_search_request.tl.tag == NFAPI_NB_IOT_CELL_SEARCH_REQUEST_TAG))) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "Mismatch RAT Type: %d and TAG value: 0x%04x \n", pNfapiMsg->rat_type, pNfapiMsg->lte_cell_search_request.tl.tag); + result = 0; + } + + return result; +} + +static uint8_t unpack_cell_search_response(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t *config) { + nfapi_cell_search_response_t *pNfapiMsg = (nfapi_cell_search_response_t *)msg; + return (pull32(ppReadPackedMsg, &pNfapiMsg->error_code, end) && + unpack_tlv_list(NULL, 0, ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); +} + +static uint8_t unpack_lte_cell_search_indication_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_lte_cell_search_indication_t *value = (nfapi_lte_cell_search_indication_t *)tlv; + uint16_t idx = 0; + + if(pull16(ppReadPackedMsg, &value->number_of_lte_cells_found, end) == 0) + return 0; + + if(value->number_of_lte_cells_found <= NFAPI_MAX_LTE_CELLS_FOUND) { + for(idx = 0; idx < value->number_of_lte_cells_found; ++idx) { + if(!(pull16(ppReadPackedMsg, &value->lte_found_cells[idx].pci, end) && + pull8(ppReadPackedMsg, &value->lte_found_cells[idx].rsrp, end) && + pull8(ppReadPackedMsg, &value->lte_found_cells[idx].rsrq, end) && + pulls16(ppReadPackedMsg, &value->lte_found_cells[idx].frequency_offset, end))) + return 0; + } + } else { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "More found LTE cells than we can decode %d \n", value->number_of_lte_cells_found); + return 0; + } + + return 1; +} + +static uint8_t unpack_utran_cell_search_indication_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_utran_cell_search_indication_t *value = (nfapi_utran_cell_search_indication_t *)tlv; + uint16_t idx = 0; + + if(pull16(ppReadPackedMsg, &value->number_of_utran_cells_found, end) == 0) + return 0; + + if(value->number_of_utran_cells_found <= NFAPI_MAX_UTRAN_CELLS_FOUND) { + for(idx = 0; idx < value->number_of_utran_cells_found; ++idx) { + if(!(pull16(ppReadPackedMsg, &value->utran_found_cells[idx].psc, end) && + pull8(ppReadPackedMsg, &value->utran_found_cells[idx].rscp, end) && + pull8(ppReadPackedMsg, &value->utran_found_cells[idx].ecno, end) && + pulls16(ppReadPackedMsg, &value->utran_found_cells[idx].frequency_offset, end))) + return 0; + } + } else { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "More found UTRAN cells than we can decode %d \n", value->number_of_utran_cells_found); + return 0; + } + + return 1; +} + +static uint8_t unpack_geran_cell_search_indication_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_geran_cell_search_indication_t *value = (nfapi_geran_cell_search_indication_t *)tlv; + uint16_t idx = 0; + + if(pull16(ppReadPackedMsg, &value->number_of_gsm_cells_found, end) == 0) + return 0; + + if(value->number_of_gsm_cells_found <= NFAPI_MAX_GSM_CELLS_FOUND) { + for(idx = 0; idx < value->number_of_gsm_cells_found; ++idx) { + if(!(pull16(ppReadPackedMsg, &value->gsm_found_cells[idx].arfcn, end) && + pull8(ppReadPackedMsg, &value->gsm_found_cells[idx].bsic, end) && + pull8(ppReadPackedMsg, &value->gsm_found_cells[idx].rxlev, end) && + pull8(ppReadPackedMsg, &value->gsm_found_cells[idx].rxqual, end) && + pulls16(ppReadPackedMsg, &value->gsm_found_cells[idx].frequency_offset, end) && + pull32(ppReadPackedMsg, &value->gsm_found_cells[idx].sfn_offset, end))) + return 0; + } + } else { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "More found GSM cells than we can decode %d \n", value->number_of_gsm_cells_found); + return 0; + } + + return 1; +} + +static uint8_t unpack_nb_iot_cell_search_indication_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_nb_iot_cell_search_indication_t *value = (nfapi_nb_iot_cell_search_indication_t *)tlv; + uint16_t idx = 0; + + if(pull16(ppReadPackedMsg, &value->number_of_nb_iot_cells_found, end) == 0) + return 0; + + if(value->number_of_nb_iot_cells_found <= NFAPI_MAX_NB_IOT_CELLS_FOUND) { + for(idx = 0; idx < value->number_of_nb_iot_cells_found; ++idx) { + if(!(pull16(ppReadPackedMsg, &value->nb_iot_found_cells[idx].pci, end) && + pull8(ppReadPackedMsg, &value->nb_iot_found_cells[idx].rsrp, end) && + pull8(ppReadPackedMsg, &value->nb_iot_found_cells[idx].rsrq, end) && + pulls16(ppReadPackedMsg, &value->nb_iot_found_cells[idx].frequency_offset, end))) + return 0; + } + } else { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "More found NB_IOT cells than we can decode %d \n", value->number_of_nb_iot_cells_found); + return 0; + } - return 1; -} - -static uint8_t unpack_system_information_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t* config) -{ - nfapi_system_information_request_t *pNfapiMsg = (nfapi_system_information_request_t*)msg; + return 1; +} - unpack_tlv_t unpack_fns[] = - { - { NFAPI_LTE_SYSTEM_INFORMATION_REQUEST_TAG, &pNfapiMsg->lte_system_information_request, &unpack_lte_system_information_request_value}, - { NFAPI_UTRAN_SYSTEM_INFORMATION_REQUEST_TAG, &pNfapiMsg->utran_system_information_request, &unpack_utran_system_information_request_value}, - { NFAPI_GERAN_SYSTEM_INFORMATION_REQUEST_TAG, &pNfapiMsg->geran_system_information_request, &unpack_geran_system_information_request_value}, - { NFAPI_NB_IOT_SYSTEM_INFORMATION_REQUEST_TAG, &pNfapiMsg->nb_iot_system_information_request, &unpack_nb_iot_system_information_request_value}, - { NFAPI_PNF_CELL_BROADCAST_STATE_TAG, &pNfapiMsg->pnf_cell_broadcast_state, &unpack_opaque_data_value} - }; +static uint8_t unpack_cell_search_indication(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t *config) { + nfapi_cell_search_indication_t *pNfapiMsg = (nfapi_cell_search_indication_t *)msg; + unpack_tlv_t unpack_fns[] = { + { NFAPI_LTE_CELL_SEARCH_INDICATION_TAG, &pNfapiMsg->lte_cell_search_indication, &unpack_lte_cell_search_indication_value}, + { NFAPI_UTRAN_CELL_SEARCH_INDICATION_TAG, &pNfapiMsg->utran_cell_search_indication, &unpack_utran_cell_search_indication_value}, + { NFAPI_GERAN_CELL_SEARCH_INDICATION_TAG, &pNfapiMsg->geran_cell_search_indication, &unpack_geran_cell_search_indication_value}, + { NFAPI_PNF_CELL_SEARCH_STATE_TAG, &pNfapiMsg->pnf_cell_search_state, &unpack_opaque_data_value}, + { NFAPI_NB_IOT_CELL_SEARCH_INDICATION_TAG, &pNfapiMsg->nb_iot_cell_search_indication, &unpack_nb_iot_cell_search_indication_value}, + }; + return (pull32(ppReadPackedMsg, &pNfapiMsg->error_code, end) && + unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); +} + +static uint8_t unpack_lte_broadcast_detect_request_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_lte_broadcast_detect_request_t *value = (nfapi_lte_broadcast_detect_request_t *)tlv; + return (pull16(ppReadPackedMsg, &value->earfcn, end) && + pull16(ppReadPackedMsg, &value->pci, end) && + pull32(ppReadPackedMsg, &value->timeout, end)); +} + +static uint8_t unpack_utran_broadcast_detect_request_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_utran_broadcast_detect_request_t *value = (nfapi_utran_broadcast_detect_request_t *)tlv; + return (pull16(ppReadPackedMsg, &value->uarfcn, end) && + pull16(ppReadPackedMsg, &value->psc, end) && + pull32(ppReadPackedMsg, &value->timeout, end)); +} + +static uint8_t unpack_nb_iot_broadcast_detect_request_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_nb_iot_broadcast_detect_request_t *value = (nfapi_nb_iot_broadcast_detect_request_t *)tlv; + return (pull16(ppReadPackedMsg, &value->earfcn, end) && + pull8(ppReadPackedMsg, &value->ro_dl, end) && + pull16(ppReadPackedMsg, &value->pci, end) && + pull32(ppReadPackedMsg, &value->timeout, end)); +} + +static uint8_t unpack_broadcast_detect_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t *config) { + nfapi_broadcast_detect_request_t *pNfapiMsg = (nfapi_broadcast_detect_request_t *)msg; + unpack_tlv_t unpack_fns[] = { + { NFAPI_LTE_BROADCAST_DETECT_REQUEST_TAG, &pNfapiMsg->lte_broadcast_detect_request, &unpack_lte_broadcast_detect_request_value}, + { NFAPI_UTRAN_BROADCAST_DETECT_REQUEST_TAG, &pNfapiMsg->utran_broadcast_detect_request, &unpack_utran_broadcast_detect_request_value}, + { NFAPI_PNF_CELL_SEARCH_STATE_TAG, &pNfapiMsg->pnf_cell_search_state, &unpack_opaque_data_value}, + { NFAPI_NB_IOT_BROADCAST_DETECT_REQUEST_TAG, &pNfapiMsg->nb_iot_broadcast_detect_request, &unpack_nb_iot_broadcast_detect_request_value} + }; + return (pull8(ppReadPackedMsg, &pNfapiMsg->rat_type, end) && + unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); +} + +static uint8_t unpack_broadcast_detect_response(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t *config) { + nfapi_broadcast_detect_response_t *pNfapiMsg = (nfapi_broadcast_detect_response_t *)msg; + return (pull32(ppReadPackedMsg, &pNfapiMsg->error_code, end) && + unpack_tlv_list(NULL, 0, ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); +} + +static uint8_t unpack_lte_broadcast_detect_indication_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_lte_broadcast_detect_indication_t *value = (nfapi_lte_broadcast_detect_indication_t *)tlv; + + if(!(pull8(ppReadPackedMsg, &value->number_of_tx_antenna, end) && + pull16(ppReadPackedMsg, &value->mib_length, end))) + return 0; + + if(value->mib_length > NFAPI_MAX_MIB_LENGTH) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "MIB too long %d \n", value->mib_length); + return 0; + } + + return (pullarray8(ppReadPackedMsg, value->mib, NFAPI_MAX_MIB_LENGTH, value->mib_length, end) && + pull32(ppReadPackedMsg, &value->sfn_offset, end)); +} +static uint8_t unpack_utran_broadcast_detect_indication_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_utran_broadcast_detect_indication_t *value = (nfapi_utran_broadcast_detect_indication_t *)tlv; - int result = (pull8(ppReadPackedMsg, &pNfapiMsg->rat_type, end) && - unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); + if(pull16(ppReadPackedMsg, &value->mib_length, end) == 0) + return 0; - // Verify that the rat type and the tlv match - if(result == 1 && - !((pNfapiMsg->rat_type == NFAPI_RAT_TYPE_LTE && pNfapiMsg->lte_system_information_request.tl.tag == NFAPI_LTE_SYSTEM_INFORMATION_REQUEST_TAG) || - (pNfapiMsg->rat_type == NFAPI_RAT_TYPE_UTRAN && pNfapiMsg->utran_system_information_request.tl.tag == NFAPI_UTRAN_SYSTEM_INFORMATION_REQUEST_TAG) || - (pNfapiMsg->rat_type == NFAPI_RAT_TYPE_GERAN && pNfapiMsg->geran_system_information_request.tl.tag == NFAPI_GERAN_SYSTEM_INFORMATION_REQUEST_TAG))) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "Mismatch RAT Type: %d and TAG value: 0x%04x \n", pNfapiMsg->rat_type, pNfapiMsg->lte_system_information_request.tl.tag); - result = 0; - } - - return result; + if(value->mib_length > NFAPI_MAX_MIB_LENGTH) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "MIB too long %d \n", value->mib_length); + return 0; + } + + return (pullarray8(ppReadPackedMsg, value->mib, NFAPI_MAX_MIB_LENGTH, value->mib_length, end) && + pull32(ppReadPackedMsg, &value->sfn_offset, end)); +} + +static uint8_t unpack_nb_iot_broadcast_detect_indication_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_nb_iot_broadcast_detect_indication_t *value = (nfapi_nb_iot_broadcast_detect_indication_t *)tlv; + + if(!(pull8(ppReadPackedMsg, &value->number_of_tx_antenna, end) && + pull16(ppReadPackedMsg, &value->mib_length, end))) + return 0; + + if(value->mib_length > NFAPI_MAX_MIB_LENGTH) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "MIB too long %d \n", value->mib_length); + return 0; + } + + return (pullarray8(ppReadPackedMsg, value->mib, NFAPI_MAX_MIB_LENGTH, value->mib_length, end) && + pull32(ppReadPackedMsg, &value->sfn_offset, end)); +} + +static uint8_t unpack_broadcast_detect_indication(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t *config) { + nfapi_broadcast_detect_indication_t *pNfapiMsg = (nfapi_broadcast_detect_indication_t *)msg; + unpack_tlv_t unpack_fns[] = { + { NFAPI_LTE_BROADCAST_DETECT_INDICATION_TAG, &pNfapiMsg->lte_broadcast_detect_indication, &unpack_lte_broadcast_detect_indication_value}, + { NFAPI_UTRAN_BROADCAST_DETECT_INDICATION_TAG, &pNfapiMsg->utran_broadcast_detect_indication, &unpack_utran_broadcast_detect_indication_value}, + { NFAPI_NB_IOT_BROADCAST_DETECT_INDICATION_TAG, &pNfapiMsg->nb_iot_broadcast_detect_indication, &unpack_nb_iot_broadcast_detect_indication_value}, + { NFAPI_PNF_CELL_BROADCAST_STATE_TAG, &pNfapiMsg->pnf_cell_broadcast_state, &unpack_opaque_data_value} + }; + return (pull32(ppReadPackedMsg, &pNfapiMsg->error_code, end) && + unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); +} + +static uint8_t unpack_lte_system_information_schedule_request_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_lte_system_information_schedule_request_t *value = (nfapi_lte_system_information_schedule_request_t *)tlv; + return (pull16(ppReadPackedMsg, &value->earfcn, end) && + pull16(ppReadPackedMsg, &value->pci, end) && + pull16(ppReadPackedMsg, &value->downlink_channel_bandwidth, end) && + pull8(ppReadPackedMsg, &value->phich_configuration, end) && + pull8(ppReadPackedMsg, &value->number_of_tx_antenna, end) && + pull8(ppReadPackedMsg, &value->retry_count, end) && + pull32(ppReadPackedMsg, &value->timeout, end)); +} + +static uint8_t unpack_nb_iot_system_information_schedule_request_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_nb_iot_system_information_schedule_request_t *value = (nfapi_nb_iot_system_information_schedule_request_t *)tlv; + return (pull16(ppReadPackedMsg, &value->earfcn, end) && + pull8(ppReadPackedMsg, &value->ro_dl, end) && + pull16(ppReadPackedMsg, &value->pci, end) && + pull8(ppReadPackedMsg, &value->scheduling_info_sib1_nb, end) && + pull32(ppReadPackedMsg, &value->timeout, end)); +} + +static uint8_t unpack_system_information_schedule_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t *config) { + nfapi_system_information_schedule_request_t *pNfapiMsg = (nfapi_system_information_schedule_request_t *)msg; + unpack_tlv_t unpack_fns[] = { + { NFAPI_LTE_SYSTEM_INFORMATION_SCHEDULE_REQUEST_TAG, &pNfapiMsg->lte_system_information_schedule_request, &unpack_lte_system_information_schedule_request_value}, + { NFAPI_NB_IOT_SYSTEM_INFORMATION_SCHEDULE_REQUEST_TAG, &pNfapiMsg->nb_iot_system_information_schedule_request, &unpack_nb_iot_system_information_schedule_request_value}, + { NFAPI_PNF_CELL_BROADCAST_STATE_TAG, &pNfapiMsg->pnf_cell_broadcast_state, &unpack_opaque_data_value} + }; + return (pull8(ppReadPackedMsg, &pNfapiMsg->rat_type, end) && + unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); +} + +static uint8_t unpack_system_information_schedule_response(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t *config) { + nfapi_system_information_schedule_response_t *pNfapiMsg = (nfapi_system_information_schedule_response_t *)msg; + return (pull32(ppReadPackedMsg, &pNfapiMsg->error_code, end) && + unpack_tlv_list(NULL, 0, ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); +} + +static uint8_t unpack_lte_system_information_indication_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_lte_system_information_indication_t *value = (nfapi_lte_system_information_indication_t *)tlv; + + if(!(pull8(ppReadPackedMsg, &value->sib_type, end) && + pull16(ppReadPackedMsg, &value->sib_length, end))) + return 0; + + if(value->sib_length > NFAPI_MAX_SIB_LENGTH) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "SIB too long %d \n", value->sib_length); + return 0; + } + + if(pullarray8(ppReadPackedMsg, value->sib, NFAPI_MAX_SIB_LENGTH, value->sib_length, end) == 0) + return 0; + + return 1; } -static uint8_t unpack_system_information_response(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t* config) -{ - nfapi_system_information_response_t *pNfapiMsg = (nfapi_system_information_response_t*)msg; +static uint8_t unpack_nb_iot_system_information_indication_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_nb_iot_system_information_indication_t *value = (nfapi_nb_iot_system_information_indication_t *)tlv; - unpack_tlv_t unpack_fns[] = - { - }; + if(!(pull8(ppReadPackedMsg, &value->sib_type, end) && + pull16(ppReadPackedMsg, &value->sib_length, end))) + return 0; - return (pull32(ppReadPackedMsg, &pNfapiMsg->error_code, end) && - unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); + if(value->sib_length > NFAPI_MAX_SIB_LENGTH) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "SIB too long %d \n", value->sib_length); + return 0; + } + + if(pullarray8(ppReadPackedMsg, value->sib, NFAPI_MAX_SIB_LENGTH, value->sib_length, end) == 0) + return 0; + + return 1; +} + +static uint8_t unpack_system_information_schedule_indication(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t *config) { + nfapi_system_information_schedule_indication_t *pNfapiMsg = (nfapi_system_information_schedule_indication_t *)msg; + unpack_tlv_t unpack_fns[] = { + { NFAPI_LTE_SYSTEM_INFORMATION_INDICATION_TAG, &pNfapiMsg->lte_system_information_indication, &unpack_lte_system_information_indication_value}, + { NFAPI_NB_IOT_SYSTEM_INFORMATION_INDICATION_TAG, &pNfapiMsg->nb_iot_system_information_indication, &unpack_nb_iot_system_information_indication_value}, + }; + return (pull32(ppReadPackedMsg, &pNfapiMsg->error_code, end) && + unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); +} + +static uint8_t unpack_lte_system_information_request_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_lte_system_information_request_t *value = (nfapi_lte_system_information_request_t *)tlv; + uint16_t idx = 0; + + if(!(pull16(ppReadPackedMsg, &value->earfcn, end) && + pull16(ppReadPackedMsg, &value->pci, end) && + pull16(ppReadPackedMsg, &value->downlink_channel_bandwidth, end) && + pull8(ppReadPackedMsg, &value->phich_configuration, end) && + pull8(ppReadPackedMsg, &value->number_of_tx_antenna, end) && + pull8(ppReadPackedMsg, &value->number_of_si_periodicity, end))) + return 0; + + if(value->number_of_si_periodicity > NFAPI_MAX_SI_PERIODICITY) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "More found SI periodicity than we can decode %d \n", value->number_of_si_periodicity); + return 0; + } + + for(idx = 0; idx < value->number_of_si_periodicity; ++idx) { + if(!(pull8(ppReadPackedMsg, &value->si_periodicity[idx].si_periodicity, end) && + pull8(ppReadPackedMsg, &value->si_periodicity[idx].si_index, end))) + return 0; + } + + if(!(pull8(ppReadPackedMsg, &value->si_window_length, end) && + pull32(ppReadPackedMsg, &value->timeout, end))) + return 0; + + return 1; +} + +static uint8_t unpack_utran_system_information_request_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_utran_system_information_request_t *value = (nfapi_utran_system_information_request_t *)tlv; + return (pull16(ppReadPackedMsg, &value->uarfcn, end) && + pull16(ppReadPackedMsg, &value->psc, end) && + pull32(ppReadPackedMsg, &value->timeout, end)); +} + +static uint8_t unpack_geran_system_information_request_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_geran_system_information_request_t *value = (nfapi_geran_system_information_request_t *)tlv; + return (pull16(ppReadPackedMsg, &value->arfcn, end) && + pull8(ppReadPackedMsg, &value->bsic, end) && + pull32(ppReadPackedMsg, &value->timeout, end)); } -static uint8_t unpack_utran_system_information_indication_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_utran_system_information_indication_t* value = (nfapi_utran_system_information_indication_t*)tlv; +static uint8_t unpack_nb_iot_system_information_request_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_nb_iot_system_information_request_t *value = (nfapi_nb_iot_system_information_request_t *)tlv; + uint16_t idx = 0; - if(pull16(ppReadPackedMsg, &value->sib_length, end) == 0) - return 0; + if(!(pull16(ppReadPackedMsg, &value->earfcn, end) && + pull8(ppReadPackedMsg, &value->ro_dl, end) && + pull16(ppReadPackedMsg, &value->pci, end) && + pull8(ppReadPackedMsg, &value->number_of_si_periodicity, end))) + return 0; - if(value->sib_length > NFAPI_MAX_SIB_LENGTH) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "SIB too long %d \n", value->sib_length); - return 0; - } - - if(pullarray8(ppReadPackedMsg, value->sib, NFAPI_MAX_SIB_LENGTH, value->sib_length, end) == 0) - return 0; + if(value->number_of_si_periodicity > NFAPI_MAX_SI_PERIODICITY) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "More found SI periodicity than we can decode %d \n", value->number_of_si_periodicity); + return 0; + } - return 1; -} - -static uint8_t unpack_geran_system_information_indication_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_geran_system_information_indication_t* value = (nfapi_geran_system_information_indication_t*)tlv; - - if(pull16(ppReadPackedMsg, &value->si_length, end) == 0) - return 0; + for(idx = 0; idx < value->number_of_si_periodicity; ++idx) { + if(!(pull8(ppReadPackedMsg, &value->si_periodicity[idx].si_periodicity, end) && + pull8(ppReadPackedMsg, &value->si_periodicity[idx].si_repetition_pattern, end) && + pull8(ppReadPackedMsg, &value->si_periodicity[idx].si_tb_size, end) && + pull8(ppReadPackedMsg, &value->si_periodicity[idx].number_of_si_index, end))) + return 0; - if(value->si_length > NFAPI_MAX_SI_LENGTH) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "SIB too long %d \n", value->si_length); - return 0; - } + uint8_t si_idx; - if(pullarray8(ppReadPackedMsg, value->si, NFAPI_MAX_SI_LENGTH, value->si_length, end) == 0) - return 0; + for(si_idx = 0; si_idx < value->si_periodicity[idx].number_of_si_index; ++si_idx) { + if(!(pull8(ppReadPackedMsg, &value->si_periodicity[idx].si_index[si_idx], end))) + return 0; + } + } - return 1; + if(!(pull8(ppReadPackedMsg, &value->si_window_length, end) && + pull32(ppReadPackedMsg, &value->timeout, end))) + return 0; + + return 1; } -static uint8_t unpack_system_information_indication(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t* config) -{ - nfapi_system_information_indication_t *pNfapiMsg = (nfapi_system_information_indication_t*)msg; +static uint8_t unpack_system_information_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t *config) { + nfapi_system_information_request_t *pNfapiMsg = (nfapi_system_information_request_t *)msg; + unpack_tlv_t unpack_fns[] = { + { NFAPI_LTE_SYSTEM_INFORMATION_REQUEST_TAG, &pNfapiMsg->lte_system_information_request, &unpack_lte_system_information_request_value}, + { NFAPI_UTRAN_SYSTEM_INFORMATION_REQUEST_TAG, &pNfapiMsg->utran_system_information_request, &unpack_utran_system_information_request_value}, + { NFAPI_GERAN_SYSTEM_INFORMATION_REQUEST_TAG, &pNfapiMsg->geran_system_information_request, &unpack_geran_system_information_request_value}, + { NFAPI_NB_IOT_SYSTEM_INFORMATION_REQUEST_TAG, &pNfapiMsg->nb_iot_system_information_request, &unpack_nb_iot_system_information_request_value}, + { NFAPI_PNF_CELL_BROADCAST_STATE_TAG, &pNfapiMsg->pnf_cell_broadcast_state, &unpack_opaque_data_value} + }; + int result = (pull8(ppReadPackedMsg, &pNfapiMsg->rat_type, end) && + unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); - unpack_tlv_t unpack_fns[] = - { - { NFAPI_LTE_SYSTEM_INFORMATION_INDICATION_TAG, &pNfapiMsg->lte_system_information_indication, &unpack_lte_system_information_indication_value}, - { NFAPI_UTRAN_SYSTEM_INFORMATION_INDICATION_TAG, &pNfapiMsg->utran_system_information_indication, &unpack_utran_system_information_indication_value}, - { NFAPI_GERAN_SYSTEM_INFORMATION_INDICATION_TAG, &pNfapiMsg->geran_system_information_indication, &unpack_geran_system_information_indication_value}, - { NFAPI_NB_IOT_SYSTEM_INFORMATION_INDICATION_TAG, &pNfapiMsg->nb_iot_system_information_indication, &unpack_nb_iot_system_information_indication_value}, - }; + // Verify that the rat type and the tlv match + if(result == 1 && + !((pNfapiMsg->rat_type == NFAPI_RAT_TYPE_LTE && pNfapiMsg->lte_system_information_request.tl.tag == NFAPI_LTE_SYSTEM_INFORMATION_REQUEST_TAG) || + (pNfapiMsg->rat_type == NFAPI_RAT_TYPE_UTRAN && pNfapiMsg->utran_system_information_request.tl.tag == NFAPI_UTRAN_SYSTEM_INFORMATION_REQUEST_TAG) || + (pNfapiMsg->rat_type == NFAPI_RAT_TYPE_GERAN && pNfapiMsg->geran_system_information_request.tl.tag == NFAPI_GERAN_SYSTEM_INFORMATION_REQUEST_TAG))) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "Mismatch RAT Type: %d and TAG value: 0x%04x \n", pNfapiMsg->rat_type, pNfapiMsg->lte_system_information_request.tl.tag); + result = 0; + } - return (pull32(ppReadPackedMsg, &pNfapiMsg->error_code, end) && - unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); + return result; +} +static uint8_t unpack_system_information_response(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t *config) { + nfapi_system_information_response_t *pNfapiMsg = (nfapi_system_information_response_t *)msg; + return (pull32(ppReadPackedMsg, &pNfapiMsg->error_code, end) && + unpack_tlv_list(NULL, 0, ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); } -static uint8_t unpack_nmm_stop_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t* config) -{ - nfapi_nmm_stop_request_t *pNfapiMsg = (nfapi_nmm_stop_request_t*)msg; +static uint8_t unpack_utran_system_information_indication_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_utran_system_information_indication_t *value = (nfapi_utran_system_information_indication_t *)tlv; + + if(pull16(ppReadPackedMsg, &value->sib_length, end) == 0) + return 0; - unpack_tlv_t unpack_fns[] = - { - }; + if(value->sib_length > NFAPI_MAX_SIB_LENGTH) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "SIB too long %d \n", value->sib_length); + return 0; + } - return unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension); + if(pullarray8(ppReadPackedMsg, value->sib, NFAPI_MAX_SIB_LENGTH, value->sib_length, end) == 0) + return 0; + + return 1; } -static uint8_t unpack_nmm_stop_response(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t* config) -{ - nfapi_nmm_stop_response_t *pNfapiMsg = (nfapi_nmm_stop_response_t*)msg; +static uint8_t unpack_geran_system_information_indication_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_geran_system_information_indication_t *value = (nfapi_geran_system_information_indication_t *)tlv; + + if(pull16(ppReadPackedMsg, &value->si_length, end) == 0) + return 0; + + if(value->si_length > NFAPI_MAX_SI_LENGTH) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "SIB too long %d \n", value->si_length); + return 0; + } - unpack_tlv_t unpack_fns[] = - { - }; + if(pullarray8(ppReadPackedMsg, value->si, NFAPI_MAX_SI_LENGTH, value->si_length, end) == 0) + return 0; - return (pull32(ppReadPackedMsg, &pNfapiMsg->error_code, end) && - unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); + return 1; } +static uint8_t unpack_system_information_indication(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t *config) { + nfapi_system_information_indication_t *pNfapiMsg = (nfapi_system_information_indication_t *)msg; + unpack_tlv_t unpack_fns[] = { + { NFAPI_LTE_SYSTEM_INFORMATION_INDICATION_TAG, &pNfapiMsg->lte_system_information_indication, &unpack_lte_system_information_indication_value}, + { NFAPI_UTRAN_SYSTEM_INFORMATION_INDICATION_TAG, &pNfapiMsg->utran_system_information_indication, &unpack_utran_system_information_indication_value}, + { NFAPI_GERAN_SYSTEM_INFORMATION_INDICATION_TAG, &pNfapiMsg->geran_system_information_indication, &unpack_geran_system_information_indication_value}, + { NFAPI_NB_IOT_SYSTEM_INFORMATION_INDICATION_TAG, &pNfapiMsg->nb_iot_system_information_indication, &unpack_nb_iot_system_information_indication_value}, + }; + return (pull32(ppReadPackedMsg, &pNfapiMsg->error_code, end) && + unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); +} + +static uint8_t unpack_nmm_stop_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t *config) { + nfapi_nmm_stop_request_t *pNfapiMsg = (nfapi_nmm_stop_request_t *)msg; + return unpack_tlv_list(NULL, 0, ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension); +} + +static uint8_t unpack_nmm_stop_response(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t *config) { + nfapi_nmm_stop_response_t *pNfapiMsg = (nfapi_nmm_stop_response_t *)msg; + return (pull32(ppReadPackedMsg, &pNfapiMsg->error_code, end) && + unpack_tlv_list(NULL, 0, ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); +} + + +static int check_unpack_length(nfapi_message_id_e msgId, uint32_t unpackedBufLen) { + int retLen = 0; + + switch (msgId) { + case NFAPI_RSSI_REQUEST: + if (unpackedBufLen >= sizeof(nfapi_rssi_request_t)) + retLen = sizeof(nfapi_rssi_request_t); + + break; + + case NFAPI_RSSI_RESPONSE: + if (unpackedBufLen >= sizeof(nfapi_rssi_response_t)) + retLen = sizeof(nfapi_rssi_response_t); + + break; + + case NFAPI_RSSI_INDICATION: + if (unpackedBufLen >= sizeof(nfapi_rssi_indication_t)) + retLen = sizeof(nfapi_rssi_indication_t); + + break; + + case NFAPI_CELL_SEARCH_REQUEST: + if (unpackedBufLen >= sizeof(nfapi_cell_search_request_t)) + retLen = sizeof(nfapi_cell_search_request_t); + + break; + + case NFAPI_CELL_SEARCH_RESPONSE: + if (unpackedBufLen >= sizeof(nfapi_cell_search_response_t)) + retLen = sizeof(nfapi_cell_search_response_t); + + break; + + case NFAPI_CELL_SEARCH_INDICATION: + if (unpackedBufLen >= sizeof(nfapi_cell_search_indication_t)) + retLen = sizeof(nfapi_cell_search_indication_t); + + break; + + case NFAPI_BROADCAST_DETECT_REQUEST: + if (unpackedBufLen >= sizeof(nfapi_broadcast_detect_request_t)) + retLen = sizeof(nfapi_broadcast_detect_request_t); + + break; + + case NFAPI_BROADCAST_DETECT_RESPONSE: + if (unpackedBufLen >= sizeof(nfapi_broadcast_detect_response_t)) + retLen = sizeof(nfapi_broadcast_detect_response_t); + + break; + + case NFAPI_BROADCAST_DETECT_INDICATION: + if (unpackedBufLen >= sizeof(nfapi_broadcast_detect_indication_t)) + retLen = sizeof(nfapi_broadcast_detect_indication_t); + + break; + + case NFAPI_SYSTEM_INFORMATION_SCHEDULE_REQUEST: + if (unpackedBufLen >= sizeof(nfapi_system_information_schedule_request_t)) + retLen = sizeof(nfapi_system_information_schedule_request_t); + + break; + + case NFAPI_SYSTEM_INFORMATION_SCHEDULE_RESPONSE: + if (unpackedBufLen >= sizeof(nfapi_system_information_schedule_response_t)) + retLen = sizeof(nfapi_system_information_schedule_response_t); + + break; + + case NFAPI_SYSTEM_INFORMATION_SCHEDULE_INDICATION: + if (unpackedBufLen >= sizeof(nfapi_system_information_schedule_indication_t)) + retLen = sizeof(nfapi_system_information_schedule_indication_t); + + break; + + case NFAPI_SYSTEM_INFORMATION_REQUEST: + if (unpackedBufLen >= sizeof(nfapi_system_information_request_t)) + retLen = sizeof(nfapi_system_information_request_t); + + break; + + case NFAPI_SYSTEM_INFORMATION_RESPONSE: + if (unpackedBufLen >= sizeof(nfapi_system_information_response_t)) + retLen = sizeof(nfapi_system_information_response_t); + + break; + + case NFAPI_SYSTEM_INFORMATION_INDICATION: + if (unpackedBufLen >= sizeof(nfapi_system_information_indication_t)) + retLen = sizeof(nfapi_system_information_indication_t); + + break; + + case NFAPI_NMM_STOP_REQUEST: + if (unpackedBufLen >= sizeof(nfapi_nmm_stop_request_t)) + retLen = sizeof(nfapi_nmm_stop_request_t); + + break; + + case NFAPI_NMM_STOP_RESPONSE: + if (unpackedBufLen >= sizeof(nfapi_nmm_stop_response_t)) + retLen = sizeof(nfapi_nmm_stop_response_t); + + break; + + default: + NFAPI_TRACE(NFAPI_TRACE_ERROR, "Unknown message ID %d\n", msgId); + break; + } + + return retLen; +} + +int nfapi_p4_message_pack(void *pMessageBuf, uint32_t messageBufLen, void *pPackedBuf, uint32_t packedBufLen, nfapi_p4_p5_codec_config_t *config) { + nfapi_p4_p5_message_header_t *pMessageHeader = pMessageBuf; + uint8_t *end = pPackedBuf + packedBufLen; + uint8_t *pWritePackedMessage = pPackedBuf; + uint8_t *pPackedLengthField = &pWritePackedMessage[4]; + uint32_t packedMsgLen; + uint16_t packedMsgLen16; + + if (pMessageBuf == NULL || pPackedBuf == NULL) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "P4 Pack supplied pointers are null\n"); + return -1; + } + + // process the header + if(!(push16(pMessageHeader->phy_id, &pWritePackedMessage, end) && + push16(pMessageHeader->message_id, &pWritePackedMessage, end) && + push16(0/*pMessageHeader->message_length*/, &pWritePackedMessage, end) && + push16(pMessageHeader->spare, &pWritePackedMessage, end))) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "Failed to pack p4 message header\n"); + return -1; + } + + // look for the specific message + uint8_t result = 0; -static int check_unpack_length(nfapi_message_id_e msgId, uint32_t unpackedBufLen) -{ - int retLen = 0; + switch (pMessageHeader->message_id) { + case NFAPI_RSSI_REQUEST: + result = pack_rssi_request(pMessageHeader, &pWritePackedMessage, end, config); + break; - switch (msgId) - { - case NFAPI_RSSI_REQUEST: - if (unpackedBufLen >= sizeof(nfapi_rssi_request_t)) - retLen = sizeof(nfapi_rssi_request_t); - break; + case NFAPI_RSSI_RESPONSE: + result = pack_rssi_response(pMessageHeader, &pWritePackedMessage, end,config); + break; - case NFAPI_RSSI_RESPONSE: - if (unpackedBufLen >= sizeof(nfapi_rssi_response_t)) - retLen = sizeof(nfapi_rssi_response_t); - break; + case NFAPI_RSSI_INDICATION: + result = pack_rssi_indication(pMessageHeader, &pWritePackedMessage, end, config); + break; - case NFAPI_RSSI_INDICATION: - if (unpackedBufLen >= sizeof(nfapi_rssi_indication_t)) - retLen = sizeof(nfapi_rssi_indication_t); - break; - - case NFAPI_CELL_SEARCH_REQUEST: - if (unpackedBufLen >= sizeof(nfapi_cell_search_request_t)) - retLen = sizeof(nfapi_cell_search_request_t); - break; - - case NFAPI_CELL_SEARCH_RESPONSE: - if (unpackedBufLen >= sizeof(nfapi_cell_search_response_t)) - retLen = sizeof(nfapi_cell_search_response_t); - break; - - case NFAPI_CELL_SEARCH_INDICATION: - if (unpackedBufLen >= sizeof(nfapi_cell_search_indication_t)) - retLen = sizeof(nfapi_cell_search_indication_t); - break; - - case NFAPI_BROADCAST_DETECT_REQUEST: - if (unpackedBufLen >= sizeof(nfapi_broadcast_detect_request_t)) - retLen = sizeof(nfapi_broadcast_detect_request_t); - break; - - case NFAPI_BROADCAST_DETECT_RESPONSE: - if (unpackedBufLen >= sizeof(nfapi_broadcast_detect_response_t)) - retLen = sizeof(nfapi_broadcast_detect_response_t); - break; - - case NFAPI_BROADCAST_DETECT_INDICATION: - if (unpackedBufLen >= sizeof(nfapi_broadcast_detect_indication_t)) - retLen = sizeof(nfapi_broadcast_detect_indication_t); - break; - - case NFAPI_SYSTEM_INFORMATION_SCHEDULE_REQUEST: - if (unpackedBufLen >= sizeof(nfapi_system_information_schedule_request_t)) - retLen = sizeof(nfapi_system_information_schedule_request_t); - break; - - case NFAPI_SYSTEM_INFORMATION_SCHEDULE_RESPONSE: - if (unpackedBufLen >= sizeof(nfapi_system_information_schedule_response_t)) - retLen = sizeof(nfapi_system_information_schedule_response_t); - break; - - case NFAPI_SYSTEM_INFORMATION_SCHEDULE_INDICATION: - if (unpackedBufLen >= sizeof(nfapi_system_information_schedule_indication_t)) - retLen = sizeof(nfapi_system_information_schedule_indication_t); - break; - - case NFAPI_SYSTEM_INFORMATION_REQUEST: - if (unpackedBufLen >= sizeof(nfapi_system_information_request_t)) - retLen = sizeof(nfapi_system_information_request_t); - break; - - case NFAPI_SYSTEM_INFORMATION_RESPONSE: - if (unpackedBufLen >= sizeof(nfapi_system_information_response_t)) - retLen = sizeof(nfapi_system_information_response_t); - break; - - case NFAPI_SYSTEM_INFORMATION_INDICATION: - if (unpackedBufLen >= sizeof(nfapi_system_information_indication_t)) - retLen = sizeof(nfapi_system_information_indication_t); - break; - - case NFAPI_NMM_STOP_REQUEST: - if (unpackedBufLen >= sizeof(nfapi_nmm_stop_request_t)) - retLen = sizeof(nfapi_nmm_stop_request_t); - break; - - case NFAPI_NMM_STOP_RESPONSE: - if (unpackedBufLen >= sizeof(nfapi_nmm_stop_response_t)) - retLen = sizeof(nfapi_nmm_stop_response_t); - break; - - default: - NFAPI_TRACE(NFAPI_TRACE_ERROR, "Unknown message ID %d\n", msgId); - break; - } - - return retLen; -} - -int nfapi_p4_message_pack(void *pMessageBuf, uint32_t messageBufLen, void *pPackedBuf, uint32_t packedBufLen, nfapi_p4_p5_codec_config_t* config) -{ - nfapi_p4_p5_message_header_t *pMessageHeader = pMessageBuf; - uint8_t *end = pPackedBuf + packedBufLen; - uint8_t *pWritePackedMessage = pPackedBuf; - uint8_t *pPackedLengthField = &pWritePackedMessage[4]; - uint32_t packedMsgLen; - uint16_t packedMsgLen16; - - if (pMessageBuf == NULL || pPackedBuf == NULL) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "P4 Pack supplied pointers are null\n"); - return -1; - } - - // process the header - if(!(push16(pMessageHeader->phy_id, &pWritePackedMessage, end) && - push16(pMessageHeader->message_id, &pWritePackedMessage, end) && - push16(0/*pMessageHeader->message_length*/, &pWritePackedMessage, end) && - push16(pMessageHeader->spare, &pWritePackedMessage, end))) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "Failed to pack p4 message header\n"); - return -1; - } - - // look for the specific message - uint8_t result = 0; - switch (pMessageHeader->message_id) - { - case NFAPI_RSSI_REQUEST: - result = pack_rssi_request(pMessageHeader, &pWritePackedMessage, end, config); - break; - - case NFAPI_RSSI_RESPONSE: - result = pack_rssi_response(pMessageHeader, &pWritePackedMessage, end,config); - break; - - case NFAPI_RSSI_INDICATION: - result = pack_rssi_indication(pMessageHeader, &pWritePackedMessage, end, config); - break; - - case NFAPI_CELL_SEARCH_REQUEST: - result = pack_cell_search_request(pMessageHeader, &pWritePackedMessage, end, config); - break; - - case NFAPI_CELL_SEARCH_RESPONSE: - result = pack_cell_search_response(pMessageHeader, &pWritePackedMessage, end, config); - break; - - case NFAPI_CELL_SEARCH_INDICATION: - result = pack_cell_search_indication(pMessageHeader, &pWritePackedMessage, end, config); - break; - - case NFAPI_BROADCAST_DETECT_REQUEST: - result = pack_broadcast_detect_request(pMessageHeader, &pWritePackedMessage, end, config); - break; - - case NFAPI_BROADCAST_DETECT_RESPONSE: - result = pack_broadcast_detect_response(pMessageHeader, &pWritePackedMessage, end, config); - break; - - case NFAPI_BROADCAST_DETECT_INDICATION: - result = pack_broadcast_detect_indication(pMessageHeader, &pWritePackedMessage, end, config); - break; - - case NFAPI_SYSTEM_INFORMATION_SCHEDULE_REQUEST: - result = pack_system_information_schedule_request(pMessageHeader, &pWritePackedMessage, end, config); - break; - - case NFAPI_SYSTEM_INFORMATION_SCHEDULE_RESPONSE: - result = pack_system_information_schedule_response(pMessageHeader, &pWritePackedMessage, end, config); - break; - - case NFAPI_SYSTEM_INFORMATION_SCHEDULE_INDICATION: - result = pack_system_information_schedule_indication(pMessageHeader, &pWritePackedMessage, end, config); - break; - - case NFAPI_SYSTEM_INFORMATION_REQUEST: - result = pack_system_information_request(pMessageHeader, &pWritePackedMessage, end, config); - break; - - case NFAPI_SYSTEM_INFORMATION_RESPONSE: - result = pack_system_information_response(pMessageHeader, &pWritePackedMessage, end, config); - break; - - case NFAPI_SYSTEM_INFORMATION_INDICATION: - result = pack_system_information_indication(pMessageHeader, &pWritePackedMessage, end, config); - break; - - case NFAPI_NMM_STOP_REQUEST: - result = pack_nmm_stop_request(pMessageHeader, &pWritePackedMessage, end, config); - break; - - case NFAPI_NMM_STOP_RESPONSE: - result = pack_nmm_stop_response(pMessageHeader, &pWritePackedMessage, end, config); - break; - - default: - { - if(pMessageHeader->message_id >= NFAPI_VENDOR_EXT_MSG_MIN && - pMessageHeader->message_id <= NFAPI_VENDOR_EXT_MSG_MIN) - { - if(config && config->pack_p4_p5_vendor_extension) - { - result =(config->pack_p4_p5_vendor_extension)(pMessageHeader, &pWritePackedMessage, end, config); - } - else - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s VE NFAPI message ID %d. No ve encoder provided\n", __FUNCTION__, pMessageHeader->message_id); - } - } - else - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s NFAPI Unknown message ID %d\n", __FUNCTION__, pMessageHeader->message_id); - } - } - break; - } - - // return the packed length - if(result == 0) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "Result is 0\n"); - return -1; - } - - - // check for a valid message length - packedMsgLen = get_packed_msg_len((uintptr_t)pPackedBuf, (uintptr_t)pWritePackedMessage); - if (packedMsgLen > 0xFFFF || packedMsgLen > packedBufLen) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "Packed message length error %d, buffer supplied %d\n", packedMsgLen, packedBufLen); - return -1; - } - else - { - packedMsgLen16 = (uint16_t)packedMsgLen; - } - - // Update the message length in the header - if(push16(packedMsgLen16, &pPackedLengthField, end) == 0) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "Failed to pack p4 message header lengt\n"); - return -1; - } - - return (packedMsgLen); + case NFAPI_CELL_SEARCH_REQUEST: + result = pack_cell_search_request(pMessageHeader, &pWritePackedMessage, end, config); + break; + case NFAPI_CELL_SEARCH_RESPONSE: + result = pack_cell_search_response(pMessageHeader, &pWritePackedMessage, end, config); + break; + + case NFAPI_CELL_SEARCH_INDICATION: + result = pack_cell_search_indication(pMessageHeader, &pWritePackedMessage, end, config); + break; + + case NFAPI_BROADCAST_DETECT_REQUEST: + result = pack_broadcast_detect_request(pMessageHeader, &pWritePackedMessage, end, config); + break; + + case NFAPI_BROADCAST_DETECT_RESPONSE: + result = pack_broadcast_detect_response(pMessageHeader, &pWritePackedMessage, end, config); + break; + + case NFAPI_BROADCAST_DETECT_INDICATION: + result = pack_broadcast_detect_indication(pMessageHeader, &pWritePackedMessage, end, config); + break; + + case NFAPI_SYSTEM_INFORMATION_SCHEDULE_REQUEST: + result = pack_system_information_schedule_request(pMessageHeader, &pWritePackedMessage, end, config); + break; + + case NFAPI_SYSTEM_INFORMATION_SCHEDULE_RESPONSE: + result = pack_system_information_schedule_response(pMessageHeader, &pWritePackedMessage, end, config); + break; + + case NFAPI_SYSTEM_INFORMATION_SCHEDULE_INDICATION: + result = pack_system_information_schedule_indication(pMessageHeader, &pWritePackedMessage, end, config); + break; + + case NFAPI_SYSTEM_INFORMATION_REQUEST: + result = pack_system_information_request(pMessageHeader, &pWritePackedMessage, end, config); + break; + + case NFAPI_SYSTEM_INFORMATION_RESPONSE: + result = pack_system_information_response(pMessageHeader, &pWritePackedMessage, end, config); + break; + + case NFAPI_SYSTEM_INFORMATION_INDICATION: + result = pack_system_information_indication(pMessageHeader, &pWritePackedMessage, end, config); + break; + + case NFAPI_NMM_STOP_REQUEST: + result = pack_nmm_stop_request(pMessageHeader, &pWritePackedMessage, end, config); + break; + + case NFAPI_NMM_STOP_RESPONSE: + result = pack_nmm_stop_response(pMessageHeader, &pWritePackedMessage, end, config); + break; + + default: { + if(pMessageHeader->message_id >= NFAPI_VENDOR_EXT_MSG_MIN && + pMessageHeader->message_id <= NFAPI_VENDOR_EXT_MSG_MIN) { + if(config && config->pack_p4_p5_vendor_extension) { + result =(config->pack_p4_p5_vendor_extension)(pMessageHeader, &pWritePackedMessage, end, config); + } else { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s VE NFAPI message ID %d. No ve encoder provided\n", __FUNCTION__, pMessageHeader->message_id); + } + } else { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s NFAPI Unknown message ID %d\n", __FUNCTION__, pMessageHeader->message_id); + } + } + break; + } + + // return the packed length + if(result == 0) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "Result is 0\n"); + return -1; + } + + // check for a valid message length + packedMsgLen = get_packed_msg_len((uintptr_t)pPackedBuf, (uintptr_t)pWritePackedMessage); + + if (packedMsgLen > 0xFFFF || packedMsgLen > packedBufLen) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "Packed message length error %d, buffer supplied %d\n", packedMsgLen, packedBufLen); + return -1; + } else { + packedMsgLen16 = (uint16_t)packedMsgLen; + } + + // Update the message length in the header + if(push16(packedMsgLen16, &pPackedLengthField, end) == 0) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "Failed to pack p4 message header lengt\n"); + return -1; + } + + return (packedMsgLen); } // Main unpack functions - public -int nfapi_p4_message_header_unpack(void *pMessageBuf, uint32_t messageBufLen, void *pUnpackedBuf, uint32_t unpackedBufLen, nfapi_p4_p5_codec_config_t* config) -{ - nfapi_p4_p5_message_header_t *pMessageHeader = pUnpackedBuf; - uint8_t *pReadPackedMessage = pMessageBuf; - uint8_t *end = pMessageBuf + messageBufLen; +int nfapi_p4_message_header_unpack(void *pMessageBuf, uint32_t messageBufLen, void *pUnpackedBuf, uint32_t unpackedBufLen, nfapi_p4_p5_codec_config_t *config) { + nfapi_p4_p5_message_header_t *pMessageHeader = pUnpackedBuf; + uint8_t *pReadPackedMessage = pMessageBuf; + uint8_t *end = pMessageBuf + messageBufLen; - if (pMessageBuf == NULL || pUnpackedBuf == NULL) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "P4 header unpack supplied pointers are null\n"); - return -1; - } + if (pMessageBuf == NULL || pUnpackedBuf == NULL) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "P4 header unpack supplied pointers are null\n"); + return -1; + } - if (messageBufLen < NFAPI_HEADER_LENGTH || unpackedBufLen < sizeof(nfapi_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; - } + if (messageBufLen < NFAPI_HEADER_LENGTH || unpackedBufLen < sizeof(nfapi_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; + } - // process the headei - if (pull16(&pReadPackedMessage, &pMessageHeader->phy_id, end) && - pull16(&pReadPackedMessage, &pMessageHeader->message_id, end) && - pull16(&pReadPackedMessage, &pMessageHeader->message_length, end) && - pull16(&pReadPackedMessage, &pMessageHeader->spare, end)) - return -1; + // process the headei + if (pull16(&pReadPackedMessage, &pMessageHeader->phy_id, end) && + pull16(&pReadPackedMessage, &pMessageHeader->message_id, end) && + pull16(&pReadPackedMessage, &pMessageHeader->message_length, end) && + pull16(&pReadPackedMessage, &pMessageHeader->spare, end)) + return -1; - return 0; + return 0; } -int nfapi_p4_message_unpack(void *pMessageBuf, uint32_t messageBufLen, void *pUnpackedBuf, uint32_t unpackedBufLen, nfapi_p4_p5_codec_config_t* config) -{ - int result = 0; - nfapi_p4_p5_message_header_t *pMessageHeader = pUnpackedBuf; - uint8_t *pReadPackedMessage = pMessageBuf; - uint8_t *end = pMessageBuf + messageBufLen; +int nfapi_p4_message_unpack(void *pMessageBuf, uint32_t messageBufLen, void *pUnpackedBuf, uint32_t unpackedBufLen, nfapi_p4_p5_codec_config_t *config) { + int result = 0; + nfapi_p4_p5_message_header_t *pMessageHeader = pUnpackedBuf; + uint8_t *pReadPackedMessage = pMessageBuf; + uint8_t *end = pMessageBuf + messageBufLen; - if (pMessageBuf == NULL || pUnpackedBuf == NULL) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "P4 unpack supplied pointers are null\n"); - return -1; - } + if (pMessageBuf == NULL || pUnpackedBuf == NULL) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "P4 unpack supplied pointers are null\n"); + return -1; + } - if (messageBufLen < NFAPI_HEADER_LENGTH || unpackedBufLen < sizeof(nfapi_p4_p5_message_header_t)) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "P4 unpack supplied message buffer is too small %d, %d\n", messageBufLen, unpackedBufLen); - return -1; - } + if (messageBufLen < NFAPI_HEADER_LENGTH || unpackedBufLen < sizeof(nfapi_p4_p5_message_header_t)) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "P4 unpack supplied message buffer is too small %d, %d\n", messageBufLen, unpackedBufLen); + return -1; + } - // clean the supplied buffer for - tag value blanking - (void)memset(pUnpackedBuf, 0, unpackedBufLen); + // clean the supplied buffer for - tag value blanking + (void)memset(pUnpackedBuf, 0, unpackedBufLen); - // process the header - if(!(pull16(&pReadPackedMessage, &pMessageHeader->phy_id, end) && - pull16(&pReadPackedMessage, &pMessageHeader->message_id, end) && - pull16(&pReadPackedMessage, &pMessageHeader->message_length, end) && - pull16(&pReadPackedMessage, &pMessageHeader->spare, end))) - return -1; + // process the header + if(!(pull16(&pReadPackedMessage, &pMessageHeader->phy_id, end) && + pull16(&pReadPackedMessage, &pMessageHeader->message_id, end) && + pull16(&pReadPackedMessage, &pMessageHeader->message_length, end) && + pull16(&pReadPackedMessage, &pMessageHeader->spare, end))) + return -1; - // look for the specific message - switch (pMessageHeader->message_id) - { - case NFAPI_RSSI_REQUEST: - if (check_unpack_length(NFAPI_RSSI_REQUEST, unpackedBufLen)) - result = unpack_rssi_request(&pReadPackedMessage, end, pMessageHeader, config); - else - result = -1; - break; + // look for the specific message + switch (pMessageHeader->message_id) { + case NFAPI_RSSI_REQUEST: + if (check_unpack_length(NFAPI_RSSI_REQUEST, unpackedBufLen)) + result = unpack_rssi_request(&pReadPackedMessage, end, pMessageHeader, config); + else + result = -1; - case NFAPI_RSSI_RESPONSE: - if (check_unpack_length(NFAPI_RSSI_RESPONSE, unpackedBufLen)) - result = unpack_rssi_response(&pReadPackedMessage, end, pMessageHeader, config); - else - result = -1; - break; + break; - case NFAPI_RSSI_INDICATION: - if (check_unpack_length(NFAPI_RSSI_INDICATION, unpackedBufLen)) - result = unpack_rssi_indication(&pReadPackedMessage, end, pMessageHeader, config); - else - result = -1; - break; + case NFAPI_RSSI_RESPONSE: + if (check_unpack_length(NFAPI_RSSI_RESPONSE, unpackedBufLen)) + result = unpack_rssi_response(&pReadPackedMessage, end, pMessageHeader, config); + else + result = -1; - case NFAPI_CELL_SEARCH_REQUEST: - if (check_unpack_length(NFAPI_CELL_SEARCH_REQUEST, unpackedBufLen)) - result = unpack_cell_search_request(&pReadPackedMessage, end, pMessageHeader, config); - else - result = -1; - break; + break; - case NFAPI_CELL_SEARCH_RESPONSE: - if (check_unpack_length(NFAPI_CELL_SEARCH_RESPONSE, unpackedBufLen)) - result = unpack_cell_search_response(&pReadPackedMessage, end, pMessageHeader, config); - else - result = -1; - break; + case NFAPI_RSSI_INDICATION: + if (check_unpack_length(NFAPI_RSSI_INDICATION, unpackedBufLen)) + result = unpack_rssi_indication(&pReadPackedMessage, end, pMessageHeader, config); + else + result = -1; - case NFAPI_CELL_SEARCH_INDICATION: - if (check_unpack_length(NFAPI_CELL_SEARCH_INDICATION, unpackedBufLen)) - result = unpack_cell_search_indication(&pReadPackedMessage, end, pMessageHeader, config); - else - result = -1; - break; + break; - case NFAPI_BROADCAST_DETECT_REQUEST: - if (check_unpack_length(NFAPI_BROADCAST_DETECT_REQUEST, unpackedBufLen)) - result = unpack_broadcast_detect_request(&pReadPackedMessage, end, pMessageHeader, config); - else - result = -1; - break; + case NFAPI_CELL_SEARCH_REQUEST: + if (check_unpack_length(NFAPI_CELL_SEARCH_REQUEST, unpackedBufLen)) + result = unpack_cell_search_request(&pReadPackedMessage, end, pMessageHeader, config); + else + result = -1; - case NFAPI_BROADCAST_DETECT_RESPONSE: - if (check_unpack_length(NFAPI_BROADCAST_DETECT_RESPONSE, unpackedBufLen)) - result = unpack_broadcast_detect_response(&pReadPackedMessage, end, pMessageHeader, config); - else - result = -1; - break; + break; - case NFAPI_BROADCAST_DETECT_INDICATION: - if (check_unpack_length(NFAPI_BROADCAST_DETECT_INDICATION, unpackedBufLen)) - result = unpack_broadcast_detect_indication(&pReadPackedMessage, end, pMessageHeader, config); - else - result = -1; - break; + case NFAPI_CELL_SEARCH_RESPONSE: + if (check_unpack_length(NFAPI_CELL_SEARCH_RESPONSE, unpackedBufLen)) + result = unpack_cell_search_response(&pReadPackedMessage, end, pMessageHeader, config); + else + result = -1; - case NFAPI_SYSTEM_INFORMATION_SCHEDULE_REQUEST: - if (check_unpack_length(NFAPI_SYSTEM_INFORMATION_SCHEDULE_REQUEST, unpackedBufLen)) - result = unpack_system_information_schedule_request(&pReadPackedMessage, end, pMessageHeader, config); - else - result = -1; - break; - - case NFAPI_SYSTEM_INFORMATION_SCHEDULE_RESPONSE: - if (check_unpack_length(NFAPI_SYSTEM_INFORMATION_SCHEDULE_RESPONSE, unpackedBufLen)) - result = unpack_system_information_schedule_response(&pReadPackedMessage, end, pMessageHeader, config); - else - result = -1; - break; + break; - case NFAPI_SYSTEM_INFORMATION_SCHEDULE_INDICATION: - if (check_unpack_length(NFAPI_SYSTEM_INFORMATION_SCHEDULE_INDICATION, unpackedBufLen)) - result = unpack_system_information_schedule_indication(&pReadPackedMessage, end, pMessageHeader, config); - else - result = -1; - break; + case NFAPI_CELL_SEARCH_INDICATION: + if (check_unpack_length(NFAPI_CELL_SEARCH_INDICATION, unpackedBufLen)) + result = unpack_cell_search_indication(&pReadPackedMessage, end, pMessageHeader, config); + else + result = -1; - case NFAPI_SYSTEM_INFORMATION_REQUEST: - if (check_unpack_length(NFAPI_SYSTEM_INFORMATION_REQUEST, unpackedBufLen)) - result = unpack_system_information_request(&pReadPackedMessage, end, pMessageHeader, config); - else - result = -1; - break; + break; - case NFAPI_SYSTEM_INFORMATION_RESPONSE: - if (check_unpack_length(NFAPI_SYSTEM_INFORMATION_RESPONSE, unpackedBufLen)) - result = unpack_system_information_response(&pReadPackedMessage, end, pMessageHeader, config); - else - result = -1; - break; + case NFAPI_BROADCAST_DETECT_REQUEST: + if (check_unpack_length(NFAPI_BROADCAST_DETECT_REQUEST, unpackedBufLen)) + result = unpack_broadcast_detect_request(&pReadPackedMessage, end, pMessageHeader, config); + else + result = -1; - case NFAPI_SYSTEM_INFORMATION_INDICATION: - if (check_unpack_length(NFAPI_SYSTEM_INFORMATION_INDICATION, unpackedBufLen)) - result = unpack_system_information_indication(&pReadPackedMessage, end, pMessageHeader, config); - else - result = -1; - break; + break; - case NFAPI_NMM_STOP_REQUEST: - if (check_unpack_length(NFAPI_NMM_STOP_REQUEST, unpackedBufLen)) - result = unpack_nmm_stop_request(&pReadPackedMessage, end, pMessageHeader, config); - else - result = -1; - break; + case NFAPI_BROADCAST_DETECT_RESPONSE: + if (check_unpack_length(NFAPI_BROADCAST_DETECT_RESPONSE, unpackedBufLen)) + result = unpack_broadcast_detect_response(&pReadPackedMessage, end, pMessageHeader, config); + else + result = -1; - case NFAPI_NMM_STOP_RESPONSE: - if (check_unpack_length(NFAPI_NMM_STOP_RESPONSE, unpackedBufLen)) - result = unpack_nmm_stop_response(&pReadPackedMessage, end , pMessageHeader, config); - else - result = -1; - break; + break; - default: - if(pMessageHeader->message_id >= NFAPI_VENDOR_EXT_MSG_MIN && - pMessageHeader->message_id <= NFAPI_VENDOR_EXT_MSG_MAX) - { - if(config && config->unpack_p4_p5_vendor_extension) - { - result = (config->unpack_p4_p5_vendor_extension)(pMessageHeader, &pReadPackedMessage, end, config); - } - else - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s VE NFAPI message ID %d. No ve decoder provided\n", __FUNCTION__, pMessageHeader->message_id); - } - } - else - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s NFAPI Unknown P4 message ID %d\n", __FUNCTION__, pMessageHeader->message_id); - } - break; - } + case NFAPI_BROADCAST_DETECT_INDICATION: + if (check_unpack_length(NFAPI_BROADCAST_DETECT_INDICATION, unpackedBufLen)) + result = unpack_broadcast_detect_indication(&pReadPackedMessage, end, pMessageHeader, config); + else + result = -1; - if(result == 0) - return -1; + break; - return result; + case NFAPI_SYSTEM_INFORMATION_SCHEDULE_REQUEST: + if (check_unpack_length(NFAPI_SYSTEM_INFORMATION_SCHEDULE_REQUEST, unpackedBufLen)) + result = unpack_system_information_schedule_request(&pReadPackedMessage, end, pMessageHeader, config); + else + result = -1; + + break; + + case NFAPI_SYSTEM_INFORMATION_SCHEDULE_RESPONSE: + if (check_unpack_length(NFAPI_SYSTEM_INFORMATION_SCHEDULE_RESPONSE, unpackedBufLen)) + result = unpack_system_information_schedule_response(&pReadPackedMessage, end, pMessageHeader, config); + else + result = -1; + + break; + + case NFAPI_SYSTEM_INFORMATION_SCHEDULE_INDICATION: + if (check_unpack_length(NFAPI_SYSTEM_INFORMATION_SCHEDULE_INDICATION, unpackedBufLen)) + result = unpack_system_information_schedule_indication(&pReadPackedMessage, end, pMessageHeader, config); + else + result = -1; + + break; + + case NFAPI_SYSTEM_INFORMATION_REQUEST: + if (check_unpack_length(NFAPI_SYSTEM_INFORMATION_REQUEST, unpackedBufLen)) + result = unpack_system_information_request(&pReadPackedMessage, end, pMessageHeader, config); + else + result = -1; + + break; + + case NFAPI_SYSTEM_INFORMATION_RESPONSE: + if (check_unpack_length(NFAPI_SYSTEM_INFORMATION_RESPONSE, unpackedBufLen)) + result = unpack_system_information_response(&pReadPackedMessage, end, pMessageHeader, config); + else + result = -1; + + break; + + case NFAPI_SYSTEM_INFORMATION_INDICATION: + if (check_unpack_length(NFAPI_SYSTEM_INFORMATION_INDICATION, unpackedBufLen)) + result = unpack_system_information_indication(&pReadPackedMessage, end, pMessageHeader, config); + else + result = -1; + + break; + + case NFAPI_NMM_STOP_REQUEST: + if (check_unpack_length(NFAPI_NMM_STOP_REQUEST, unpackedBufLen)) + result = unpack_nmm_stop_request(&pReadPackedMessage, end, pMessageHeader, config); + else + result = -1; + + break; + + case NFAPI_NMM_STOP_RESPONSE: + if (check_unpack_length(NFAPI_NMM_STOP_RESPONSE, unpackedBufLen)) + result = unpack_nmm_stop_response(&pReadPackedMessage, end, pMessageHeader, config); + else + result = -1; + + break; + + default: + if(pMessageHeader->message_id >= NFAPI_VENDOR_EXT_MSG_MIN && + pMessageHeader->message_id <= NFAPI_VENDOR_EXT_MSG_MAX) { + if(config && config->unpack_p4_p5_vendor_extension) { + result = (config->unpack_p4_p5_vendor_extension)(pMessageHeader, &pReadPackedMessage, end, config); + } else { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s VE NFAPI message ID %d. No ve decoder provided\n", __FUNCTION__, pMessageHeader->message_id); + } + } else { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s NFAPI Unknown P4 message ID %d\n", __FUNCTION__, pMessageHeader->message_id); + } + + break; + } + + if(result == 0) + return -1; + + return result; } diff --git a/nfapi/open-nFAPI/nfapi/src/nfapi_p5.c b/nfapi/open-nFAPI/nfapi/src/nfapi_p5.c index 8aea9f590c..0c0a8750bc 100644 --- a/nfapi/open-nFAPI/nfapi/src/nfapi_p5.c +++ b/nfapi/open-nFAPI/nfapi/src/nfapi_p5.c @@ -1,2785 +1,2368 @@ -/* - * 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. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include "nfapi_nr_interface.h" -#include "nfapi_nr_interface_scf.h" -#include - - -// Pack routines -//TODO: Add pacl/unpack fns for uint32 and uint64 -static uint8_t pack_nr_pnf_param_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t* end, nfapi_p4_p5_codec_config_t* config) -{ - nfapi_nr_pnf_param_request_t* request = (nfapi_nr_pnf_param_request_t*)msg; - return pack_vendor_extension_tlv(request->vendor_extension, ppWritePackedMsg, end, config); -} - -static uint8_t pack_pnf_param_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t* end, nfapi_p4_p5_codec_config_t* config) -{ - nfapi_pnf_param_request_t* request = (nfapi_pnf_param_request_t*)msg; - return pack_vendor_extension_tlv(request->vendor_extension, ppWritePackedMsg, end, config); -} - -static uint8_t pack_pnf_param_general_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_pnf_param_general_t* value = (nfapi_pnf_param_general_t*)tlv; - - return ( push8(value->nfapi_sync_mode, ppWritePackedMsg, end) && - push8(value->location_mode, ppWritePackedMsg, end) && - push16(value->location_coordinates_length, ppWritePackedMsg, end) && - pusharray8(value->location_coordinates, NFAPI_PNF_PARAM_GENERAL_LOCATION_LENGTH, value->location_coordinates_length, ppWritePackedMsg, end) && - push32(value->dl_config_timing, ppWritePackedMsg, end) && - push32(value->tx_timing, ppWritePackedMsg, end) && - push32(value->ul_config_timing, ppWritePackedMsg, end) && - push32(value->hi_dci0_timing, ppWritePackedMsg, end) && - push16(value->maximum_number_phys, ppWritePackedMsg, end) && - push16(value->maximum_total_bandwidth, ppWritePackedMsg, end) && - push8(value->maximum_total_number_dl_layers, ppWritePackedMsg, end) && - push8(value->maximum_total_number_ul_layers, ppWritePackedMsg, end) && - push8(value->shared_bands, ppWritePackedMsg, end) && - push8(value->shared_pa, ppWritePackedMsg, end) && - pushs16(value->maximum_total_power, ppWritePackedMsg, end) && - pusharray8(value->oui, NFAPI_PNF_PARAM_GENERAL_OUI_LENGTH, NFAPI_PNF_PARAM_GENERAL_OUI_LENGTH, ppWritePackedMsg, end)); -} - -static uint8_t pack_rf_config_info(void* elem, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_rf_config_info_t* rf = (nfapi_rf_config_info_t*)elem; - - return (push16(rf->rf_config_index, ppWritePackedMsg, end)); -} - - -static uint8_t pack_pnf_phy_info(void* elem, uint8_t **ppWritePackedMsg, uint8_t* end) -{ - nfapi_pnf_phy_info_t* phy = (nfapi_pnf_phy_info_t*)elem; - - return ( push16(phy->phy_config_index, ppWritePackedMsg, end) && - push16(phy->number_of_rfs, ppWritePackedMsg, end) && - packarray(phy->rf_config, sizeof(nfapi_rf_config_info_t), NFAPI_MAX_PNF_PHY_RF_CONFIG, phy->number_of_rfs, ppWritePackedMsg, end, &pack_rf_config_info) && - push16(phy->number_of_rf_exclusions, ppWritePackedMsg, end) && - packarray(phy->excluded_rf_config, sizeof(nfapi_rf_config_info_t), NFAPI_MAX_PNF_PHY_RF_CONFIG, phy->number_of_rf_exclusions, ppWritePackedMsg, end, &pack_rf_config_info) && - push16(phy->downlink_channel_bandwidth_supported, ppWritePackedMsg, end) && - push16(phy->uplink_channel_bandwidth_supported, ppWritePackedMsg, end) && - push8(phy->number_of_dl_layers_supported, ppWritePackedMsg, end) && - push8(phy->number_of_ul_layers_supported, ppWritePackedMsg, end) && - push16(phy->maximum_3gpp_release_supported, ppWritePackedMsg, end) && - push8(phy->nmm_modes_supported, ppWritePackedMsg, end)); - - -} - -static uint8_t pack_pnf_phy_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_pnf_phy_t* value = (nfapi_pnf_phy_t*)tlv; - - return ( push16(value->number_of_phys, ppWritePackedMsg, end) && - packarray(value->phy, sizeof(nfapi_pnf_phy_info_t), NFAPI_MAX_PNF_PHY, value->number_of_phys, ppWritePackedMsg, end, &pack_pnf_phy_info)); -} - -static uint8_t pack_pnf_rf_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_pnf_rf_t* value = (nfapi_pnf_rf_t*)tlv; - uint16_t rf_index = 0; - - if(push16(value->number_of_rfs, ppWritePackedMsg, end) == 0) - return 0; - - for(; rf_index < value->number_of_rfs; ++rf_index) - { - if( !(push16(value->rf[rf_index].rf_config_index, ppWritePackedMsg, end) && - push16(value->rf[rf_index].band, ppWritePackedMsg, end) && - pushs16(value->rf[rf_index].maximum_transmit_power, ppWritePackedMsg, end) && - pushs16(value->rf[rf_index].minimum_transmit_power, ppWritePackedMsg, end) && - push8(value->rf[rf_index].number_of_antennas_suppported, ppWritePackedMsg, end) && - push32(value->rf[rf_index].minimum_downlink_frequency, ppWritePackedMsg, end) && - push32(value->rf[rf_index].maximum_downlink_frequency, ppWritePackedMsg, end) && - push32(value->rf[rf_index].minimum_uplink_frequency, ppWritePackedMsg, end) && - push32(value->rf[rf_index].maximum_uplink_frequency, ppWritePackedMsg, end))) - return 0; - } - - return 1; -} -static uint8_t pack_pnf_phy_rel10_info(void* elem, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_pnf_phy_rel10_info_t* phy = (nfapi_pnf_phy_rel10_info_t*)elem; - - return(push16(phy->phy_config_index, ppWritePackedMsg, end) && - push16(phy->transmission_mode_7_supported, ppWritePackedMsg, end) && - push16(phy->transmission_mode_8_supported, ppWritePackedMsg, end) && - push16(phy->two_antenna_ports_for_pucch, ppWritePackedMsg, end) && - push16(phy->transmission_mode_9_supported, ppWritePackedMsg, end) && - push16(phy->simultaneous_pucch_pusch, ppWritePackedMsg, end) && - push16(phy->four_layer_tx_with_tm3_and_tm4, ppWritePackedMsg, end)); -} - -static uint8_t pack_pnf_phy_rel10_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_pnf_phy_rel10_t* value = (nfapi_pnf_phy_rel10_t*)tlv; - - return (push16(value->number_of_phys, ppWritePackedMsg, end) && - packarray(value->phy, sizeof(nfapi_pnf_phy_rel10_info_t), NFAPI_MAX_PNF_PHY, value->number_of_phys, ppWritePackedMsg, end, &pack_pnf_phy_rel10_info)); - -} - -static uint8_t pack_pnf_phy_rel11_info(void* elem, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_pnf_phy_rel11_info_t* phy = (nfapi_pnf_phy_rel11_info_t*)elem; - - return (push16(phy->phy_config_index, ppWritePackedMsg, end) && - push16(phy->edpcch_supported, ppWritePackedMsg, end) && - push16(phy->multi_ack_csi_reporting, ppWritePackedMsg, end) && - push16(phy->pucch_tx_diversity, ppWritePackedMsg, end) && - push16(phy->ul_comp_supported, ppWritePackedMsg, end) && - push16(phy->transmission_mode_5_supported, ppWritePackedMsg, end )); -} -static uint8_t pack_pnf_phy_rel11_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_pnf_phy_rel11_t* value = (nfapi_pnf_phy_rel11_t*)tlv; - - return (push16(value->number_of_phys, ppWritePackedMsg, end) && - packarray(value->phy, sizeof(nfapi_pnf_phy_rel11_info_t), NFAPI_MAX_PNF_PHY, value->number_of_phys, ppWritePackedMsg, end, &pack_pnf_phy_rel11_info)); -} -static uint8_t pack_pnf_phy_rel12_info(void* elem, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_pnf_phy_rel12_info_t* phy = (nfapi_pnf_phy_rel12_info_t*)elem; - - return( push16(phy->phy_config_index, ppWritePackedMsg, end) && - push16(phy->csi_subframe_set, ppWritePackedMsg, end) && - push16(phy->enhanced_4tx_codebook, ppWritePackedMsg, end) && - push16(phy->drs_supported, ppWritePackedMsg, end) && - push16(phy->ul_64qam_supported, ppWritePackedMsg, end) && - push16(phy->transmission_mode_10_supported, ppWritePackedMsg, end) && - push16(phy->alternative_bts_indices, ppWritePackedMsg, end)); -} -static uint8_t pack_pnf_phy_rel12_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_pnf_phy_rel12_t* value = (nfapi_pnf_phy_rel12_t*)tlv; - - return (push16(value->number_of_phys, ppWritePackedMsg, end) && - packarray(value->phy, sizeof(nfapi_pnf_phy_rel12_info_t), NFAPI_MAX_PNF_PHY, value->number_of_phys, ppWritePackedMsg, end, &pack_pnf_phy_rel12_info)); - -} - -static uint8_t pack_pnf_phy_rel13_info(void* elem, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_pnf_phy_rel13_info_t* phy = (nfapi_pnf_phy_rel13_info_t*)elem; - - return( push16(phy->phy_config_index, ppWritePackedMsg, end) && - push16(phy->pucch_format4_supported, ppWritePackedMsg, end) && - push16(phy->pucch_format5_supported, ppWritePackedMsg, end) && - push16(phy->more_than_5_ca_support, ppWritePackedMsg, end) && - push16(phy->laa_supported, ppWritePackedMsg, end) && - push16(phy->laa_ending_in_dwpts_supported, ppWritePackedMsg, end) && - push16(phy->laa_starting_in_second_slot_supported, ppWritePackedMsg, end) && - push16(phy->beamforming_supported, ppWritePackedMsg, end) && - push16(phy->csi_rs_enhancement_supported, ppWritePackedMsg, end) && - push16(phy->drms_enhancement_supported, ppWritePackedMsg, end) && - push16(phy->srs_enhancement_supported, ppWritePackedMsg, end) ); -} - -static uint8_t pack_pnf_phy_rel13_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_pnf_phy_rel13_t* value = (nfapi_pnf_phy_rel13_t*)tlv; - - return (push16(value->number_of_phys, ppWritePackedMsg, end) && - packarray(value->phy, sizeof(nfapi_pnf_phy_rel13_info_t), NFAPI_MAX_PNF_PHY, value->number_of_phys, ppWritePackedMsg, end, &pack_pnf_phy_rel13_info)); -} - -static uint8_t pack_pnf_phy_rel13_nb_iot_info(void* elem, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_pnf_phy_rel13_nb_iot_info_t* phy = (nfapi_pnf_phy_rel13_nb_iot_info_t*)elem; - - return( push16(phy->phy_config_index, ppWritePackedMsg, end) && - push16(phy->number_of_rfs, ppWritePackedMsg, end) && - packarray(phy->rf_config, sizeof(nfapi_rf_config_info_t), NFAPI_MAX_PNF_PHY_RF_CONFIG, phy->number_of_rfs, ppWritePackedMsg, end, &pack_rf_config_info) && - push16(phy->number_of_rf_exclusions, ppWritePackedMsg, end) && - packarray(phy->excluded_rf_config, sizeof(nfapi_rf_config_info_t), NFAPI_MAX_PNF_PHY_RF_CONFIG, phy->number_of_rf_exclusions, ppWritePackedMsg, end, &pack_rf_config_info) && - push8(phy->number_of_dl_layers_supported, ppWritePackedMsg, end) && - push8(phy->number_of_ul_layers_supported, ppWritePackedMsg, end) && - push16(phy->maximum_3gpp_release_supported, ppWritePackedMsg, end) && - push8(phy->nmm_modes_supported, ppWritePackedMsg, end)); -} - -static uint8_t pack_pnf_phy_rel13_nb_iot_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_pnf_phy_rel13_nb_iot_t* value = (nfapi_pnf_phy_rel13_nb_iot_t*)tlv; - - return (push16(value->number_of_phys, ppWritePackedMsg, end) && - packarray(value->phy, sizeof(nfapi_pnf_phy_rel13_nb_iot_info_t), NFAPI_MAX_PNF_PHY, value->number_of_phys, ppWritePackedMsg, end, &pack_pnf_phy_rel13_nb_iot_info)); -} -/* -static uint8_t pack_nr_pnf_param_response(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t* config) -{ - nfapi_nr_pnf_param_response_t *pNfapiMsg = (nfapi_nr_pnf_param_response_t*)msg; - - return (push32(pNfapiMsg->error_code, ppWritePackedMsg, end) && - pack_tlv(NFAPI_PNF_PARAM_GENERAL_TAG, &pNfapiMsg->pnf_param_general, ppWritePackedMsg, end, &pack_pnf_param_general_value) && - pack_tlv(NFAPI_PNF_PHY_TAG, &pNfapiMsg->pnf_phy, ppWritePackedMsg, end, &pack_pnf_phy_value) && - pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); -} -*/ -static uint8_t pack_nr_pnf_param_response(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t* config) -{ - nfapi_nr_pnf_param_response_t *pNfapiMsg = (nfapi_nr_pnf_param_response_t*)msg; - - return (push32(pNfapiMsg->error_code, ppWritePackedMsg, end) && - pack_tlv(NFAPI_PNF_PARAM_GENERAL_TAG, &pNfapiMsg->pnf_param_general, ppWritePackedMsg, end, &pack_pnf_param_general_value) && - pack_tlv(NFAPI_PNF_PHY_TAG, &pNfapiMsg->pnf_phy, ppWritePackedMsg, end, &pack_pnf_phy_value) && - pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); -} - - -static uint8_t pack_pnf_param_response(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t* config) -{ - nfapi_pnf_param_response_t *pNfapiMsg = (nfapi_pnf_param_response_t*)msg; - - return (push32(pNfapiMsg->error_code, ppWritePackedMsg, end) && - pack_tlv(NFAPI_PNF_PARAM_GENERAL_TAG, &pNfapiMsg->pnf_param_general, ppWritePackedMsg, end, &pack_pnf_param_general_value) && - pack_tlv(NFAPI_PNF_PHY_TAG, &pNfapiMsg->pnf_phy, ppWritePackedMsg, end, &pack_pnf_phy_value) && - pack_tlv(NFAPI_PNF_RF_TAG, &pNfapiMsg->pnf_rf, ppWritePackedMsg, end, &pack_pnf_rf_value) && - pack_tlv(NFAPI_PNF_PHY_REL10_TAG, &pNfapiMsg->pnf_phy_rel10, ppWritePackedMsg, end, &pack_pnf_phy_rel10_value) && - pack_tlv(NFAPI_PNF_PHY_REL11_TAG, &pNfapiMsg->pnf_phy_rel11, ppWritePackedMsg, end, &pack_pnf_phy_rel11_value) && - pack_tlv(NFAPI_PNF_PHY_REL12_TAG, &pNfapiMsg->pnf_phy_rel12, ppWritePackedMsg, end, &pack_pnf_phy_rel12_value) && - pack_tlv(NFAPI_PNF_PHY_REL13_TAG, &pNfapiMsg->pnf_phy_rel13, ppWritePackedMsg, end, &pack_pnf_phy_rel13_value) && - pack_tlv(NFAPI_PNF_PHY_REL13_NB_IOT_TAG, &pNfapiMsg->pnf_phy_rel13_nb_iot, ppWritePackedMsg, end, &pack_pnf_phy_rel13_nb_iot_value) && - pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); -} - - -static uint8_t pack_phy_rf_config_info(void* elem, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_phy_rf_config_info_t* rf = (nfapi_phy_rf_config_info_t*)elem; - - return (push16(rf->phy_id, ppWritePackedMsg, end) && - push16(rf->phy_config_index, ppWritePackedMsg, end) && - push16(rf->rf_config_index, ppWritePackedMsg, end)); -} - - -static uint8_t pack_pnf_phy_rf_config_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_pnf_phy_rf_config_t *value = (nfapi_pnf_phy_rf_config_t*)tlv; - - return(push16(value->number_phy_rf_config_info, ppWritePackedMsg, end) && - packarray(value->phy_rf_config, sizeof(nfapi_phy_rf_config_info_t), NFAPI_MAX_PHY_RF_INSTANCES, value->number_phy_rf_config_info, ppWritePackedMsg, end, &pack_phy_rf_config_info)); - -} - -static uint8_t pack_nr_pnf_config_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t* config) -{ - nfapi_nr_pnf_config_request_t *pNfapiMsg = (nfapi_nr_pnf_config_request_t*)msg; - return (pack_tlv(NFAPI_PNF_PHY_RF_TAG, &pNfapiMsg->pnf_phy_rf_config, ppWritePackedMsg, end, &pack_pnf_phy_rf_config_value) && - //push8(pNfapiMsg->num_tlvs,ppWritePackedMsg,end) && - pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end , config)); -} - -static uint8_t pack_pnf_config_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t* config) -{ - nfapi_pnf_config_request_t *pNfapiMsg = (nfapi_pnf_config_request_t*)msg; - return (pack_tlv(NFAPI_PNF_PHY_RF_TAG, &pNfapiMsg->pnf_phy_rf_config, ppWritePackedMsg, end, &pack_pnf_phy_rf_config_value) && - push8(pNfapiMsg->num_tlvs,ppWritePackedMsg,end) && - pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end , config)); -} - - -static uint8_t pack_nr_pnf_config_response(void *msg, uint8_t **ppWritePackedMsg, uint8_t* end, nfapi_p4_p5_codec_config_t* config) -{ - nfapi_nr_pnf_config_response_t *pNfapiMsg = (nfapi_nr_pnf_config_response_t*)msg; - - return ( push32(pNfapiMsg->error_code, ppWritePackedMsg, end) && - pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); -} - - -static uint8_t pack_pnf_config_response(void *msg, uint8_t **ppWritePackedMsg, uint8_t* end, nfapi_p4_p5_codec_config_t* config) -{ - nfapi_pnf_config_response_t *pNfapiMsg = (nfapi_pnf_config_response_t*)msg; - - return ( push32(pNfapiMsg->error_code, ppWritePackedMsg, end) && - pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); -} - -static uint8_t pack_nr_pnf_start_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t* end, nfapi_p4_p5_codec_config_t* config) -{ - nfapi_nr_pnf_start_request_t *pNfapiMsg = (nfapi_nr_pnf_start_request_t*)msg; - return ( pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); -} - -static uint8_t pack_pnf_start_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t* end, nfapi_p4_p5_codec_config_t* config) -{ - nfapi_pnf_start_request_t *pNfapiMsg = (nfapi_pnf_start_request_t*)msg; - return ( pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); -} - - -static uint8_t pack_nr_pnf_start_response(void *msg, uint8_t **ppWritePackedMsg, uint8_t* end, nfapi_p4_p5_codec_config_t* config) -{ - nfapi_nr_pnf_start_response_t *pNfapiMsg = (nfapi_nr_pnf_start_response_t*)msg; - - return( push32(pNfapiMsg->error_code, ppWritePackedMsg, end) && - pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); -} - - -static uint8_t pack_pnf_start_response(void *msg, uint8_t **ppWritePackedMsg, uint8_t* end, nfapi_p4_p5_codec_config_t* config) -{ - nfapi_pnf_start_response_t *pNfapiMsg = (nfapi_pnf_start_response_t*)msg; - - return( push32(pNfapiMsg->error_code, ppWritePackedMsg, end) && - pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); -} - - -static uint8_t pack_nr_pnf_stop_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t* end, nfapi_p4_p5_codec_config_t* config) -{ - nfapi_nr_pnf_stop_request_t *pNfapiMsg = (nfapi_nr_pnf_stop_request_t*)msg; - return ( pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config) ); -} - - - -static uint8_t pack_pnf_stop_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t* end, nfapi_p4_p5_codec_config_t* config) -{ - nfapi_pnf_stop_request_t *pNfapiMsg = (nfapi_pnf_stop_request_t*)msg; - return ( pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config) ); -} - - -static uint8_t pack_nr_pnf_stop_response(void *msg, uint8_t **ppWritePackedMsg, uint8_t* end, nfapi_p4_p5_codec_config_t* config) -{ - nfapi_nr_pnf_stop_response_t *pNfapiMsg = (nfapi_nr_pnf_stop_response_t*)msg; - - return ( push32(pNfapiMsg->error_code, ppWritePackedMsg, end) && - pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); -} - - -static uint8_t pack_pnf_stop_response(void *msg, uint8_t **ppWritePackedMsg, uint8_t* end, nfapi_p4_p5_codec_config_t* config) -{ - nfapi_pnf_stop_response_t *pNfapiMsg = (nfapi_pnf_stop_response_t*)msg; - - return ( push32(pNfapiMsg->error_code, ppWritePackedMsg, end) && - pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); -} - -static uint8_t pack_nr_param_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t* end, nfapi_p4_p5_codec_config_t* config) -{ - nfapi_nr_param_request_scf_t *pNfapiMsg = (nfapi_nr_param_request_scf_t*)msg; - return (pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); -} - -static uint8_t pack_param_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t* end, nfapi_p4_p5_codec_config_t* config) -{ - nfapi_param_request_t *pNfapiMsg = (nfapi_param_request_t*)msg; - return (pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); -} - -static uint8_t pack_uint32_tlv_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_uint32_tlv_t* value = (nfapi_uint32_tlv_t*)tlv; - return push32(value->value, ppWritePackedMsg, end); -} - -static uint8_t unpack_uint32_tlv_value(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_uint32_tlv_t* value = (nfapi_uint32_tlv_t*)tlv; - return pull32(ppReadPackedMsg, &value->value, end); -} - - -static uint8_t pack_uint16_tlv_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_uint16_tlv_t* value = (nfapi_uint16_tlv_t*)tlv; - return push16(value->value, ppWritePackedMsg, end); -} - -static uint8_t unpack_uint16_tlv_value(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_uint16_tlv_t* value = (nfapi_uint16_tlv_t*)tlv; - return pull16(ppReadPackedMsg, &value->value, end); -} - -static uint8_t pack_int16_tlv_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_int16_tlv_t* value = (nfapi_int16_tlv_t*)tlv; - return pushs16(value->value, ppWritePackedMsg, end); -} - -static uint8_t unpack_int16_tlv_value(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_int16_tlv_t* value = (nfapi_int16_tlv_t*)tlv; - return pulls16(ppReadPackedMsg, &value->value, end); -} - -static uint8_t pack_uint8_tlv_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_uint8_tlv_t* value = (nfapi_uint8_tlv_t*)tlv; - return push8(value->value, ppWritePackedMsg, end); -} -static uint8_t unpack_uint8_tlv_value(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_uint8_tlv_t* value = (nfapi_uint8_tlv_t*)tlv; - return pull8(ppReadPackedMsg, &value->value, end); -} - -static uint8_t pack_ipv4_address_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_ipv4_address_t* value = (nfapi_ipv4_address_t*)tlv; - return pusharray8(value->address, NFAPI_IPV4_ADDRESS_LENGTH, NFAPI_IPV4_ADDRESS_LENGTH, ppWritePackedMsg, end); -} -static uint8_t unpack_ipv4_address_value(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_ipv4_address_t* value = (nfapi_ipv4_address_t*)tlv; - return pullarray8(ppReadPackedMsg, value->address, NFAPI_IPV4_ADDRESS_LENGTH, NFAPI_IPV4_ADDRESS_LENGTH, end); -} -static uint8_t pack_ipv6_address_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_ipv6_address_t* value = (nfapi_ipv6_address_t*)tlv; - return pusharray8(value->address, NFAPI_IPV6_ADDRESS_LENGTH, NFAPI_IPV6_ADDRESS_LENGTH, ppWritePackedMsg, end); -} -static uint8_t unpack_ipv6_address_value(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_ipv4_address_t* value = (nfapi_ipv4_address_t*)tlv; - return pullarray8(ppReadPackedMsg, value->address, NFAPI_IPV6_ADDRESS_LENGTH, NFAPI_IPV6_ADDRESS_LENGTH, end); -} - -static uint8_t pack_rf_bands_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_rf_bands_t* value = (nfapi_rf_bands_t*)tlv; - - return ( push16(value->number_rf_bands, ppWritePackedMsg, end) && - pusharray16(value->rf_band, NFAPI_MAX_NUM_RF_BANDS, value->number_rf_bands, ppWritePackedMsg, end)); -} -static uint8_t unpack_rf_bands_value(void* tlv, uint8_t **ppReadPackedMsg, uint8_t* end) -{ - nfapi_rf_bands_t* value = (nfapi_rf_bands_t*)tlv; - - return ( pull16(ppReadPackedMsg, &value->number_rf_bands, end) && - pullarray16(ppReadPackedMsg, value->rf_band, NFAPI_MAX_NUM_RF_BANDS, value->number_rf_bands, end)); -} - -static uint8_t pack_nmm_frequency_bands_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_nmm_frequency_bands_t* value = (nfapi_nmm_frequency_bands_t*)tlv; - - return( push16(value->number_of_rf_bands, ppWritePackedMsg, end) && - pusharray16(value->bands, NFAPI_MAX_NMM_FREQUENCY_BANDS, value->number_of_rf_bands, ppWritePackedMsg, end)); -} -static uint8_t unpack_nmm_frequency_bands_value(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_nmm_frequency_bands_t* value = (nfapi_nmm_frequency_bands_t*)tlv; - - return ( pull16(ppReadPackedMsg, &value->number_of_rf_bands, end) && - pullarray16(ppReadPackedMsg, value->bands, NFAPI_MAX_NMM_FREQUENCY_BANDS, value->number_of_rf_bands, end)); -} -static uint8_t pack_embms_mbsfn_config_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_embms_mbsfn_config_t* value = (nfapi_embms_mbsfn_config_t*)tlv; - - return ( push16(value->num_mbsfn_config, ppWritePackedMsg, end) && - pusharray16(value->radioframe_allocation_period, 8,value->num_mbsfn_config ,ppWritePackedMsg, end) && - pusharray16(value->radioframe_allocation_offset, 8,value->num_mbsfn_config ,ppWritePackedMsg, end) && - pusharray8(value->fourframes_flag, 8,value->num_mbsfn_config,ppWritePackedMsg, end) && - pusharrays32(value->mbsfn_subframeconfig, 8, value->num_mbsfn_config, ppWritePackedMsg, end)); -} -// static uint8_t unpack_embms_mbsfn_config_value(void* tlv, uint8_t **ppReadPackedMsg, uint8_t* end) -// { -// nfapi_embms_mbsfn_config_t* value = (nfapi_embms_mbsfn_config_t*)tlv; - -// return ( pull16(ppReadPackedMsg, &value->num_mbsfn_config, end) && -// pull16(ppReadPackedMsg, &value->radioframe_allocation_period, end) && -// pull16(ppReadPackedMsg, &value->radioframe_allocation_offset, end) && -// pull8(ppReadPackedMsg, &value->fourframes_flag, end) && -// pullarrays32(ppReadPackedMsg, value->mbsfn_subframeconfig, 8, value->num_mbsfn_config, end)); -// } - -static uint8_t pack_param_response(void *msg, uint8_t **ppWritePackedMsg, uint8_t* end, nfapi_p4_p5_codec_config_t* config) -{ - nfapi_param_response_t *pNfapiMsg = (nfapi_param_response_t*)msg; - - return( push8(pNfapiMsg->error_code, ppWritePackedMsg, end) && - push8(pNfapiMsg->num_tlv, ppWritePackedMsg, end) && - pack_tlv(NFAPI_L1_STATUS_PHY_STATE_TAG, &pNfapiMsg->l1_status.phy_state, ppWritePackedMsg, end, &pack_uint16_tlv_value) && - - // Do we check the phy state and then just fill those sepecified, however - // we do not know the duplex mode, so just attempt to pack all and assumme - // that the callee has set the right tlvs - - pack_tlv(NFAPI_PHY_CAPABILITIES_DL_BANDWIDTH_SUPPORT_TAG, &(pNfapiMsg->phy_capabilities.dl_bandwidth_support), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_PHY_CAPABILITIES_UL_BANDWIDTH_SUPPORT_TAG, &(pNfapiMsg->phy_capabilities.ul_bandwidth_support), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_PHY_CAPABILITIES_DL_MODULATION_SUPPORT_TAG, &(pNfapiMsg->phy_capabilities.dl_modulation_support), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_PHY_CAPABILITIES_UL_MODULATION_SUPPORT_TAG, &(pNfapiMsg->phy_capabilities.ul_modulation_support), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_PHY_CAPABILITIES_PHY_ANTENNA_CAPABILITY_TAG, &(pNfapiMsg->phy_capabilities.phy_antenna_capability), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_PHY_CAPABILITIES_RELEASE_CAPABILITY_TAG, &(pNfapiMsg->phy_capabilities.release_capability), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_PHY_CAPABILITIES_MBSFN_CAPABILITY_TAG, &(pNfapiMsg->phy_capabilities.mbsfn_capability), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - // laa capability - - pack_tlv(NFAPI_SUBFRAME_CONFIG_DUPLEX_MODE_TAG, &(pNfapiMsg->subframe_config.duplex_mode), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_SUBFRAME_CONFIG_PCFICH_POWER_OFFSET_TAG, &(pNfapiMsg->subframe_config.pcfich_power_offset), ppWritePackedMsg, end, &pack_uint16_tlv_value)&& - pack_tlv(NFAPI_SUBFRAME_CONFIG_PB_TAG, &(pNfapiMsg->subframe_config.pb), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_SUBFRAME_CONFIG_DL_CYCLIC_PREFIX_TYPE_TAG, &(pNfapiMsg->subframe_config.dl_cyclic_prefix_type), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_SUBFRAME_CONFIG_UL_CYCLIC_PREFIX_TYPE_TAG, &(pNfapiMsg->subframe_config.ul_cyclic_prefix_type), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - - pack_tlv(NFAPI_RF_CONFIG_DL_CHANNEL_BANDWIDTH_TAG, &(pNfapiMsg->rf_config.dl_channel_bandwidth), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_RF_CONFIG_UL_CHANNEL_BANDWIDTH_TAG, &(pNfapiMsg->rf_config.ul_channel_bandwidth), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_RF_CONFIG_REFERENCE_SIGNAL_POWER_TAG, &(pNfapiMsg->rf_config.reference_signal_power), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_RF_CONFIG_TX_ANTENNA_PORTS_TAG, &(pNfapiMsg->rf_config.tx_antenna_ports), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_RF_CONFIG_RX_ANTENNA_PORTS_TAG, &(pNfapiMsg->rf_config.rx_antenna_ports), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - - pack_tlv(NFAPI_PHICH_CONFIG_PHICH_RESOURCE_TAG, &(pNfapiMsg->phich_config.phich_resource), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_PHICH_CONFIG_PHICH_DURATION_TAG, &(pNfapiMsg->phich_config.phich_duration), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_PHICH_CONFIG_PHICH_POWER_OFFSET_TAG, &(pNfapiMsg->phich_config.phich_power_offset), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - - pack_tlv(NFAPI_SCH_CONFIG_PRIMARY_SYNCHRONIZATION_SIGNAL_EPRE_EPRERS_TAG, &(pNfapiMsg->sch_config.primary_synchronization_signal_epre_eprers), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_SCH_CONFIG_SECONDARY_SYNCHRONIZATION_SIGNAL_EPRE_EPRERS_TAG, &(pNfapiMsg->sch_config.secondary_synchronization_signal_epre_eprers), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_SCH_CONFIG_PHYSICAL_CELL_ID_TAG, &(pNfapiMsg->sch_config.physical_cell_id), ppWritePackedMsg, end ,&pack_uint16_tlv_value) && - - pack_tlv(NFAPI_PRACH_CONFIG_CONFIGURATION_INDEX_TAG, &(pNfapiMsg->prach_config.configuration_index), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_PRACH_CONFIG_ROOT_SEQUENCE_INDEX_TAG, &(pNfapiMsg->prach_config.root_sequence_index), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_PRACH_CONFIG_ZERO_CORRELATION_ZONE_CONFIGURATION_TAG, &(pNfapiMsg->prach_config.zero_correlation_zone_configuration), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_PRACH_CONFIG_HIGH_SPEED_FLAG_TAG, &(pNfapiMsg->prach_config.high_speed_flag), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_PRACH_CONFIG_FREQUENCY_OFFSET_TAG, &(pNfapiMsg->prach_config.frequency_offset), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - - pack_tlv(NFAPI_PUSCH_CONFIG_HOPPING_MODE_TAG, &(pNfapiMsg->pusch_config.hopping_mode), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_PUSCH_CONFIG_HOPPING_OFFSET_TAG, &(pNfapiMsg->pusch_config.hopping_offset), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_PUSCH_CONFIG_NUMBER_OF_SUBBANDS_TAG, &(pNfapiMsg->pusch_config.number_of_subbands), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - - pack_tlv(NFAPI_PUCCH_CONFIG_DELTA_PUCCH_SHIFT_TAG, &(pNfapiMsg->pucch_config.delta_pucch_shift), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_PUCCH_CONFIG_N_CQI_RB_TAG, &(pNfapiMsg->pucch_config.n_cqi_rb), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_PUCCH_CONFIG_N_AN_CS_TAG, &(pNfapiMsg->pucch_config.n_an_cs), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_PUCCH_CONFIG_N1_PUCCH_AN_TAG, &(pNfapiMsg->pucch_config.n1_pucch_an), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - - pack_tlv(NFAPI_EMBMS_MBSFN_CONFIG_AREA_IDX_TAG, &(pNfapiMsg->embms_sib13_config.mbsfn_area_idx), ppWritePackedMsg, end, &pack_uint8_tlv_value) && - pack_tlv(NFAPI_EMBMS_MBSFN_CONFIG_AREA_IDR9_TAG, &(pNfapiMsg->embms_sib13_config.mbsfn_area_id_r9), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - - pack_tlv(NFAPI_EMBMS_MBSFN_CONFIG_TAG, &(pNfapiMsg->embms_mbsfn_config), ppWritePackedMsg, end, &pack_embms_mbsfn_config_value) && - - pack_tlv(NFAPI_FEMBMS_CONFIG_RADIOFRAME_ALLOCATION_PERIOD_TAG, &(pNfapiMsg->fembms_config.radioframe_allocation_period), ppWritePackedMsg, end, &pack_uint8_tlv_value) && - pack_tlv(NFAPI_FEMBMS_CONFIG_RADIOFRAME_ALLOCATION_OFFSET_TAG, &(pNfapiMsg->fembms_config.radioframe_allocation_offset), ppWritePackedMsg, end, &pack_uint8_tlv_value) && - pack_tlv(NFAPI_FEMBMS_CONFIG_NON_MBSFN_FLAG_TAG, &(pNfapiMsg->fembms_config.non_mbsfn_config_flag), ppWritePackedMsg, end, &pack_uint8_tlv_value) && - pack_tlv(NFAPI_FEMBMS_CONFIG_NON_MBSFN_SUBFRAMECONFIG_TAG, &(pNfapiMsg->fembms_config.non_mbsfn_subframeconfig), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - - - pack_tlv(NFAPI_SRS_CONFIG_BANDWIDTH_CONFIGURATION_TAG, &(pNfapiMsg->srs_config.bandwidth_configuration), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_SRS_CONFIG_MAX_UP_PTS_TAG, &(pNfapiMsg->srs_config.max_up_pts), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_SRS_CONFIG_SRS_SUBFRAME_CONFIGURATION_TAG, &(pNfapiMsg->srs_config.srs_subframe_configuration), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_SRS_CONFIG_SRS_ACKNACK_SRS_SIMULTANEOUS_TRANSMISSION_TAG, &(pNfapiMsg->srs_config.srs_acknack_srs_simultaneous_transmission), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - - pack_tlv(NFAPI_UPLINK_REFERENCE_SIGNAL_CONFIG_UPLINK_RS_HOPPING_TAG, &(pNfapiMsg->uplink_reference_signal_config.uplink_rs_hopping), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_UPLINK_REFERENCE_SIGNAL_CONFIG_GROUP_ASSIGNMENT_TAG, &(pNfapiMsg->uplink_reference_signal_config.group_assignment), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_UPLINK_REFERENCE_SIGNAL_CONFIG_CYCLIC_SHIFT_1_FOR_DRMS_TAG, &(pNfapiMsg->uplink_reference_signal_config.cyclic_shift_1_for_drms), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_TDD_FRAME_STRUCTURE_SUBFRAME_ASSIGNMENT_TAG, &(pNfapiMsg->tdd_frame_structure_config.subframe_assignment), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_TDD_FRAME_STRUCTURE_SPECIAL_SUBFRAME_PATTERNS_TAG, &(pNfapiMsg->tdd_frame_structure_config.special_subframe_patterns), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - - pack_tlv(NFAPI_L23_CONFIG_DATA_REPORT_MODE_TAG, &(pNfapiMsg->l23_config.data_report_mode), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_L23_CONFIG_SFNSF_TAG, &(pNfapiMsg->l23_config.sfnsf), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - - pack_tlv(NFAPI_NFAPI_P7_VNF_ADDRESS_IPV4_TAG, &(pNfapiMsg->nfapi_config.p7_vnf_address_ipv4), ppWritePackedMsg, end, &pack_ipv4_address_value) && - pack_tlv(NFAPI_NFAPI_P7_VNF_ADDRESS_IPV6_TAG, &(pNfapiMsg->nfapi_config.p7_vnf_address_ipv6), ppWritePackedMsg, end, &pack_ipv6_address_value) && - - pack_tlv(NFAPI_NFAPI_P7_VNF_PORT_TAG, &(pNfapiMsg->nfapi_config.p7_vnf_port), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - - pack_tlv(NFAPI_NFAPI_P7_PNF_ADDRESS_IPV4_TAG, &(pNfapiMsg->nfapi_config.p7_pnf_address_ipv4), ppWritePackedMsg, end, &pack_ipv4_address_value) && - pack_tlv(NFAPI_NFAPI_P7_PNF_ADDRESS_IPV6_TAG, &(pNfapiMsg->nfapi_config.p7_pnf_address_ipv6), ppWritePackedMsg, end, &pack_ipv6_address_value) && - - pack_tlv(NFAPI_NFAPI_P7_PNF_PORT_TAG, &(pNfapiMsg->nfapi_config.p7_pnf_port), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - - pack_tlv(NFAPI_NFAPI_DOWNLINK_UES_PER_SUBFRAME_TAG, &(pNfapiMsg->nfapi_config.dl_ue_per_sf), ppWritePackedMsg, end, &pack_uint8_tlv_value) && - pack_tlv(NFAPI_NFAPI_UPLINK_UES_PER_SUBFRAME_TAG, &(pNfapiMsg->nfapi_config.ul_ue_per_sf), ppWritePackedMsg, end, &pack_uint8_tlv_value) && - - pack_tlv(NFAPI_NFAPI_RF_BANDS_TAG, &(pNfapiMsg->nfapi_config.rf_bands), ppWritePackedMsg, end, &pack_rf_bands_value) && - - pack_tlv(NFAPI_NFAPI_TIMING_WINDOW_TAG, &(pNfapiMsg->nfapi_config.timing_window), ppWritePackedMsg, end, &pack_uint8_tlv_value) && - pack_tlv(NFAPI_NFAPI_TIMING_INFO_MODE_TAG, &(pNfapiMsg->nfapi_config.timing_info_mode), ppWritePackedMsg, end, &pack_uint8_tlv_value) && - pack_tlv(NFAPI_NFAPI_TIMING_INFO_PERIOD_TAG, &(pNfapiMsg->nfapi_config.timing_info_period), ppWritePackedMsg, end, &pack_uint8_tlv_value) && - - pack_tlv(NFAPI_NFAPI_MAXIMUM_TRANSMIT_POWER_TAG, &(pNfapiMsg->nfapi_config.max_transmit_power), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_NFAPI_EARFCN_TAG, &(pNfapiMsg->nfapi_config.earfcn), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - - - pack_tlv(NFAPI_NFAPI_NMM_GSM_FREQUENCY_BANDS_TAG, &(pNfapiMsg->nfapi_config.nmm_gsm_frequency_bands), ppWritePackedMsg, end, &pack_nmm_frequency_bands_value) && - pack_tlv(NFAPI_NFAPI_NMM_UMTS_FREQUENCY_BANDS_TAG, &(pNfapiMsg->nfapi_config.nmm_umts_frequency_bands), ppWritePackedMsg, end, &pack_nmm_frequency_bands_value) && - pack_tlv(NFAPI_NFAPI_NMM_LTE_FREQUENCY_BANDS_TAG, &(pNfapiMsg->nfapi_config.nmm_lte_frequency_bands), ppWritePackedMsg, end, &pack_nmm_frequency_bands_value) && - pack_tlv(NFAPI_NFAPI_NMM_UPLINK_RSSI_SUPPORTED_TAG, &(pNfapiMsg->nfapi_config.nmm_uplink_rssi_supported), ppWritePackedMsg, end, &pack_uint8_tlv_value) && - pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config) ); - -} - -static uint8_t pack_nr_param_response(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t* config) -{ - printf("\nRUNNING pack_param_response\n"); - nfapi_nr_param_response_scf_t *pNfapiMsg = (nfapi_nr_param_response_scf_t*)msg; - - return (push8(pNfapiMsg->error_code, ppWritePackedMsg, end) && - push8(pNfapiMsg->num_tlv, ppWritePackedMsg, end) && - pack_tlv(NFAPI_NR_PARAM_TLV_RELEASE_CAPABILITY_TAG, &(pNfapiMsg->cell_param.release_capability), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_NR_PARAM_TLV_PHY_STATE_TAG, &(pNfapiMsg->cell_param.phy_state), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_NR_PARAM_TLV_SKIP_BLANK_DL_CONFIG_TAG, &(pNfapiMsg->cell_param.skip_blank_dl_config), ppWritePackedMsg, end, &pack_uint8_tlv_value) && - pack_tlv(NFAPI_NR_PARAM_TLV_SKIP_BLANK_UL_CONFIG_TAG, &(pNfapiMsg->cell_param.skip_blank_ul_config), ppWritePackedMsg, end, &pack_uint8_tlv_value) && - pack_tlv(NFAPI_NR_PARAM_TLV_NUM_CONFIG_TLVS_TO_REPORT_TAG, &(pNfapiMsg->cell_param.num_config_tlvs_to_report ), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - - pack_tlv(NFAPI_NR_PARAM_TLV_CYCLIC_PREFIX_TAG, &(pNfapiMsg->carrier_param.cyclic_prefix), ppWritePackedMsg, end, &pack_uint8_tlv_value) && - pack_tlv(NFAPI_NR_PARAM_TLV_SUPPORTED_SUBCARRIER_SPACINGS_DL_TAG, &(pNfapiMsg->carrier_param.supported_subcarrier_spacings_dl), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_NR_PARAM_TLV_SUPPORTED_BANDWIDTH_DL_TAG, &(pNfapiMsg->carrier_param.supported_bandwidth_dl), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_NR_PARAM_TLV_SUPPORTED_SUBCARRIER_SPACINGS_UL_TAG, &(pNfapiMsg->carrier_param.supported_subcarrier_spacings_ul), ppWritePackedMsg, end, &pack_uint8_tlv_value) && - pack_tlv(NFAPI_NR_PARAM_TLV_SUPPORTED_BANDWIDTH_UL_TAG, &(pNfapiMsg->carrier_param.supported_bandwidth_ul), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - - pack_tlv(NFAPI_NR_PARAM_TLV_CCE_MAPPING_TYPE_TAG, &(pNfapiMsg->pdcch_param.cce_mapping_type), ppWritePackedMsg, end, &pack_uint8_tlv_value) && - pack_tlv(NFAPI_NR_PARAM_TLV_CORESET_OUTSIDE_FIRST_3_OFDM_SYMS_OF_SLOT_TAG, &(pNfapiMsg->pdcch_param.coreset_outside_first_3_of_ofdm_syms_of_slot), ppWritePackedMsg, end, &pack_uint8_tlv_value) && - pack_tlv(NFAPI_NR_PARAM_TLV_PRECODER_GRANULARITY_CORESET_TAG, &(pNfapiMsg->pdcch_param.coreset_precoder_granularity_coreset), ppWritePackedMsg, end, &pack_uint8_tlv_value) && - pack_tlv(NFAPI_NR_PARAM_TLV_PDCCH_MU_MIMO_TAG, &(pNfapiMsg->pdcch_param.pdcch_mu_mimo), ppWritePackedMsg, end, &pack_uint8_tlv_value) && - pack_tlv(NFAPI_NR_PARAM_TLV_PDCCH_PRECODER_CYCLING_TAG, &(pNfapiMsg->pdcch_param.pdcch_precoder_cycling), ppWritePackedMsg, end, &pack_uint8_tlv_value) && - pack_tlv(NFAPI_NR_PARAM_TLV_MAX_PDCCHS_PER_SLOT_TAG, &(pNfapiMsg->pdcch_param.max_pdcch_per_slot), ppWritePackedMsg, end, &pack_uint8_tlv_value) && - - pack_tlv(NFAPI_NR_PARAM_TLV_PUCCH_FORMATS_TAG, &(pNfapiMsg->pucch_param.pucch_formats), ppWritePackedMsg, end, &pack_uint8_tlv_value) && - pack_tlv(NFAPI_NR_PARAM_TLV_MAX_PUCCHS_PER_SLOT_TAG, &(pNfapiMsg->pucch_param.max_pucchs_per_slot), ppWritePackedMsg, end, &pack_uint8_tlv_value) && - - pack_tlv(NFAPI_NR_PARAM_TLV_PDSCH_MAPPING_TYPE_TAG, &(pNfapiMsg->pdsch_param.pdsch_mapping_type), ppWritePackedMsg, end, &pack_uint8_tlv_value) && - pack_tlv(NFAPI_NR_PARAM_TLV_PDSCH_ALLOCATION_TYPES_TAG, &(pNfapiMsg->pdsch_param.pdsch_allocation_types), ppWritePackedMsg, end, &pack_uint8_tlv_value) && - pack_tlv(NFAPI_NR_PARAM_TLV_PDSCH_VRB_TO_PRB_MAPPING_TAG, &(pNfapiMsg->pdsch_param.pdsch_vrb_to_prb_mapping), ppWritePackedMsg, end, &pack_uint8_tlv_value) && - pack_tlv(NFAPI_NR_PARAM_TLV_PDSCH_CBG_TAG, &(pNfapiMsg->pdsch_param.pdsch_cbg), ppWritePackedMsg, end, &pack_uint8_tlv_value) && - pack_tlv(NFAPI_NR_PARAM_TLV_PDSCH_DMRS_CONFIG_TYPES_TAG, &(pNfapiMsg->pdsch_param.pdsch_dmrs_config_types), ppWritePackedMsg, end, &pack_uint8_tlv_value) && - pack_tlv(NFAPI_NR_PARAM_TLV_PDSCH_DMRS_MAX_LENGTH_TAG, &(pNfapiMsg->pdsch_param.pdsch_dmrs_max_length), ppWritePackedMsg, end, &pack_uint8_tlv_value) && - pack_tlv(NFAPI_NR_PARAM_TLV_PDSCH_DMRS_ADDITIONAL_POS_TAG, &(pNfapiMsg->pdsch_param.pdsch_dmrs_additional_pos), ppWritePackedMsg, end, &pack_uint8_tlv_value) && - pack_tlv(NFAPI_NR_PARAM_TLV_MAX_PDSCH_S_YBS_PER_SLOT_TAG, &(pNfapiMsg->pdsch_param.max_pdsch_tbs_per_slot), ppWritePackedMsg, end, &pack_uint8_tlv_value) && - pack_tlv(NFAPI_NR_PARAM_TLV_MAX_NUMBER_MIMO_LAYERS_PDSCH_TAG, &(pNfapiMsg->pdsch_param.max_number_mimo_layers_pdsch), ppWritePackedMsg, end, &pack_uint8_tlv_value) && - pack_tlv(NFAPI_NR_PARAM_TLV_MAX_MU_MIMO_USERS_DL_TAG, &(pNfapiMsg->pdsch_param.max_mu_mimo_users_dl), ppWritePackedMsg, end, &pack_uint8_tlv_value) && - pack_tlv(NFAPI_NR_PARAM_TLV_PDSCH_DATA_IN_DMRS_SYMBOLS_TAG, &(pNfapiMsg->pdsch_param.pdsch_data_in_dmrs_symbols), ppWritePackedMsg, end, &pack_uint8_tlv_value) && - pack_tlv(NFAPI_NR_PARAM_TLV_PREMPTION_SUPPORT_TAG, &(pNfapiMsg->pdsch_param.premption_support), ppWritePackedMsg, end, &pack_uint8_tlv_value) && - pack_tlv(NFAPI_NR_PARAM_TLV_PDSCH_NON_SLOT_SUPPORT_TAG, &(pNfapiMsg->pdsch_param.pdsch_non_slot_support), ppWritePackedMsg, end, &pack_uint8_tlv_value) && - - pack_tlv(NFAPI_NR_PARAM_TLV_UCI_MUX_ULSCH_IN_PUSCH_TAG, &(pNfapiMsg->pusch_param.uci_mux_ulsch_in_pusch), ppWritePackedMsg, end, &pack_uint8_tlv_value) && - pack_tlv(NFAPI_NR_PARAM_TLV_UCI_ONLY_PUSCH_TAG, &(pNfapiMsg->pusch_param.uci_only_pusch), ppWritePackedMsg, end, &pack_uint8_tlv_value) && - pack_tlv(NFAPI_NR_PARAM_TLV_PUSCH_FREQUENCY_HOPPING_TAG, &(pNfapiMsg->pusch_param.pusch_frequency_hopping), ppWritePackedMsg, end, &pack_uint8_tlv_value) && - pack_tlv(NFAPI_NR_PARAM_TLV_PUSCH_DMRS_CONFIG_TYPES_TAG, &(pNfapiMsg->pusch_param.pusch_dmrs_config_types), ppWritePackedMsg, end, &pack_uint8_tlv_value) && - pack_tlv(NFAPI_NR_PARAM_TLV_PUSCH_DMRS_MAX_LEN_TAG, &(pNfapiMsg->pusch_param.pusch_dmrs_max_len), ppWritePackedMsg, end, &pack_uint8_tlv_value) && - pack_tlv(NFAPI_NR_PARAM_TLV_PUSCH_DMRS_ADDITIONAL_POS_TAG, &(pNfapiMsg->pusch_param.pusch_dmrs_additional_pos), ppWritePackedMsg, end, &pack_uint8_tlv_value) && - pack_tlv(NFAPI_NR_PARAM_TLV_PUSCH_CBG_TAG, &(pNfapiMsg->pusch_param.pusch_cbg), ppWritePackedMsg, end, &pack_uint8_tlv_value) && - pack_tlv(NFAPI_NR_PARAM_TLV_PUSCH_MAPPING_TYPE_TAG, &(pNfapiMsg->pusch_param.pusch_mapping_type), ppWritePackedMsg, end, &pack_uint8_tlv_value) && - pack_tlv(NFAPI_NR_PARAM_TLV_PUSCH_ALLOCATION_TYPES_TAG, &(pNfapiMsg->pusch_param.pusch_allocation_types), ppWritePackedMsg, end, &pack_uint8_tlv_value) && - pack_tlv(NFAPI_NR_PARAM_TLV_PUSCH_VRB_TO_PRB_MAPPING_TAG, &(pNfapiMsg->pusch_param.pusch_vrb_to_prb_mapping), ppWritePackedMsg, end, &pack_uint8_tlv_value) && - pack_tlv(NFAPI_NR_PARAM_TLV_PUSCH_MAX_PTRS_PORTS_TAG, &(pNfapiMsg->pusch_param.pusch_max_ptrs_ports), ppWritePackedMsg, end, &pack_uint8_tlv_value) && - pack_tlv(NFAPI_NR_PARAM_TLV_MAX_PDUSCHS_TBS_PER_SLOT_TAG, &(pNfapiMsg->pusch_param.max_pduschs_tbs_per_slot), ppWritePackedMsg, end, &pack_uint8_tlv_value) && - pack_tlv(NFAPI_NR_PARAM_TLV_MAX_NUMBER_MIMO_LAYERS_NON_CB_PUSCH_TAG, &(pNfapiMsg->pusch_param.max_number_mimo_layers_non_cb_pusch), ppWritePackedMsg, end, &pack_uint8_tlv_value) && - pack_tlv(NFAPI_NR_PARAM_TLV_SUPPORTED_MODULATION_ORDER_UL_TAG, &(pNfapiMsg->pusch_param.supported_modulation_order_ul), ppWritePackedMsg, end, &pack_uint8_tlv_value) && - pack_tlv(NFAPI_NR_PARAM_TLV_MAX_MU_MIMO_USERS_UL_TAG, &(pNfapiMsg->pusch_param.max_mu_mimo_users_ul), ppWritePackedMsg, end, &pack_uint8_tlv_value) && - pack_tlv(NFAPI_NR_PARAM_TLV_DFTS_OFDM_SUPPORT_TAG, &(pNfapiMsg->pusch_param.dfts_ofdm_support), ppWritePackedMsg, end, &pack_uint8_tlv_value) && - pack_tlv(NFAPI_NR_PARAM_TLV_PUSCH_AGGREGATION_FACTOR_TAG, &(pNfapiMsg->pusch_param.pusch_aggregation_factor), ppWritePackedMsg, end, &pack_uint8_tlv_value) && - - pack_tlv(NFAPI_NR_PARAM_TLV_PRACH_LONG_FORMATS_TAG, &(pNfapiMsg->prach_param.prach_long_formats), ppWritePackedMsg, end, &pack_uint8_tlv_value) && - pack_tlv(NFAPI_NR_PARAM_TLV_PRACH_SHORT_FORMATS_TAG, &(pNfapiMsg->prach_param.prach_short_formats), ppWritePackedMsg, end, &pack_uint8_tlv_value) && - pack_tlv(NFAPI_NR_PARAM_TLV_PRACH_RESTRICTED_SETS_TAG, &(pNfapiMsg->prach_param.prach_restricted_sets), ppWritePackedMsg, end, &pack_uint8_tlv_value) && - pack_tlv(NFAPI_NR_PARAM_TLV_MAX_PRACH_FD_OCCASIONS_IN_A_SLOT_TAG, &(pNfapiMsg->prach_param.max_prach_fd_occasions_in_a_slot), ppWritePackedMsg, end, &pack_uint8_tlv_value) && - - pack_tlv(NFAPI_NR_PARAM_TLV_RSSI_MEASUREMENT_SUPPORT_TAG, &(pNfapiMsg->measurement_param.rssi_measurement_support), ppWritePackedMsg, end, &pack_uint8_tlv_value) && - - // config: - - pack_tlv(NFAPI_NR_NFAPI_P7_VNF_ADDRESS_IPV4_TAG, &(pNfapiMsg->nfapi_config.p7_vnf_address_ipv4), ppWritePackedMsg, end, &pack_ipv4_address_value) && - pack_tlv(NFAPI_NR_NFAPI_P7_VNF_ADDRESS_IPV6_TAG, &(pNfapiMsg->nfapi_config.p7_vnf_address_ipv6), ppWritePackedMsg, end, &pack_ipv6_address_value) && - - pack_tlv(NFAPI_NR_NFAPI_P7_VNF_PORT_TAG, &(pNfapiMsg->nfapi_config.p7_vnf_port), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - - pack_tlv(NFAPI_NR_NFAPI_P7_PNF_ADDRESS_IPV4_TAG, &(pNfapiMsg->nfapi_config.p7_pnf_address_ipv4), ppWritePackedMsg, end, &pack_ipv4_address_value) && - pack_tlv(NFAPI_NR_NFAPI_P7_PNF_ADDRESS_IPV6_TAG, &(pNfapiMsg->nfapi_config.p7_pnf_address_ipv6), ppWritePackedMsg, end, &pack_ipv6_address_value) && - - pack_tlv(NFAPI_NR_NFAPI_P7_PNF_PORT_TAG, &(pNfapiMsg->nfapi_config.p7_pnf_port), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_NR_NFAPI_TIMING_WINDOW_TAG, &(pNfapiMsg->nfapi_config.timing_window), ppWritePackedMsg, end, &pack_uint8_tlv_value) && - pack_tlv(NFAPI_NR_NFAPI_TIMING_INFO_MODE_TAG, &(pNfapiMsg->nfapi_config.timing_info_mode), ppWritePackedMsg, end, &pack_uint8_tlv_value) && - pack_tlv(NFAPI_NR_NFAPI_TIMING_INFO_PERIOD_TAG, &(pNfapiMsg->nfapi_config.timing_info_period), ppWritePackedMsg, end, &pack_uint8_tlv_value) && - pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); - -} - -static uint8_t pack_config_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t* config) -{ - nfapi_config_request_t *pNfapiMsg = (nfapi_config_request_t*)msg; - - return ( push8(pNfapiMsg->num_tlv, ppWritePackedMsg, end) && - - // Do we check the phy state and then just fill those sepecified, however - // we do not know the duplex mode, so just attempt to pack all and assumme - // that the callee has set the right tlvs - - pack_tlv(NFAPI_SUBFRAME_CONFIG_DUPLEX_MODE_TAG, &(pNfapiMsg->subframe_config.duplex_mode), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_SUBFRAME_CONFIG_PCFICH_POWER_OFFSET_TAG, &(pNfapiMsg->subframe_config.pcfich_power_offset), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_SUBFRAME_CONFIG_PB_TAG, &(pNfapiMsg->subframe_config.pb), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_SUBFRAME_CONFIG_DL_CYCLIC_PREFIX_TYPE_TAG, &(pNfapiMsg->subframe_config.dl_cyclic_prefix_type), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_SUBFRAME_CONFIG_UL_CYCLIC_PREFIX_TYPE_TAG, &(pNfapiMsg->subframe_config.ul_cyclic_prefix_type), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - - pack_tlv(NFAPI_RF_CONFIG_DL_CHANNEL_BANDWIDTH_TAG, &(pNfapiMsg->rf_config.dl_channel_bandwidth), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_RF_CONFIG_UL_CHANNEL_BANDWIDTH_TAG, &(pNfapiMsg->rf_config.ul_channel_bandwidth), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_RF_CONFIG_REFERENCE_SIGNAL_POWER_TAG, &(pNfapiMsg->rf_config.reference_signal_power), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_RF_CONFIG_TX_ANTENNA_PORTS_TAG, &(pNfapiMsg->rf_config.tx_antenna_ports), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_RF_CONFIG_RX_ANTENNA_PORTS_TAG, &(pNfapiMsg->rf_config.rx_antenna_ports), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - - pack_tlv(NFAPI_PHICH_CONFIG_PHICH_RESOURCE_TAG, &(pNfapiMsg->phich_config.phich_resource), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_PHICH_CONFIG_PHICH_DURATION_TAG, &(pNfapiMsg->phich_config.phich_duration), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_PHICH_CONFIG_PHICH_POWER_OFFSET_TAG, &(pNfapiMsg->phich_config.phich_power_offset), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - - pack_tlv(NFAPI_SCH_CONFIG_PRIMARY_SYNCHRONIZATION_SIGNAL_EPRE_EPRERS_TAG, &(pNfapiMsg->sch_config.primary_synchronization_signal_epre_eprers), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_SCH_CONFIG_SECONDARY_SYNCHRONIZATION_SIGNAL_EPRE_EPRERS_TAG, &(pNfapiMsg->sch_config.secondary_synchronization_signal_epre_eprers), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_SCH_CONFIG_PHYSICAL_CELL_ID_TAG, &(pNfapiMsg->sch_config.physical_cell_id), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - - pack_tlv(NFAPI_PRACH_CONFIG_CONFIGURATION_INDEX_TAG, &(pNfapiMsg->prach_config.configuration_index), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_PRACH_CONFIG_ROOT_SEQUENCE_INDEX_TAG, &(pNfapiMsg->prach_config.root_sequence_index), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_PRACH_CONFIG_ZERO_CORRELATION_ZONE_CONFIGURATION_TAG, &(pNfapiMsg->prach_config.zero_correlation_zone_configuration), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_PRACH_CONFIG_HIGH_SPEED_FLAG_TAG, &(pNfapiMsg->prach_config.high_speed_flag), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_PRACH_CONFIG_FREQUENCY_OFFSET_TAG, &(pNfapiMsg->prach_config.frequency_offset), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - - pack_tlv(NFAPI_PUSCH_CONFIG_HOPPING_MODE_TAG, &(pNfapiMsg->pusch_config.hopping_mode), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_PUSCH_CONFIG_HOPPING_OFFSET_TAG, &(pNfapiMsg->pusch_config.hopping_offset), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_PUSCH_CONFIG_NUMBER_OF_SUBBANDS_TAG, &(pNfapiMsg->pusch_config.number_of_subbands), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - - pack_tlv(NFAPI_PUCCH_CONFIG_DELTA_PUCCH_SHIFT_TAG, &(pNfapiMsg->pucch_config.delta_pucch_shift), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_PUCCH_CONFIG_N_CQI_RB_TAG, &(pNfapiMsg->pucch_config.n_cqi_rb), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_PUCCH_CONFIG_N_AN_CS_TAG, &(pNfapiMsg->pucch_config.n_an_cs), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_PUCCH_CONFIG_N1_PUCCH_AN_TAG, &(pNfapiMsg->pucch_config.n1_pucch_an), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - - pack_tlv(NFAPI_SRS_CONFIG_BANDWIDTH_CONFIGURATION_TAG, &(pNfapiMsg->srs_config.bandwidth_configuration), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_SRS_CONFIG_MAX_UP_PTS_TAG, &(pNfapiMsg->srs_config.max_up_pts), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_SRS_CONFIG_SRS_SUBFRAME_CONFIGURATION_TAG, &(pNfapiMsg->srs_config.srs_subframe_configuration), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_SRS_CONFIG_SRS_ACKNACK_SRS_SIMULTANEOUS_TRANSMISSION_TAG, &(pNfapiMsg->srs_config.srs_acknack_srs_simultaneous_transmission), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - - pack_tlv(NFAPI_UPLINK_REFERENCE_SIGNAL_CONFIG_UPLINK_RS_HOPPING_TAG, &(pNfapiMsg->uplink_reference_signal_config.uplink_rs_hopping), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_UPLINK_REFERENCE_SIGNAL_CONFIG_GROUP_ASSIGNMENT_TAG, &(pNfapiMsg->uplink_reference_signal_config.group_assignment), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_UPLINK_REFERENCE_SIGNAL_CONFIG_CYCLIC_SHIFT_1_FOR_DRMS_TAG, &(pNfapiMsg->uplink_reference_signal_config.cyclic_shift_1_for_drms), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - - pack_tlv(NFAPI_LAA_CONFIG_ED_THRESHOLD_FOR_LBT_FOR_PDSCH_TAG, &(pNfapiMsg->laa_config.ed_threshold_lbt_pdsch), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_LAA_CONFIG_ED_THRESHOLD_FOR_LBT_FOR_DRS_TAG, &(pNfapiMsg->laa_config.ed_threshold_lbt_drs), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_LAA_CONFIG_PD_THRESHOLD_TAG, &(pNfapiMsg->laa_config.pd_threshold), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_LAA_CONFIG_MULTI_CARRIER_TYPE_TAG, &(pNfapiMsg->laa_config.multi_carrier_type), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_LAA_CONFIG_MULTI_CARRIER_TX_TAG, &(pNfapiMsg->laa_config.multi_carrier_tx), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_LAA_CONFIG_MULTI_CARRIER_FREEZE_TAG, &(pNfapiMsg->laa_config.multi_carrier_freeze), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_LAA_CONFIG_TX_ANTENNA_PORTS_FOR_DRS_TAG, &(pNfapiMsg->laa_config.tx_antenna_ports_drs), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_LAA_CONFIG_TRANSMISSION_POWER_FOR_DRS_TAG, &(pNfapiMsg->laa_config.tx_power_drs), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - - pack_tlv(NFAPI_EMTC_CONFIG_PBCH_REPETITIONS_ENABLE_R13_TAG, &(pNfapiMsg->emtc_config.pbch_repetitions_enable_r13), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_EMTC_CONFIG_PRACH_CATM_ROOT_SEQUENCE_INDEX_TAG, &(pNfapiMsg->emtc_config.prach_catm_root_sequence_index), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_EMTC_CONFIG_PRACH_CATM_ZERO_CORRELATION_ZONE_CONFIGURATION_TAG, &(pNfapiMsg->emtc_config.prach_catm_zero_correlation_zone_configuration), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_EMTC_CONFIG_PRACH_CATM_HIGH_SPEED_FLAG, &(pNfapiMsg->emtc_config.prach_catm_high_speed_flag), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_0_ENABLE_TAG, &(pNfapiMsg->emtc_config.prach_ce_level_0_enable), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_0_CONFIGURATION_INDEX_TAG, &(pNfapiMsg->emtc_config.prach_ce_level_0_configuration_index), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_0_FREQUENCY_OFFSET_TAG, &(pNfapiMsg->emtc_config.prach_ce_level_0_frequency_offset), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_0_NUMBER_OF_REPETITIONS_PER_ATTEMPT_TAG, &(pNfapiMsg->emtc_config.prach_ce_level_0_number_of_repetitions_per_attempt), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_0_STARTING_SUBFRAME_PERIODICITY_TAG, &(pNfapiMsg->emtc_config.prach_ce_level_0_starting_subframe_periodicity), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_0_HOPPING_ENABLE_TAG, &(pNfapiMsg->emtc_config.prach_ce_level_0_hopping_enable), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_0_HOPPING_OFFSET_TAG, &(pNfapiMsg->emtc_config.prach_ce_level_0_hopping_offset), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_1_ENABLE_TAG, &(pNfapiMsg->emtc_config.prach_ce_level_1_enable), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_1_CONFIGURATION_INDEX_TAG, &(pNfapiMsg->emtc_config.prach_ce_level_1_configuration_index), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_1_FREQUENCY_OFFSET_TAG, &(pNfapiMsg->emtc_config.prach_ce_level_1_frequency_offset), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_1_NUMBER_OF_REPETITIONS_PER_ATTEMPT_TAG, &(pNfapiMsg->emtc_config.prach_ce_level_1_number_of_repetitions_per_attempt), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_1_STARTING_SUBFRAME_PERIODICITY_TAG, &(pNfapiMsg->emtc_config.prach_ce_level_1_starting_subframe_periodicity), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_1_HOPPING_ENABLE_TAG, &(pNfapiMsg->emtc_config.prach_ce_level_1_hopping_enable), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_1_HOPPING_OFFSET_TAG, &(pNfapiMsg->emtc_config.prach_ce_level_1_hopping_offset), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_2_ENABLE_TAG, &(pNfapiMsg->emtc_config.prach_ce_level_2_enable), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_2_CONFIGURATION_INDEX_TAG, &(pNfapiMsg->emtc_config.prach_ce_level_2_configuration_index), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_2_FREQUENCY_OFFSET_TAG, &(pNfapiMsg->emtc_config.prach_ce_level_2_frequency_offset), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_2_NUMBER_OF_REPETITIONS_PER_ATTEMPT_TAG, &(pNfapiMsg->emtc_config.prach_ce_level_2_number_of_repetitions_per_attempt), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_2_STARTING_SUBFRAME_PERIODICITY_TAG, &(pNfapiMsg->emtc_config.prach_ce_level_2_starting_subframe_periodicity), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_2_HOPPING_ENABLE_TAG, &(pNfapiMsg->emtc_config.prach_ce_level_2_hopping_enable), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_2_HOPPING_OFFSET_TAG, &(pNfapiMsg->emtc_config.prach_ce_level_2_hopping_offset), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_3_ENABLE_TAG, &(pNfapiMsg->emtc_config.prach_ce_level_3_enable), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_3_CONFIGURATION_INDEX_TAG, &(pNfapiMsg->emtc_config.prach_ce_level_3_configuration_index), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_3_FREQUENCY_OFFSET_TAG, &(pNfapiMsg->emtc_config.prach_ce_level_3_frequency_offset), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_3_NUMBER_OF_REPETITIONS_PER_ATTEMPT_TAG, &(pNfapiMsg->emtc_config.prach_ce_level_3_number_of_repetitions_per_attempt), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_3_STARTING_SUBFRAME_PERIODICITY_TAG, &(pNfapiMsg->emtc_config.prach_ce_level_3_starting_subframe_periodicity), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_3_HOPPING_ENABLE_TAG, &(pNfapiMsg->emtc_config.prach_ce_level_3_hopping_enable), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_3_HOPPING_OFFSET_TAG, &(pNfapiMsg->emtc_config.prach_ce_level_3_hopping_offset), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_EMTC_CONFIG_PUCCH_INTERVAL_ULHOPPINGCONFIGCOMMONMODEA_TAG, &(pNfapiMsg->emtc_config.pucch_interval_ulhoppingconfigcommonmodea), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_EMTC_CONFIG_PUCCH_INTERVAL_ULHOPPINGCONFIGCOMMONMODEB_TAG, &(pNfapiMsg->emtc_config.pucch_interval_ulhoppingconfigcommonmodeb), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - - pack_tlv(NFAPI_TDD_FRAME_STRUCTURE_SUBFRAME_ASSIGNMENT_TAG, &(pNfapiMsg->tdd_frame_structure_config.subframe_assignment), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_TDD_FRAME_STRUCTURE_SPECIAL_SUBFRAME_PATTERNS_TAG, &(pNfapiMsg->tdd_frame_structure_config.special_subframe_patterns), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - - pack_tlv(NFAPI_L23_CONFIG_DATA_REPORT_MODE_TAG, &(pNfapiMsg->l23_config.data_report_mode), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_L23_CONFIG_SFNSF_TAG, &(pNfapiMsg->l23_config.sfnsf), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - - - pack_tlv(NFAPI_NFAPI_P7_VNF_ADDRESS_IPV4_TAG, &(pNfapiMsg->nfapi_config.p7_vnf_address_ipv4), ppWritePackedMsg, end, &pack_ipv4_address_value) && - pack_tlv(NFAPI_NFAPI_P7_VNF_ADDRESS_IPV6_TAG, &(pNfapiMsg->nfapi_config.p7_vnf_address_ipv6), ppWritePackedMsg, end, &pack_ipv6_address_value) && - pack_tlv(NFAPI_NFAPI_P7_VNF_PORT_TAG, &(pNfapiMsg->nfapi_config.p7_vnf_port), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_NFAPI_P7_PNF_ADDRESS_IPV4_TAG, &(pNfapiMsg->nfapi_config.p7_pnf_address_ipv4), ppWritePackedMsg, end, &pack_ipv4_address_value) && - pack_tlv(NFAPI_NFAPI_P7_PNF_ADDRESS_IPV6_TAG, &(pNfapiMsg->nfapi_config.p7_pnf_address_ipv6), ppWritePackedMsg, end, &pack_ipv6_address_value) && - pack_tlv(NFAPI_NFAPI_P7_PNF_PORT_TAG, &(pNfapiMsg->nfapi_config.p7_pnf_port), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_NFAPI_DOWNLINK_UES_PER_SUBFRAME_TAG, &(pNfapiMsg->nfapi_config.dl_ue_per_sf), ppWritePackedMsg, end, &pack_uint8_tlv_value) && - pack_tlv(NFAPI_NFAPI_UPLINK_UES_PER_SUBFRAME_TAG, &(pNfapiMsg->nfapi_config.ul_ue_per_sf), ppWritePackedMsg, end, &pack_uint8_tlv_value) && - - pack_tlv(NFAPI_PHY_RF_BANDS_TAG, &(pNfapiMsg->nfapi_config.rf_bands), ppWritePackedMsg, end, &pack_rf_bands_value) && - - pack_tlv(NFAPI_NFAPI_TIMING_WINDOW_TAG, &(pNfapiMsg->nfapi_config.timing_window), ppWritePackedMsg, end, &pack_uint8_tlv_value) && - pack_tlv(NFAPI_NFAPI_TIMING_INFO_MODE_TAG, &(pNfapiMsg->nfapi_config.timing_info_mode), ppWritePackedMsg, end, &pack_uint8_tlv_value) && - pack_tlv(NFAPI_NFAPI_TIMING_INFO_PERIOD_TAG, &(pNfapiMsg->nfapi_config.timing_info_period), ppWritePackedMsg, end, &pack_uint8_tlv_value) && - - pack_tlv(NFAPI_NFAPI_MAXIMUM_TRANSMIT_POWER_TAG, &(pNfapiMsg->nfapi_config.max_transmit_power), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_NFAPI_EARFCN_TAG, &(pNfapiMsg->nfapi_config.earfcn), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - - - pack_tlv(NFAPI_NFAPI_NMM_GSM_FREQUENCY_BANDS_TAG, &(pNfapiMsg->nfapi_config.nmm_gsm_frequency_bands), ppWritePackedMsg, end, &pack_nmm_frequency_bands_value) && - pack_tlv(NFAPI_NFAPI_NMM_UMTS_FREQUENCY_BANDS_TAG, &(pNfapiMsg->nfapi_config.nmm_umts_frequency_bands), ppWritePackedMsg, end, &pack_nmm_frequency_bands_value) && - pack_tlv(NFAPI_NFAPI_NMM_LTE_FREQUENCY_BANDS_TAG, &(pNfapiMsg->nfapi_config.nmm_lte_frequency_bands), ppWritePackedMsg, end, &pack_nmm_frequency_bands_value) && - pack_tlv(NFAPI_NFAPI_NMM_UPLINK_RSSI_SUPPORTED_TAG, &(pNfapiMsg->nfapi_config.nmm_uplink_rssi_supported), ppWritePackedMsg, end, &pack_uint8_tlv_value) && - - pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config) ); -} - - -static uint8_t pack_nr_config_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t* config) -{ - printf("\n\nEntering pack_config_request\n"); - nfapi_nr_config_request_scf_t *pNfapiMsg = (nfapi_nr_config_request_scf_t*)msg; - - - return (push8(pNfapiMsg->num_tlv, ppWritePackedMsg, end) && - pack_tlv(NFAPI_NR_CONFIG_DL_BANDWIDTH_TAG, &(pNfapiMsg->carrier_config.dl_bandwidth), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_NR_CONFIG_DL_FREQUENCY_TAG, &(pNfapiMsg->carrier_config.dl_frequency), ppWritePackedMsg, end, &pack_uint32_tlv_value) && - pack_tlv(NFAPI_NR_CONFIG_DL_GRID_SIZE_TAG, &(pNfapiMsg->carrier_config.dl_grid_size[1]), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_NR_CONFIG_DL_K0_TAG, &(pNfapiMsg->carrier_config.dl_k0[1]), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_NR_CONFIG_NUM_RX_ANT_TAG, &(pNfapiMsg->carrier_config.num_rx_ant), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_NR_CONFIG_NUM_TX_ANT_TAG, &(pNfapiMsg->carrier_config.num_tx_ant), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_NR_CONFIG_UL_GRID_SIZE_TAG, &(pNfapiMsg->carrier_config.ul_grid_size[1]), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_NR_CONFIG_UL_K0_TAG, &(pNfapiMsg->carrier_config.ul_k0[1]), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_NR_CONFIG_UPLINK_BANDWIDTH_TAG, &(pNfapiMsg->carrier_config.uplink_bandwidth), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_NR_CONFIG_UPLINK_FREQUENCY_TAG, &(pNfapiMsg->carrier_config.uplink_frequency), ppWritePackedMsg, end, &pack_uint32_tlv_value) && - - pack_tlv(NFAPI_NR_CONFIG_FRAME_DUPLEX_TYPE_TAG, &(pNfapiMsg->cell_config.frame_duplex_type), ppWritePackedMsg, end, &pack_uint8_tlv_value) && - pack_tlv(NFAPI_NR_CONFIG_PHY_CELL_ID_TAG, &(pNfapiMsg->cell_config.phy_cell_id), ppWritePackedMsg, end, &pack_uint8_tlv_value) && - - pack_tlv(NFAPI_NR_CONFIG_NUM_PRACH_FD_OCCASIONS_TAG, &(pNfapiMsg->prach_config.num_prach_fd_occasions), ppWritePackedMsg, end, &pack_uint8_tlv_value) && - pack_tlv(NFAPI_NR_CONFIG_PRACH_SEQUENCE_LENGTH_TAG, &(pNfapiMsg->prach_config.prach_sequence_length), ppWritePackedMsg, end, &pack_uint8_tlv_value) && - pack_tlv(NFAPI_NR_CONFIG_RESTRICTED_SET_CONFIG_TAG, &(pNfapiMsg->prach_config.restricted_set_config), ppWritePackedMsg, end, &pack_uint8_tlv_value) && - pack_tlv(NFAPI_NR_CONFIG_SSB_PER_RACH_TAG, &(pNfapiMsg->prach_config.ssb_per_rach), ppWritePackedMsg, end, &pack_uint8_tlv_value) && - pack_tlv(NFAPI_NR_CONFIG_PRACH_SUB_C_SPACING_TAG, &(pNfapiMsg->prach_config.prach_sub_c_spacing), ppWritePackedMsg, end, &pack_uint8_tlv_value) && - pack_tlv(NFAPI_NR_CONFIG_PRACH_ROOT_SEQUENCE_INDEX_TAG, &(pNfapiMsg->prach_config.num_prach_fd_occasions_list[0].prach_root_sequence_index), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_NR_CONFIG_K1_TAG, &(pNfapiMsg->prach_config.num_prach_fd_occasions_list[0].k1), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_NR_CONFIG_PRACH_ZERO_CORR_CONF_TAG, &(pNfapiMsg->prach_config.num_prach_fd_occasions_list[0].prach_zero_corr_conf), ppWritePackedMsg, end, &pack_uint8_tlv_value) && - pack_tlv(NFAPI_NR_CONFIG_NUM_ROOT_SEQUENCES_TAG, &(pNfapiMsg->prach_config.num_prach_fd_occasions_list[0].num_root_sequences), ppWritePackedMsg, end, &pack_uint8_tlv_value) && - - - pack_tlv(NFAPI_NR_CONFIG_SCS_COMMON_TAG, &(pNfapiMsg->ssb_config.scs_common), ppWritePackedMsg, end, &pack_uint8_tlv_value) && - pack_tlv(NFAPI_NR_CONFIG_SS_PBCH_POWER_TAG, &(pNfapiMsg->ssb_config.ss_pbch_power), ppWritePackedMsg, end, &pack_uint32_tlv_value) && - - pack_tlv(NFAPI_NR_CONFIG_BETA_PSS_TAG, &(pNfapiMsg->ssb_table.beta_pss), ppWritePackedMsg, end, &pack_uint8_tlv_value) && - pack_tlv(NFAPI_NR_CONFIG_MIB_TAG, &(pNfapiMsg->ssb_table.MIB), ppWritePackedMsg, end, &pack_uint32_tlv_value) && - pack_tlv(NFAPI_NR_CONFIG_SSB_MASK_TAG, &(pNfapiMsg->ssb_table.ssb_mask_list[0].ssb_mask), ppWritePackedMsg, end, &pack_uint32_tlv_value) && - pack_tlv(NFAPI_NR_CONFIG_SSB_MASK_TAG, &(pNfapiMsg->ssb_table.ssb_mask_list[1].ssb_mask), ppWritePackedMsg, end, &pack_uint32_tlv_value) && - - pack_tlv(NFAPI_NR_CONFIG_SSB_OFFSET_POINT_A_TAG, &(pNfapiMsg->ssb_table.ssb_offset_point_a), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_NR_CONFIG_SSB_PERIOD_TAG, &(pNfapiMsg->ssb_table.ssb_period), ppWritePackedMsg, end, &pack_uint8_tlv_value) && - pack_tlv(NFAPI_NR_CONFIG_SSB_SUBCARRIER_OFFSET_TAG, &(pNfapiMsg->ssb_table.ssb_subcarrier_offset), ppWritePackedMsg, end, &pack_uint8_tlv_value) && - - pack_tlv(NFAPI_NR_CONFIG_TDD_PERIOD_TAG, &(pNfapiMsg->tdd_table.tdd_period), ppWritePackedMsg, end, &pack_uint8_tlv_value) && - pack_tlv(NFAPI_NR_CONFIG_SLOT_CONFIG_TAG, &(pNfapiMsg->tdd_table.max_tdd_periodicity_list[0].max_num_of_symbol_per_slot_list[0].slot_config), ppWritePackedMsg, end, &pack_uint8_tlv_value) && - - //pack_tlv(NFAPI_NR_NFAPI_DOWNLINK_UES_PER_SUBFRAME_TAG, &(pNfapiMsg->nfapi_config.dl_ue_per_sf), ppWritePackedMsg, end, &pack_uint8_tlv_value) && - //pack_tlv(NFAPI_NR_NFAPI_MAXIMUM_TRANSMIT_POWER_TAG, &(pNfapiMsg->nfapi_config.max_transmit_power), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - //pack_tlv(NFAPI_NR_NFAPI_NRARFCN_TAG, &(pNfapiMsg->nfapi_config.nrarfcn), ppWritePackedMsg, end, &pack_uint32_tlv_value) && - pack_tlv(NFAPI_NR_NFAPI_P7_PNF_ADDRESS_IPV4_TAG, &(pNfapiMsg->nfapi_config.p7_pnf_address_ipv4), ppWritePackedMsg, end, &pack_ipv4_address_value) && - pack_tlv(NFAPI_NR_NFAPI_P7_PNF_ADDRESS_IPV6_TAG, &(pNfapiMsg->nfapi_config.p7_pnf_address_ipv6), ppWritePackedMsg, end, &pack_ipv6_address_value) && - pack_tlv(NFAPI_NR_NFAPI_P7_PNF_PORT_TAG, &(pNfapiMsg->nfapi_config.p7_pnf_port), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_NR_NFAPI_P7_VNF_ADDRESS_IPV4_TAG, &(pNfapiMsg->nfapi_config.p7_vnf_address_ipv4), ppWritePackedMsg, end, &pack_ipv4_address_value) && - pack_tlv(NFAPI_NR_NFAPI_P7_VNF_ADDRESS_IPV6_TAG, &(pNfapiMsg->nfapi_config.p7_vnf_address_ipv6), ppWritePackedMsg, end, &pack_ipv6_address_value) && - pack_tlv(NFAPI_NR_NFAPI_P7_VNF_PORT_TAG, &(pNfapiMsg->nfapi_config.p7_vnf_port), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - //pack_tlv(NFAPI_NR_NFAPI_RF_BANDS_TAG, &(pNfapiMsg->nfapi_config.rf_bands), ppWritePackedMsg, end, &pack_rf_bands_value) && - pack_tlv(NFAPI_NR_NFAPI_TIMING_INFO_MODE_TAG, &(pNfapiMsg->nfapi_config.timing_info_mode), ppWritePackedMsg, end, &pack_uint8_tlv_value) && - pack_tlv(NFAPI_NR_NFAPI_TIMING_INFO_PERIOD_TAG, &(pNfapiMsg->nfapi_config.timing_info_period), ppWritePackedMsg, end, &pack_uint8_tlv_value) && - pack_tlv(NFAPI_NR_NFAPI_TIMING_WINDOW_TAG, &(pNfapiMsg->nfapi_config.timing_window), ppWritePackedMsg, end, &pack_uint8_tlv_value) && - //pack_tlv(NFAPI_NR_NFAPI_UPLINK_UES_PER_SUBFRAME_TAG, &(pNfapiMsg->nfapi_config.ul_ue_per_sf), ppWritePackedMsg, end, &pack_uint8_tlv_value) && - - pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config) ); -} - -static uint8_t pack_nr_config_response(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t* config) -{ - nfapi_nr_config_response_scf_t *pNfapiMsg = (nfapi_nr_config_response_scf_t*)msg; - - return ( push8(pNfapiMsg->error_code, ppWritePackedMsg, end) && - pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config) ); -} - -static uint8_t pack_config_response(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t* config) -{ - nfapi_config_response_t *pNfapiMsg = (nfapi_config_response_t*)msg; - - return ( push8(pNfapiMsg->error_code, ppWritePackedMsg, end) && - pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config) ); -} - -static uint8_t pack_nr_start_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t* config) -{ - nfapi_nr_start_request_scf_t *pNfapiMsg = (nfapi_nr_start_request_scf_t*)msg; - return pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config); -} - -static uint8_t pack_start_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t* config) -{ - nfapi_start_request_t *pNfapiMsg = (nfapi_start_request_t*)msg; - return pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config); -} - -static uint8_t pack_nr_start_response(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t* config) -{ - nfapi_nr_start_response_scf_t *pNfapiMsg = (nfapi_nr_start_response_scf_t*)msg; - - return ( push32(pNfapiMsg->error_code, ppWritePackedMsg, end ) && - pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config) ); -} - -static uint8_t pack_start_response(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t* config) -{ - nfapi_start_response_t *pNfapiMsg = (nfapi_start_response_t*)msg; - - return ( push32(pNfapiMsg->error_code, ppWritePackedMsg, end ) && - pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config) ); -} - - -static uint8_t pack_stop_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t* config) -{ - nfapi_stop_request_t *pNfapiMsg = (nfapi_stop_request_t*)msg; - return pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config); -} - -static uint8_t pack_stop_response(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t* config) -{ - nfapi_stop_response_t *pNfapiMsg = (nfapi_stop_response_t*)msg; - - return ( push32(pNfapiMsg->error_code, ppWritePackedMsg, end) && - pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config) ); -} - -static uint8_t pack_measurement_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t* config) -{ - nfapi_measurement_request_t *pNfapiMsg = (nfapi_measurement_request_t*)msg; - - return( pack_tlv(NFAPI_MEASUREMENT_REQUEST_DL_RS_XTX_POWER_TAG, &(pNfapiMsg->dl_rs_tx_power), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_MEASUREMENT_REQUEST_RECEIVED_INTERFERENCE_POWER_TAG, &(pNfapiMsg->received_interference_power), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_MEASUREMENT_REQUEST_THERMAL_NOISE_POWER_TAG, &(pNfapiMsg->thermal_noise_power), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); -} - -static uint8_t pack_recevied_interference_power_measurement_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_received_interference_power_measurement_t* value = (nfapi_received_interference_power_measurement_t*)tlv; - - return ( push16(value->number_of_resource_blocks, ppWritePackedMsg, end) && - pusharrays16(value->received_interference_power, NFAPI_MAX_RECEIVED_INTERFERENCE_POWER_RESULTS, value->number_of_resource_blocks, ppWritePackedMsg, end)); -} - -static uint8_t pack_measurement_response(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t* config) -{ - nfapi_measurement_response_t *pNfapiMsg = (nfapi_measurement_response_t*)msg; - - return( push32(pNfapiMsg->error_code, ppWritePackedMsg, end) && - pack_tlv(NFAPI_MEASUREMENT_RESPONSE_DL_RS_POWER_MEASUREMENT_TAG, &(pNfapiMsg->dl_rs_tx_power_measurement), ppWritePackedMsg, end, &pack_int16_tlv_value) && - pack_tlv(NFAPI_MEASUREMENT_RESPONSE_RECEIVED_INTERFERENCE_POWER_MEASUREMENT_TAG, &(pNfapiMsg->received_interference_power_measurement), ppWritePackedMsg, end, &pack_recevied_interference_power_measurement_value) && - pack_tlv(NFAPI_MEASUREMENT_RESPONSE_THERMAL_NOISE_MEASUREMENT_TAG, &(pNfapiMsg->thermal_noise_power_measurement), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); -} - -static uint8_t pack_nr_p5_message_body(nfapi_p4_p5_message_header_t *header, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t* config) -{ - uint8_t result = 0; - // look for the specific message - switch (header->message_id) - { - case NFAPI_NR_PHY_MSG_TYPE_PNF_PARAM_REQUEST: - result = pack_nr_pnf_param_request(header, ppWritePackedMsg, end, config); - break; - - case NFAPI_PNF_PARAM_RESPONSE: - result = pack_nr_pnf_param_response(header, ppWritePackedMsg, end, config); - break; - - case NFAPI_NR_PHY_MSG_TYPE_PNF_CONFIG_REQUEST: - result = pack_nr_pnf_config_request(header, ppWritePackedMsg, end, config); - break; - - case NFAPI_NR_PHY_MSG_TYPE_PNF_CONFIG_RESPONSE: - result = pack_nr_pnf_config_response(header, ppWritePackedMsg, end, config); - break; - - case NFAPI_NR_PHY_MSG_TYPE_PNF_START_REQUEST: - result = pack_nr_pnf_start_request(header, ppWritePackedMsg, end, config); - break; - - case NFAPI_NR_PHY_MSG_TYPE_PNF_START_RESPONSE: - result = pack_nr_pnf_start_response(header, ppWritePackedMsg, end, config); - break; - - case NFAPI_NR_PHY_MSG_TYPE_PNF_STOP_REQUEST: - result = pack_nr_pnf_stop_request(header, ppWritePackedMsg, end, config); - break; - - case NFAPI_PNF_STOP_RESPONSE: - result = pack_nr_pnf_stop_response(header, ppWritePackedMsg, end, config); - break; - - case NFAPI_NR_PHY_MSG_TYPE_PARAM_REQUEST: - result = pack_nr_param_request(header, ppWritePackedMsg, end, config); - break; - - case NFAPI_NR_PHY_MSG_TYPE_PARAM_RESPONSE: - result = pack_nr_param_response(header, ppWritePackedMsg, end, config); - break; - - case NFAPI_NR_PHY_MSG_TYPE_CONFIG_REQUEST: - result = pack_nr_config_request(header, ppWritePackedMsg, end, config); - break; - - case NFAPI_NR_PHY_MSG_TYPE_CONFIG_RESPONSE: - result = pack_nr_config_response(header, ppWritePackedMsg, end, config); - break; - - case NFAPI_NR_PHY_MSG_TYPE_START_REQUEST: - result = pack_nr_start_request(header, ppWritePackedMsg, end, config); - break; - - case NFAPI_NR_PHY_MSG_TYPE_START_RESPONSE: - result = pack_nr_start_response(header, ppWritePackedMsg, end, config); - break; - - case NFAPI_NR_PHY_MSG_TYPE_STOP_REQUEST: - result = pack_stop_request(header, ppWritePackedMsg, end, config); - break; - - case NFAPI_NR_PHY_MSG_TYPE_STOP_RESPONSE: - result = pack_stop_response(header, ppWritePackedMsg, end, config); - break; - default: - { - if(header->message_id >= NFAPI_VENDOR_EXT_MSG_MIN && - header->message_id <= NFAPI_VENDOR_EXT_MSG_MAX) - { - if(config && config->pack_p4_p5_vendor_extension) - { - result = (config->pack_p4_p5_vendor_extension)(header, ppWritePackedMsg, end, config); - } - else - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s VE NFAPI message ID %d. No ve ecoder provided\n", __FUNCTION__, header->message_id); - } - } - else - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s NFAPI Unknown message ID %d\n", __FUNCTION__, header->message_id); - } - } - break; - } - - return result; -} - - -static uint8_t pack_p5_message_body(nfapi_p4_p5_message_header_t *header, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t* config) -{ - uint8_t result = 0; - // look for the specific message - switch (header->message_id) - { - case NFAPI_PNF_PARAM_REQUEST: - result = pack_pnf_param_request(header, ppWritePackedMsg, end, config); - break; - - case NFAPI_PNF_PARAM_RESPONSE: - result = pack_pnf_param_response(header, ppWritePackedMsg, end, config); - break; - - case NFAPI_PNF_CONFIG_REQUEST: - result = pack_pnf_config_request(header, ppWritePackedMsg, end, config); - break; - - case NFAPI_PNF_CONFIG_RESPONSE: - result = pack_pnf_config_response(header, ppWritePackedMsg, end, config); - break; - - case NFAPI_PNF_START_REQUEST: - result = pack_pnf_start_request(header, ppWritePackedMsg, end, config); - break; - - case NFAPI_PNF_START_RESPONSE: - result = pack_pnf_start_response(header, ppWritePackedMsg, end, config); - break; - - case NFAPI_PNF_STOP_REQUEST: - result = pack_pnf_stop_request(header, ppWritePackedMsg, end, config); - break; - - case NFAPI_PNF_STOP_RESPONSE: - result = pack_pnf_stop_response(header, ppWritePackedMsg, end, config); - break; - - case NFAPI_PARAM_REQUEST: - result = pack_param_request(header, ppWritePackedMsg, end, config); - break; - - case NFAPI_PARAM_RESPONSE: - result = pack_param_response(header, ppWritePackedMsg, end, config); - break; - - case NFAPI_CONFIG_REQUEST: - result = pack_config_request(header, ppWritePackedMsg, end, config); - break; - - case NFAPI_CONFIG_RESPONSE: - result = pack_config_response(header, ppWritePackedMsg, end, config); - break; - - case NFAPI_START_REQUEST: - result = pack_start_request(header, ppWritePackedMsg, end, config); - break; - - case NFAPI_START_RESPONSE: - result = pack_start_response(header, ppWritePackedMsg, end, config); - break; - - case NFAPI_STOP_REQUEST: - result = pack_stop_request(header, ppWritePackedMsg, end, config); - break; - - case NFAPI_STOP_RESPONSE: - result = pack_stop_response(header, ppWritePackedMsg, end, config); - break; - - case NFAPI_MEASUREMENT_REQUEST: - result = pack_measurement_request(header, ppWritePackedMsg, end, config); - break; - - case NFAPI_MEASUREMENT_RESPONSE: - result = pack_measurement_response(header, ppWritePackedMsg, end, config); - break; - - default: - { - if(header->message_id >= NFAPI_VENDOR_EXT_MSG_MIN && - header->message_id <= NFAPI_VENDOR_EXT_MSG_MAX) - { - if(config && config->pack_p4_p5_vendor_extension) - { - result = (config->pack_p4_p5_vendor_extension)(header, ppWritePackedMsg, end, config); - } - else - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s VE NFAPI message ID %d. No ve ecoder provided\n", __FUNCTION__, header->message_id); - } - } - else - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s NFAPI Unknown message ID %d\n", __FUNCTION__, header->message_id); - } - } - break; - } - - return result; -} - - -// helper function for message length calculation - -// takes the pointers to the start of message to end of message - -static uint32_t get_packed_msg_len(uintptr_t msgHead, uintptr_t msgEnd) -{ - if (msgEnd < msgHead) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "get_packed_msg_len: Error in pointers supplied %d, %d\n", msgHead, msgEnd); - return 0; - } - - return (msgEnd - msgHead); -} - -// Main pack function - public -int nfapi_nr_p5_message_pack(void *pMessageBuf, uint32_t messageBufLen, void *pPackedBuf, uint32_t packedBufLen, nfapi_p4_p5_codec_config_t* config) -{ - nfapi_p4_p5_message_header_t *pMessageHeader = pMessageBuf; - uint8_t *pWritePackedMessage = pPackedBuf; - uint8_t *pPackMessageEnd = pPackedBuf + packedBufLen; - uint8_t *pPackedLengthField = &pWritePackedMessage[4]; - uint32_t packedMsgLen; - uint16_t packedMsgLen16; - - if (pMessageBuf == NULL || pPackedBuf == NULL) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "P5 Pack supplied pointers are null\n"); - return -1; - } - - // pack the message - if(push16(pMessageHeader->phy_id, &pWritePackedMessage, pPackMessageEnd) && - push16(pMessageHeader->message_id, &pWritePackedMessage, pPackMessageEnd) && - push16(0, &pWritePackedMessage, pPackMessageEnd) && - push16(pMessageHeader->spare, &pWritePackedMessage, pPackMessageEnd) && - pack_nr_p5_message_body(pMessageHeader, &pWritePackedMessage, pPackMessageEnd, config)) - { - // check for a valid message length - packedMsgLen = get_packed_msg_len((uintptr_t)pPackedBuf, (uintptr_t)pWritePackedMessage); - if (packedMsgLen > 0xFFFF || packedMsgLen > packedBufLen) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "Packed message length error %d, buffer supplied %d\n", packedMsgLen, packedBufLen); - return -1; - } - else - { - packedMsgLen16 = (uint16_t)packedMsgLen; - } - - // Update the message length in the header - if(!push16(packedMsgLen16, &pPackedLengthField, pPackMessageEnd)) - return -1; - - // return the packed length - return (packedMsgLen); - } - else - { - // Failed to pack the meassage - NFAPI_TRACE(NFAPI_TRACE_ERROR, "P5 Failed to pack message\n"); - return -1; - } - -} - -int nfapi_p5_message_pack(void *pMessageBuf, uint32_t messageBufLen, void *pPackedBuf, uint32_t packedBufLen, nfapi_p4_p5_codec_config_t* config) -{ - nfapi_p4_p5_message_header_t *pMessageHeader = pMessageBuf; - uint8_t *pWritePackedMessage = pPackedBuf; - uint8_t *pPackMessageEnd = pPackedBuf + packedBufLen; - uint8_t *pPackedLengthField = &pWritePackedMessage[4]; - uint32_t packedMsgLen; - uint16_t packedMsgLen16; - - if (pMessageBuf == NULL || pPackedBuf == NULL) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "P5 Pack supplied pointers are null\n"); - return -1; - } - - // pack the message - if(push16(pMessageHeader->phy_id, &pWritePackedMessage, pPackMessageEnd) && - push16(pMessageHeader->message_id, &pWritePackedMessage, pPackMessageEnd) && - push16(0/*pMessageHeader->message_length*/, &pWritePackedMessage, pPackMessageEnd) && - push16(pMessageHeader->spare, &pWritePackedMessage, pPackMessageEnd) && - pack_p5_message_body(pMessageHeader, &pWritePackedMessage, pPackMessageEnd, config)) - { - // check for a valid message length - packedMsgLen = get_packed_msg_len((uintptr_t)pPackedBuf, (uintptr_t)pWritePackedMessage); - if (packedMsgLen > 0xFFFF || packedMsgLen > packedBufLen) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "Packed message length error %d, buffer supplied %d\n", packedMsgLen, packedBufLen); - return -1; - } - else - { - packedMsgLen16 = (uint16_t)packedMsgLen; - } - - // Update the message length in the header - if(!push16(packedMsgLen16, &pPackedLengthField, pPackMessageEnd)) - return -1; - - // return the packed length - return (packedMsgLen); - } - else - { - // Failed to pack the meassage - NFAPI_TRACE(NFAPI_TRACE_ERROR, "P5 Failed to pack message\n"); - return -1; - } - -} - - - -// Unpack routines - - -static uint8_t unpack_nr_pnf_param_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t* config) -{ - nfapi_nr_pnf_param_request_t *pNfapiMsg = (nfapi_nr_pnf_param_request_t*)msg; - - unpack_tlv_t unpack_fns[] = - { - }; - - return unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &(pNfapiMsg->vendor_extension)); -} - - -static uint8_t unpack_pnf_param_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t* config) -{ - nfapi_pnf_param_request_t *pNfapiMsg = (nfapi_pnf_param_request_t*)msg; - - unpack_tlv_t unpack_fns[] = - { - }; - - return unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &(pNfapiMsg->vendor_extension)); -} - -static uint8_t unpack_pnf_param_general_value(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_pnf_param_general_t* value = (nfapi_pnf_param_general_t*)tlv; - - return( pull8(ppReadPackedMsg, &value->nfapi_sync_mode, end) && - pull8(ppReadPackedMsg, &value->location_mode, end) && - pull16(ppReadPackedMsg, &value->location_coordinates_length, end) && - pullarray8(ppReadPackedMsg, value->location_coordinates, NFAPI_PNF_PARAM_GENERAL_LOCATION_LENGTH, value->location_coordinates_length, end) && - pull32(ppReadPackedMsg, &value->dl_config_timing, end) && - pull32(ppReadPackedMsg, &value->tx_timing, end) && - pull32(ppReadPackedMsg, &value->ul_config_timing, end) && - pull32(ppReadPackedMsg, &value->hi_dci0_timing, end) && - pull16(ppReadPackedMsg, &value->maximum_number_phys, end) && - pull16(ppReadPackedMsg, &value->maximum_total_bandwidth, end) && - pull8(ppReadPackedMsg, &value->maximum_total_number_dl_layers, end) && - pull8(ppReadPackedMsg, &value->maximum_total_number_ul_layers, end) && - pull8(ppReadPackedMsg, &value->shared_bands, end) && - pull8(ppReadPackedMsg, &value->shared_pa, end) && - pulls16(ppReadPackedMsg, &value->maximum_total_power, end) && - pullarray8(ppReadPackedMsg, value->oui, NFAPI_PNF_PARAM_GENERAL_OUI_LENGTH, NFAPI_PNF_PARAM_GENERAL_OUI_LENGTH, end)); -} - -static uint8_t unpack_rf_config_info(void* elem, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_rf_config_info_t* info = (nfapi_rf_config_info_t*)elem; - return pull16(ppReadPackedMsg, &info->rf_config_index, end); -} - -static uint8_t unpack_pnf_phy_info(void* elem, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_pnf_phy_info_t* phy = (nfapi_pnf_phy_info_t*)elem; - - return ( pull16(ppReadPackedMsg, &phy->phy_config_index, end) && - pull16(ppReadPackedMsg, &phy->number_of_rfs, end) && - unpackarray(ppReadPackedMsg, phy->rf_config, sizeof(nfapi_rf_config_info_t), NFAPI_MAX_PNF_PHY_RF_CONFIG, phy->number_of_rfs, end, &unpack_rf_config_info) && - pull16(ppReadPackedMsg, &phy->number_of_rf_exclusions, end) && - unpackarray(ppReadPackedMsg, phy->excluded_rf_config, sizeof(nfapi_rf_config_info_t), NFAPI_MAX_PNF_PHY_RF_CONFIG, phy->number_of_rf_exclusions, end, &unpack_rf_config_info) && - pull16(ppReadPackedMsg, &phy->downlink_channel_bandwidth_supported, end) && - pull16(ppReadPackedMsg, &phy->uplink_channel_bandwidth_supported, end) && - pull8(ppReadPackedMsg, &phy->number_of_dl_layers_supported, end) && - pull8(ppReadPackedMsg, &phy->number_of_ul_layers_supported, end) && - pull16(ppReadPackedMsg, &phy->maximum_3gpp_release_supported, end) && - pull8(ppReadPackedMsg, &phy->nmm_modes_supported, end)); -} - - -static uint8_t unpack_pnf_phy_value(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_pnf_phy_t* value = (nfapi_pnf_phy_t*)tlv; - return ( pull16(ppReadPackedMsg, &value->number_of_phys, end) && - unpackarray(ppReadPackedMsg, value->phy, sizeof(nfapi_pnf_phy_info_t), NFAPI_MAX_PNF_PHY, value->number_of_phys, end, &unpack_pnf_phy_info)); -} - -static uint8_t unpack_pnf_rf_info(void* elem, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_pnf_rf_info_t* rf = (nfapi_pnf_rf_info_t*)elem; - - return( pull16(ppReadPackedMsg, &rf->rf_config_index, end) && - pull16(ppReadPackedMsg, &rf->band, end) && - pulls16(ppReadPackedMsg, &rf->maximum_transmit_power, end) && - pulls16(ppReadPackedMsg, &rf->minimum_transmit_power, end) && - pull8(ppReadPackedMsg, &rf->number_of_antennas_suppported, end) && - pull32(ppReadPackedMsg, &rf->minimum_downlink_frequency, end) && - pull32(ppReadPackedMsg, &rf->maximum_downlink_frequency, end) && - pull32(ppReadPackedMsg, &rf->minimum_uplink_frequency, end) && - pull32(ppReadPackedMsg, &rf->maximum_uplink_frequency, end)); - -} -static uint8_t unpack_pnf_rf_value(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_pnf_rf_t* value = (nfapi_pnf_rf_t*)tlv; - - return ( pull16(ppReadPackedMsg, &value->number_of_rfs, end) && - unpackarray(ppReadPackedMsg, value->rf, sizeof(nfapi_pnf_rf_info_t), NFAPI_MAX_PNF_RF, value->number_of_rfs, end, &unpack_pnf_rf_info)); -} - -static uint8_t unpack_pnf_phy_rel10_info(void* elem, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_pnf_phy_rel10_info_t* phy = (nfapi_pnf_phy_rel10_info_t*)elem; - - return( pull16(ppReadPackedMsg, &phy->phy_config_index, end) && - pull16(ppReadPackedMsg, &phy->transmission_mode_7_supported, end) && - pull16(ppReadPackedMsg, &phy->transmission_mode_8_supported, end) && - pull16(ppReadPackedMsg, &phy->two_antenna_ports_for_pucch, end) && - pull16(ppReadPackedMsg, &phy->transmission_mode_9_supported, end) && - pull16(ppReadPackedMsg, &phy->simultaneous_pucch_pusch, end) && - pull16(ppReadPackedMsg, &phy->four_layer_tx_with_tm3_and_tm4, end)); - - -} -static uint8_t unpack_pnf_phy_rel10_value(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_pnf_phy_rel10_t* value = (nfapi_pnf_phy_rel10_t*)tlv; - - return ( pull16(ppReadPackedMsg, &value->number_of_phys, end) && - unpackarray(ppReadPackedMsg, value->phy, sizeof(nfapi_pnf_phy_rel10_info_t), NFAPI_MAX_PNF_PHY, value->number_of_phys, end, &unpack_pnf_phy_rel10_info)); - -} - - -static uint8_t unpack_pnf_phy_rel11_info(void* elem, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_pnf_phy_rel11_info_t* phy = (nfapi_pnf_phy_rel11_info_t*)elem; - - return( pull16(ppReadPackedMsg, &phy->phy_config_index, end) && - pull16(ppReadPackedMsg, &phy->edpcch_supported, end) && - pull16(ppReadPackedMsg, &phy->multi_ack_csi_reporting, end ) && - pull16(ppReadPackedMsg, &phy->pucch_tx_diversity, end) && - pull16(ppReadPackedMsg, &phy->ul_comp_supported, end) && - pull16(ppReadPackedMsg, &phy->transmission_mode_5_supported, end)); -} - -static uint8_t unpack_pnf_phy_rel11_value(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_pnf_phy_rel11_t* value = (nfapi_pnf_phy_rel11_t*)tlv; - - return ( pull16(ppReadPackedMsg, &value->number_of_phys, end) && - unpackarray(ppReadPackedMsg, value->phy, sizeof(nfapi_pnf_phy_rel11_info_t), NFAPI_MAX_PNF_PHY, value->number_of_phys, end, &unpack_pnf_phy_rel11_info)); - -} - -static uint8_t unpack_phy_phy_rel12_info(void* elem, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_pnf_phy_rel12_info_t* phy = (nfapi_pnf_phy_rel12_info_t*)elem; - - return( pull16(ppReadPackedMsg, &phy->phy_config_index, end) && - pull16(ppReadPackedMsg, &phy->csi_subframe_set, end) && - pull16(ppReadPackedMsg, &phy->enhanced_4tx_codebook, end) && - pull16(ppReadPackedMsg, &phy->drs_supported, end) && - pull16(ppReadPackedMsg, &phy->ul_64qam_supported, end) && - pull16(ppReadPackedMsg, &phy->transmission_mode_10_supported, end) && - pull16(ppReadPackedMsg, &phy->alternative_bts_indices, end)); -} - -static uint8_t unpack_pnf_phy_rel12_value(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_pnf_phy_rel12_t* value = (nfapi_pnf_phy_rel12_t*)tlv; - - return (pull16(ppReadPackedMsg, &value->number_of_phys, end) && - unpackarray(ppReadPackedMsg, value->phy, sizeof(nfapi_pnf_phy_rel12_t), NFAPI_MAX_PNF_PHY, value->number_of_phys, end, &unpack_phy_phy_rel12_info)); - -} - -static uint8_t unpack_pnf_phy_rel13_info(void *elem, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_pnf_phy_rel13_info_t* phy = (nfapi_pnf_phy_rel13_info_t*)elem; - - return( pull16(ppReadPackedMsg, &phy->phy_config_index, end) && - pull16(ppReadPackedMsg, &phy->pucch_format4_supported, end) && - pull16(ppReadPackedMsg, &phy->pucch_format5_supported, end) && - pull16(ppReadPackedMsg, &phy->more_than_5_ca_support, end) && - pull16(ppReadPackedMsg, &phy->laa_supported, end) && - pull16(ppReadPackedMsg, &phy->laa_ending_in_dwpts_supported, end) && - pull16(ppReadPackedMsg, &phy->laa_starting_in_second_slot_supported, end) && - pull16(ppReadPackedMsg, &phy->beamforming_supported, end) && - pull16(ppReadPackedMsg, &phy->csi_rs_enhancement_supported, end) && - pull16(ppReadPackedMsg, &phy->drms_enhancement_supported, end) && - pull16(ppReadPackedMsg, &phy->srs_enhancement_supported, end)); -} - -static uint8_t unpack_pnf_phy_rel13_value(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_pnf_phy_rel13_t* value = (nfapi_pnf_phy_rel13_t*)tlv; - - return ( pull16(ppReadPackedMsg, &value->number_of_phys, end) && - unpackarray(ppReadPackedMsg, value->phy, sizeof(nfapi_pnf_phy_rel13_info_t), NFAPI_MAX_PNF_PHY, value->number_of_phys, end, &unpack_pnf_phy_rel13_info)); -} - -static uint8_t unpack_pnf_phy_rel13_nb_info_info(void *elem, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_pnf_phy_rel13_nb_iot_info_t* phy = (nfapi_pnf_phy_rel13_nb_iot_info_t*)elem; - - return( pull16(ppReadPackedMsg, &phy->phy_config_index, end) && - pull16(ppReadPackedMsg, &phy->number_of_rfs, end) && - unpackarray(ppReadPackedMsg, phy->rf_config, sizeof(nfapi_rf_config_info_t), NFAPI_MAX_PNF_PHY_RF_CONFIG, phy->number_of_rfs, end, &unpack_rf_config_info) && - pull16(ppReadPackedMsg, &phy->number_of_rf_exclusions, end) && - unpackarray(ppReadPackedMsg, phy->excluded_rf_config, sizeof(nfapi_rf_config_info_t), NFAPI_MAX_PNF_PHY_RF_CONFIG, phy->number_of_rf_exclusions, end, &unpack_rf_config_info) && - pull8(ppReadPackedMsg, &phy->number_of_dl_layers_supported, end) && - pull8(ppReadPackedMsg, &phy->number_of_ul_layers_supported, end) && - pull16(ppReadPackedMsg, &phy->maximum_3gpp_release_supported, end) && - pull8(ppReadPackedMsg, &phy->nmm_modes_supported, end)); -} - -static uint8_t unpack_pnf_phy_rel13_nb_iot_value(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_pnf_phy_rel13_nb_iot_t* value = (nfapi_pnf_phy_rel13_nb_iot_t*)tlv; - - return ( pull16(ppReadPackedMsg, &value->number_of_phys, end) && - unpackarray(ppReadPackedMsg, value->phy, sizeof(nfapi_pnf_phy_rel13_nb_iot_info_t), NFAPI_MAX_PNF_PHY, value->number_of_phys, end, &unpack_pnf_phy_rel13_nb_info_info)); -} - -static uint8_t unpack_nr_pnf_param_response(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t* config) -{ - nfapi_nr_pnf_param_response_t *pNfapiMsg = (nfapi_nr_pnf_param_response_t*)msg; - - unpack_tlv_t unpack_fns[] = - { - { NFAPI_PNF_PARAM_GENERAL_TAG, &pNfapiMsg->pnf_param_general, &unpack_pnf_param_general_value}, - { NFAPI_PNF_PHY_TAG, &pNfapiMsg->pnf_phy, &unpack_pnf_phy_value}, - }; - - return ( pull32(ppReadPackedMsg, &pNfapiMsg->error_code, end) && - unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); -} - - - -static uint8_t unpack_pnf_param_response(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t* config) -{ - nfapi_pnf_param_response_t *pNfapiMsg = (nfapi_pnf_param_response_t*)msg; - - unpack_tlv_t unpack_fns[] = - { - { NFAPI_PNF_PARAM_GENERAL_TAG, &pNfapiMsg->pnf_param_general, &unpack_pnf_param_general_value}, - { NFAPI_PNF_PHY_TAG, &pNfapiMsg->pnf_phy, &unpack_pnf_phy_value}, - { NFAPI_PNF_RF_TAG, &pNfapiMsg->pnf_rf, &unpack_pnf_rf_value}, - { NFAPI_PNF_PHY_REL10_TAG, &pNfapiMsg->pnf_phy_rel10, &unpack_pnf_phy_rel10_value}, - { NFAPI_PNF_PHY_REL11_TAG, &pNfapiMsg->pnf_phy_rel11, &unpack_pnf_phy_rel11_value}, - { NFAPI_PNF_PHY_REL12_TAG, &pNfapiMsg->pnf_phy_rel12, &unpack_pnf_phy_rel12_value}, - { NFAPI_PNF_PHY_REL13_TAG, &pNfapiMsg->pnf_phy_rel13, &unpack_pnf_phy_rel13_value}, - { NFAPI_PNF_PHY_REL13_NB_IOT_TAG, &pNfapiMsg->pnf_phy_rel13_nb_iot, &unpack_pnf_phy_rel13_nb_iot_value}, - - }; - - return ( pull32(ppReadPackedMsg, &pNfapiMsg->error_code, end) && - unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); -} - - -static uint8_t unpack_phy_rf_config_info(void* elem, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_phy_rf_config_info_t* rf = (nfapi_phy_rf_config_info_t*)elem; - - return( pull16(ppReadPackedMsg, &rf->phy_id, end) && - pull16(ppReadPackedMsg, &rf->phy_config_index, end) && - pull16(ppReadPackedMsg, &rf->rf_config_index, end)); - -} - -static uint8_t unpack_pnf_phy_rf_config_value(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_pnf_phy_rf_config_t* value = (nfapi_pnf_phy_rf_config_t*)tlv; - - return ( pull16(ppReadPackedMsg, &value->number_phy_rf_config_info, end) && - unpackarray(ppReadPackedMsg, value->phy_rf_config, sizeof(nfapi_phy_rf_config_info_t), NFAPI_MAX_PHY_RF_INSTANCES, value->number_phy_rf_config_info, end, &unpack_phy_rf_config_info)); -} - -static uint8_t unpack_nr_pnf_config_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t* config) -{ - nfapi_nr_pnf_config_request_t *pNfapiMsg = (nfapi_nr_pnf_config_request_t*)msg; - - unpack_tlv_t unpack_fns[] = - { - { NFAPI_PNF_PHY_RF_TAG, &pNfapiMsg->pnf_phy_rf_config, &unpack_pnf_phy_rf_config_value}, - }; - - return unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension); -} - - - -static uint8_t unpack_pnf_config_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t* config) -{ - nfapi_pnf_config_request_t *pNfapiMsg = (nfapi_pnf_config_request_t*)msg; - - unpack_tlv_t unpack_fns[] = - { - { NFAPI_PNF_PHY_RF_TAG, &pNfapiMsg->pnf_phy_rf_config, &unpack_pnf_phy_rf_config_value}, - }; - - return unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension); -} - - -static uint8_t unpack_nr_pnf_config_response(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t* config) -{ - nfapi_nr_pnf_config_response_t *pNfapiMsg = (nfapi_nr_pnf_config_response_t*)msg; - - unpack_tlv_t unpack_fns[] = - { - }; - - return ( pull32(ppReadPackedMsg, &pNfapiMsg->error_code, end) && - unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &(pNfapiMsg->vendor_extension))); - -} - -static uint8_t unpack_pnf_config_response(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t* config) -{ - nfapi_pnf_config_response_t *pNfapiMsg = (nfapi_pnf_config_response_t*)msg; - - unpack_tlv_t unpack_fns[] = - { - }; - - return ( pull32(ppReadPackedMsg, &pNfapiMsg->error_code, end) && - unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &(pNfapiMsg->vendor_extension))); - -} - -static uint8_t unpack_nr_pnf_start_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t* config) -{ - nfapi_nr_pnf_start_request_t *pNfapiMsg = (nfapi_nr_pnf_start_request_t*)msg; - - unpack_tlv_t unpack_fns[] = - { - }; - - return unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &(pNfapiMsg->vendor_extension)); -} - - -static uint8_t unpack_pnf_start_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t* config) -{ - nfapi_pnf_start_request_t *pNfapiMsg = (nfapi_pnf_start_request_t*)msg; - - unpack_tlv_t unpack_fns[] = - { - }; - - return unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &(pNfapiMsg->vendor_extension)); -} - - -static uint8_t unpack_pnf_start_response(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t* config) -{ - nfapi_pnf_start_response_t *pNfapiMsg = (nfapi_pnf_start_response_t*)msg; - - unpack_tlv_t unpack_fns[] = - { - }; - - return ( pull32(ppReadPackedMsg, &pNfapiMsg->error_code, end ) && - unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &(pNfapiMsg->vendor_extension))); -} - -static uint8_t unpack_nr_pnf_start_response(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t* config) -{ - nfapi_nr_pnf_start_response_t *pNfapiMsg = (nfapi_nr_pnf_start_response_t*)msg; - - unpack_tlv_t unpack_fns[] = - { - }; - - return ( pull32(ppReadPackedMsg, &pNfapiMsg->error_code, end ) && - unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &(pNfapiMsg->vendor_extension))); -} - - -static uint8_t unpack_pnf_stop_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t* config) -{ - nfapi_pnf_stop_request_t *pNfapiMsg = (nfapi_pnf_stop_request_t*)msg; - - unpack_tlv_t unpack_fns[] = - { - }; - - return unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &(pNfapiMsg->vendor_extension)); -} - -static uint8_t unpack_pnf_stop_response(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t* config) -{ - nfapi_pnf_stop_response_t *pNfapiMsg = (nfapi_pnf_stop_response_t*)msg; - - unpack_tlv_t unpack_fns[] = - { - }; - - return ( pull32(ppReadPackedMsg, &pNfapiMsg->error_code, end) && - unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &(pNfapiMsg->vendor_extension))); - -} - -static uint8_t unpack_param_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t* config) -{ - nfapi_param_request_t *pNfapiMsg = (nfapi_param_request_t*)msg; - - unpack_tlv_t unpack_fns[] = - { - }; - - return unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &(pNfapiMsg->vendor_extension)); -} - -static uint8_t unpack_nr_param_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t* config) -{ - nfapi_nr_param_request_scf_t *pNfapiMsg = (nfapi_nr_param_request_scf_t*)msg; - - unpack_tlv_t unpack_fns[] = - { - }; - - return unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &(pNfapiMsg->vendor_extension)); -} - -static uint8_t unpack_param_response(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t* config) -{ - nfapi_param_response_t *pNfapiMsg = (nfapi_param_response_t*)msg; - - unpack_tlv_t unpack_fns[] = - { - { NFAPI_L1_STATUS_PHY_STATE_TAG, &pNfapiMsg->l1_status.phy_state, &unpack_uint16_tlv_value}, - - { NFAPI_PHY_CAPABILITIES_DL_BANDWIDTH_SUPPORT_TAG, &pNfapiMsg->phy_capabilities.dl_bandwidth_support, &unpack_uint16_tlv_value}, - { NFAPI_PHY_CAPABILITIES_UL_BANDWIDTH_SUPPORT_TAG, &pNfapiMsg->phy_capabilities.ul_bandwidth_support, &unpack_uint16_tlv_value}, - { NFAPI_PHY_CAPABILITIES_DL_MODULATION_SUPPORT_TAG, &pNfapiMsg->phy_capabilities.dl_modulation_support, &unpack_uint16_tlv_value}, - { NFAPI_PHY_CAPABILITIES_UL_MODULATION_SUPPORT_TAG, &pNfapiMsg->phy_capabilities.ul_modulation_support, &unpack_uint16_tlv_value}, - { NFAPI_PHY_CAPABILITIES_PHY_ANTENNA_CAPABILITY_TAG, &pNfapiMsg->phy_capabilities.phy_antenna_capability, &unpack_uint16_tlv_value}, - { NFAPI_PHY_CAPABILITIES_RELEASE_CAPABILITY_TAG, &pNfapiMsg->phy_capabilities.release_capability, &unpack_uint16_tlv_value}, - { NFAPI_PHY_CAPABILITIES_MBSFN_CAPABILITY_TAG, &pNfapiMsg->phy_capabilities.mbsfn_capability, &unpack_uint16_tlv_value}, - - { NFAPI_LAA_CAPABILITY_LAA_SUPPORT_TAG, &pNfapiMsg->laa_capability.laa_support, &unpack_uint16_tlv_value}, - { NFAPI_LAA_CAPABILITY_PD_SENSING_LBT_SUPPORT_TAG, &pNfapiMsg->laa_capability.pd_sensing_lbt_support, &unpack_uint16_tlv_value}, - { NFAPI_LAA_CAPABILITY_MULTI_CARRIER_LBT_SUPPORT_TAG, &pNfapiMsg->laa_capability.multi_carrier_lbt_support, &unpack_uint16_tlv_value}, - { NFAPI_LAA_CAPABILITY_PARTIAL_SF_SUPPORT_TAG, &pNfapiMsg->laa_capability.partial_sf_support, &unpack_uint16_tlv_value}, - - { NFAPI_SUBFRAME_CONFIG_DUPLEX_MODE_TAG, &pNfapiMsg->subframe_config.duplex_mode, &unpack_uint16_tlv_value}, - { NFAPI_SUBFRAME_CONFIG_PCFICH_POWER_OFFSET_TAG, &pNfapiMsg->subframe_config.pcfich_power_offset, &unpack_uint16_tlv_value}, - { NFAPI_SUBFRAME_CONFIG_PB_TAG, &pNfapiMsg->subframe_config.pb, &unpack_uint16_tlv_value}, - { NFAPI_SUBFRAME_CONFIG_DL_CYCLIC_PREFIX_TYPE_TAG, &pNfapiMsg->subframe_config.dl_cyclic_prefix_type, &unpack_uint16_tlv_value}, - { NFAPI_SUBFRAME_CONFIG_UL_CYCLIC_PREFIX_TYPE_TAG, &pNfapiMsg->subframe_config.ul_cyclic_prefix_type, &unpack_uint16_tlv_value}, - - { NFAPI_RF_CONFIG_DL_CHANNEL_BANDWIDTH_TAG, &pNfapiMsg->rf_config.dl_channel_bandwidth, &unpack_uint16_tlv_value}, - { NFAPI_RF_CONFIG_UL_CHANNEL_BANDWIDTH_TAG, &pNfapiMsg->rf_config.ul_channel_bandwidth, &unpack_uint16_tlv_value}, - { NFAPI_RF_CONFIG_REFERENCE_SIGNAL_POWER_TAG, &pNfapiMsg->rf_config.reference_signal_power, &unpack_uint16_tlv_value}, - { NFAPI_RF_CONFIG_TX_ANTENNA_PORTS_TAG, &pNfapiMsg->rf_config.tx_antenna_ports, &unpack_uint16_tlv_value}, - { NFAPI_RF_CONFIG_RX_ANTENNA_PORTS_TAG, &pNfapiMsg->rf_config.rx_antenna_ports, &unpack_uint16_tlv_value}, - - { NFAPI_PHICH_CONFIG_PHICH_RESOURCE_TAG, &pNfapiMsg->phich_config.phich_resource, &unpack_uint16_tlv_value}, - { NFAPI_PHICH_CONFIG_PHICH_DURATION_TAG, &pNfapiMsg->phich_config.phich_duration, &unpack_uint16_tlv_value}, - { NFAPI_PHICH_CONFIG_PHICH_POWER_OFFSET_TAG, &pNfapiMsg->phich_config.phich_power_offset, &unpack_uint16_tlv_value}, - - { NFAPI_SCH_CONFIG_PRIMARY_SYNCHRONIZATION_SIGNAL_EPRE_EPRERS_TAG, &pNfapiMsg->sch_config.primary_synchronization_signal_epre_eprers, &unpack_uint16_tlv_value}, - { NFAPI_SCH_CONFIG_SECONDARY_SYNCHRONIZATION_SIGNAL_EPRE_EPRERS_TAG, &pNfapiMsg->sch_config.secondary_synchronization_signal_epre_eprers, &unpack_uint16_tlv_value}, - { NFAPI_SCH_CONFIG_PHYSICAL_CELL_ID_TAG, &pNfapiMsg->sch_config.physical_cell_id, &unpack_uint16_tlv_value}, - - { NFAPI_PRACH_CONFIG_CONFIGURATION_INDEX_TAG, &pNfapiMsg->prach_config.configuration_index, &unpack_uint16_tlv_value}, - { NFAPI_PRACH_CONFIG_ROOT_SEQUENCE_INDEX_TAG, &pNfapiMsg->prach_config.root_sequence_index, &unpack_uint16_tlv_value}, - { NFAPI_PRACH_CONFIG_ZERO_CORRELATION_ZONE_CONFIGURATION_TAG, &pNfapiMsg->prach_config.zero_correlation_zone_configuration, &unpack_uint16_tlv_value}, - { NFAPI_PRACH_CONFIG_HIGH_SPEED_FLAG_TAG, &pNfapiMsg->prach_config.high_speed_flag, &unpack_uint16_tlv_value}, - { NFAPI_PRACH_CONFIG_FREQUENCY_OFFSET_TAG, &pNfapiMsg->prach_config.frequency_offset, &unpack_uint16_tlv_value}, - - { NFAPI_PUSCH_CONFIG_HOPPING_MODE_TAG, &pNfapiMsg->pusch_config.hopping_mode, &unpack_uint16_tlv_value}, - { NFAPI_PUSCH_CONFIG_HOPPING_OFFSET_TAG, &pNfapiMsg->pusch_config.hopping_offset, &unpack_uint16_tlv_value}, - { NFAPI_PUSCH_CONFIG_NUMBER_OF_SUBBANDS_TAG, &pNfapiMsg->pusch_config.number_of_subbands, &unpack_uint16_tlv_value}, - - { NFAPI_PUCCH_CONFIG_DELTA_PUCCH_SHIFT_TAG, &pNfapiMsg->pucch_config.delta_pucch_shift, &unpack_uint16_tlv_value}, - { NFAPI_PUCCH_CONFIG_N_CQI_RB_TAG, &pNfapiMsg->pucch_config.n_cqi_rb, &unpack_uint16_tlv_value}, - { NFAPI_PUCCH_CONFIG_N_AN_CS_TAG, &pNfapiMsg->pucch_config.n_an_cs, &unpack_uint16_tlv_value}, - { NFAPI_PUCCH_CONFIG_N1_PUCCH_AN_TAG, &pNfapiMsg->pucch_config.n1_pucch_an, &unpack_uint16_tlv_value}, - - { NFAPI_SRS_CONFIG_BANDWIDTH_CONFIGURATION_TAG, &pNfapiMsg->srs_config.bandwidth_configuration, &unpack_uint16_tlv_value}, - { NFAPI_SRS_CONFIG_MAX_UP_PTS_TAG, &pNfapiMsg->srs_config.max_up_pts, &unpack_uint16_tlv_value}, - { NFAPI_SRS_CONFIG_SRS_SUBFRAME_CONFIGURATION_TAG, &pNfapiMsg->srs_config.srs_subframe_configuration, &unpack_uint16_tlv_value}, - { NFAPI_SRS_CONFIG_SRS_ACKNACK_SRS_SIMULTANEOUS_TRANSMISSION_TAG, &pNfapiMsg->srs_config.srs_acknack_srs_simultaneous_transmission, &unpack_uint16_tlv_value}, - - { NFAPI_UPLINK_REFERENCE_SIGNAL_CONFIG_UPLINK_RS_HOPPING_TAG, &pNfapiMsg->uplink_reference_signal_config.uplink_rs_hopping, &unpack_uint16_tlv_value}, - { NFAPI_UPLINK_REFERENCE_SIGNAL_CONFIG_GROUP_ASSIGNMENT_TAG, &pNfapiMsg->uplink_reference_signal_config.group_assignment, &unpack_uint16_tlv_value}, - { NFAPI_UPLINK_REFERENCE_SIGNAL_CONFIG_CYCLIC_SHIFT_1_FOR_DRMS_TAG, &pNfapiMsg->uplink_reference_signal_config.cyclic_shift_1_for_drms, &unpack_uint16_tlv_value}, - - { NFAPI_TDD_FRAME_STRUCTURE_SUBFRAME_ASSIGNMENT_TAG, &pNfapiMsg->tdd_frame_structure_config.subframe_assignment, &unpack_uint16_tlv_value}, - { NFAPI_TDD_FRAME_STRUCTURE_SPECIAL_SUBFRAME_PATTERNS_TAG, &pNfapiMsg->tdd_frame_structure_config.special_subframe_patterns, &unpack_uint16_tlv_value}, - - { NFAPI_L23_CONFIG_DATA_REPORT_MODE_TAG, &pNfapiMsg->l23_config.data_report_mode, &unpack_uint16_tlv_value}, - { NFAPI_L23_CONFIG_SFNSF_TAG, &pNfapiMsg->l23_config.sfnsf, &unpack_uint16_tlv_value}, - - { NFAPI_NFAPI_P7_VNF_ADDRESS_IPV4_TAG, &pNfapiMsg->nfapi_config.p7_vnf_address_ipv4, &unpack_ipv4_address_value}, - { NFAPI_NFAPI_P7_VNF_ADDRESS_IPV6_TAG, &pNfapiMsg->nfapi_config.p7_vnf_address_ipv6, &unpack_ipv6_address_value}, - { NFAPI_NFAPI_P7_VNF_PORT_TAG, &pNfapiMsg->nfapi_config.p7_vnf_port, &unpack_uint16_tlv_value}, - { NFAPI_NFAPI_P7_PNF_ADDRESS_IPV4_TAG, &pNfapiMsg->nfapi_config.p7_pnf_address_ipv4, &unpack_ipv4_address_value}, - { NFAPI_NFAPI_P7_PNF_ADDRESS_IPV6_TAG, &pNfapiMsg->nfapi_config.p7_pnf_address_ipv6, &unpack_ipv6_address_value}, - { NFAPI_NFAPI_P7_PNF_PORT_TAG, &pNfapiMsg->nfapi_config.p7_pnf_port, &unpack_uint16_tlv_value}, - { NFAPI_NFAPI_DOWNLINK_UES_PER_SUBFRAME_TAG, &pNfapiMsg->nfapi_config.dl_ue_per_sf, &unpack_uint8_tlv_value}, - { NFAPI_NFAPI_UPLINK_UES_PER_SUBFRAME_TAG, &pNfapiMsg->nfapi_config.ul_ue_per_sf, &unpack_uint8_tlv_value}, - { NFAPI_NFAPI_RF_BANDS_TAG, &pNfapiMsg->nfapi_config.rf_bands, &unpack_rf_bands_value}, - { NFAPI_NFAPI_TIMING_WINDOW_TAG, &pNfapiMsg->nfapi_config.timing_window, &unpack_uint8_tlv_value}, - { NFAPI_NFAPI_TIMING_INFO_MODE_TAG, &pNfapiMsg->nfapi_config.timing_info_mode, &unpack_uint8_tlv_value}, - { NFAPI_NFAPI_TIMING_INFO_PERIOD_TAG, &pNfapiMsg->nfapi_config.timing_info_period, &unpack_uint8_tlv_value}, - { NFAPI_NFAPI_MAXIMUM_TRANSMIT_POWER_TAG, &pNfapiMsg->nfapi_config.max_transmit_power, &unpack_uint16_tlv_value}, - { NFAPI_NFAPI_EARFCN_TAG, &pNfapiMsg->nfapi_config.earfcn, &unpack_uint16_tlv_value}, - { NFAPI_NFAPI_NMM_GSM_FREQUENCY_BANDS_TAG, &pNfapiMsg->nfapi_config.nmm_gsm_frequency_bands, &unpack_nmm_frequency_bands_value}, - { NFAPI_NFAPI_NMM_UMTS_FREQUENCY_BANDS_TAG, &pNfapiMsg->nfapi_config.nmm_umts_frequency_bands, &unpack_nmm_frequency_bands_value}, - { NFAPI_NFAPI_NMM_LTE_FREQUENCY_BANDS_TAG, &pNfapiMsg->nfapi_config.nmm_lte_frequency_bands, &unpack_nmm_frequency_bands_value}, - { NFAPI_NFAPI_NMM_UPLINK_RSSI_SUPPORTED_TAG, &pNfapiMsg->nfapi_config.nmm_uplink_rssi_supported, &unpack_uint8_tlv_value}, - - }; - - return ( pull8(ppReadPackedMsg, &pNfapiMsg->error_code, end) && - pull8(ppReadPackedMsg, &pNfapiMsg->num_tlv, end) && - unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); - -} - -static uint8_t unpack_nr_param_response(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t* config) -{ - nfapi_nr_param_response_scf_t *pNfapiMsg = (nfapi_nr_param_response_scf_t*)msg; - - unpack_tlv_t unpack_fns[] = - { - { NFAPI_NR_PARAM_TLV_RELEASE_CAPABILITY_TAG, &(pNfapiMsg->cell_param.release_capability), &unpack_uint16_tlv_value}, - { NFAPI_NR_PARAM_TLV_PHY_STATE_TAG, &(pNfapiMsg->cell_param.phy_state),&unpack_uint16_tlv_value}, - { NFAPI_NR_PARAM_TLV_SKIP_BLANK_DL_CONFIG_TAG, &(pNfapiMsg->cell_param.skip_blank_dl_config), &unpack_uint8_tlv_value}, - { NFAPI_NR_PARAM_TLV_SKIP_BLANK_UL_CONFIG_TAG, &(pNfapiMsg->cell_param.skip_blank_ul_config), &unpack_uint8_tlv_value}, - { NFAPI_NR_PARAM_TLV_NUM_CONFIG_TLVS_TO_REPORT_TAG, &(pNfapiMsg->cell_param.num_config_tlvs_to_report ), &unpack_uint16_tlv_value}, - - { NFAPI_NR_PARAM_TLV_CYCLIC_PREFIX_TAG, &(pNfapiMsg->carrier_param.cyclic_prefix), &unpack_uint8_tlv_value}, - { NFAPI_NR_PARAM_TLV_SUPPORTED_SUBCARRIER_SPACINGS_DL_TAG, &(pNfapiMsg->carrier_param.supported_subcarrier_spacings_dl), &unpack_uint16_tlv_value}, - { NFAPI_NR_PARAM_TLV_SUPPORTED_BANDWIDTH_DL_TAG, &(pNfapiMsg->carrier_param.supported_bandwidth_dl), &unpack_uint16_tlv_value}, - { NFAPI_NR_PARAM_TLV_SUPPORTED_SUBCARRIER_SPACINGS_UL_TAG, &(pNfapiMsg->carrier_param.supported_subcarrier_spacings_ul), &unpack_uint8_tlv_value}, - { NFAPI_NR_PARAM_TLV_SUPPORTED_BANDWIDTH_UL_TAG, &(pNfapiMsg->carrier_param.supported_bandwidth_ul), &unpack_uint16_tlv_value}, - - - { NFAPI_NR_PARAM_TLV_CCE_MAPPING_TYPE_TAG, &(pNfapiMsg->pdcch_param.cce_mapping_type), &unpack_uint8_tlv_value}, - { NFAPI_NR_PARAM_TLV_CORESET_OUTSIDE_FIRST_3_OFDM_SYMS_OF_SLOT_TAG, &(pNfapiMsg->pdcch_param.coreset_outside_first_3_of_ofdm_syms_of_slot), &unpack_uint8_tlv_value}, - { NFAPI_NR_PARAM_TLV_PRECODER_GRANULARITY_CORESET_TAG, &(pNfapiMsg->pdcch_param.coreset_precoder_granularity_coreset), &unpack_uint8_tlv_value}, - { NFAPI_NR_PARAM_TLV_PDCCH_MU_MIMO_TAG, &(pNfapiMsg->pdcch_param.pdcch_mu_mimo), &unpack_uint8_tlv_value}, - { NFAPI_NR_PARAM_TLV_PDCCH_PRECODER_CYCLING_TAG, &(pNfapiMsg->pdcch_param.pdcch_precoder_cycling), &unpack_uint8_tlv_value}, - { NFAPI_NR_PARAM_TLV_MAX_PDCCHS_PER_SLOT_TAG, &(pNfapiMsg->pdcch_param.max_pdcch_per_slot), &unpack_uint8_tlv_value}, - - { NFAPI_NR_PARAM_TLV_PUCCH_FORMATS_TAG, &(pNfapiMsg->pucch_param.pucch_formats), &unpack_uint8_tlv_value}, - { NFAPI_NR_PARAM_TLV_MAX_PUCCHS_PER_SLOT_TAG, &(pNfapiMsg->pucch_param.max_pucchs_per_slot), &unpack_uint8_tlv_value}, - - { NFAPI_NR_PARAM_TLV_PDSCH_MAPPING_TYPE_TAG, &(pNfapiMsg->pdsch_param.pdsch_mapping_type), &unpack_uint8_tlv_value}, - { NFAPI_NR_PARAM_TLV_PDSCH_ALLOCATION_TYPES_TAG, &(pNfapiMsg->pdsch_param.pdsch_allocation_types), &unpack_uint8_tlv_value}, - { NFAPI_NR_PARAM_TLV_PDSCH_VRB_TO_PRB_MAPPING_TAG, &(pNfapiMsg->pdsch_param.pdsch_vrb_to_prb_mapping), &unpack_uint8_tlv_value}, - { NFAPI_NR_PARAM_TLV_PDSCH_CBG_TAG, &(pNfapiMsg->pdsch_param.pdsch_cbg), &unpack_uint8_tlv_value}, - { NFAPI_NR_PARAM_TLV_PDSCH_DMRS_CONFIG_TYPES_TAG, &(pNfapiMsg->pdsch_param.pdsch_dmrs_config_types), &unpack_uint8_tlv_value}, - { NFAPI_NR_PARAM_TLV_PDSCH_DMRS_MAX_LENGTH_TAG, &(pNfapiMsg->pdsch_param.pdsch_dmrs_max_length), &unpack_uint8_tlv_value}, - { NFAPI_NR_PARAM_TLV_PDSCH_DMRS_ADDITIONAL_POS_TAG, &(pNfapiMsg->pdsch_param.pdsch_dmrs_additional_pos), &unpack_uint8_tlv_value}, - { NFAPI_NR_PARAM_TLV_MAX_PDSCH_S_YBS_PER_SLOT_TAG, &(pNfapiMsg->pdsch_param.max_pdsch_tbs_per_slot), &unpack_uint8_tlv_value}, - { NFAPI_NR_PARAM_TLV_MAX_NUMBER_MIMO_LAYERS_PDSCH_TAG, &(pNfapiMsg->pdsch_param.max_number_mimo_layers_pdsch), &unpack_uint8_tlv_value}, - { NFAPI_NR_PARAM_TLV_MAX_MU_MIMO_USERS_DL_TAG, &(pNfapiMsg->pdsch_param.max_mu_mimo_users_dl), &unpack_uint8_tlv_value}, - { NFAPI_NR_PARAM_TLV_PDSCH_DATA_IN_DMRS_SYMBOLS_TAG, &(pNfapiMsg->pdsch_param.pdsch_data_in_dmrs_symbols), &unpack_uint8_tlv_value}, - { NFAPI_NR_PARAM_TLV_PREMPTION_SUPPORT_TAG, &(pNfapiMsg->pdsch_param.premption_support), &unpack_uint8_tlv_value}, - { NFAPI_NR_PARAM_TLV_PDSCH_NON_SLOT_SUPPORT_TAG, &(pNfapiMsg->pdsch_param.pdsch_non_slot_support), &unpack_uint8_tlv_value}, - - { NFAPI_NR_PARAM_TLV_UCI_MUX_ULSCH_IN_PUSCH_TAG, &(pNfapiMsg->pusch_param.uci_mux_ulsch_in_pusch), &unpack_uint8_tlv_value}, - { NFAPI_NR_PARAM_TLV_UCI_ONLY_PUSCH_TAG, &(pNfapiMsg->pusch_param.uci_only_pusch), &unpack_uint8_tlv_value}, - { NFAPI_NR_PARAM_TLV_PUSCH_FREQUENCY_HOPPING_TAG, &(pNfapiMsg->pusch_param.pusch_frequency_hopping), &unpack_uint8_tlv_value}, - { NFAPI_NR_PARAM_TLV_PUSCH_DMRS_CONFIG_TYPES_TAG, &(pNfapiMsg->pusch_param.pusch_dmrs_config_types), &unpack_uint8_tlv_value}, - { NFAPI_NR_PARAM_TLV_PUSCH_DMRS_MAX_LEN_TAG, &(pNfapiMsg->pusch_param.pusch_dmrs_max_len), &unpack_uint8_tlv_value}, - { NFAPI_NR_PARAM_TLV_PUSCH_DMRS_ADDITIONAL_POS_TAG, &(pNfapiMsg->pusch_param.pusch_dmrs_additional_pos), &unpack_uint8_tlv_value}, - { NFAPI_NR_PARAM_TLV_PUSCH_CBG_TAG, &(pNfapiMsg->pusch_param.pusch_cbg), &unpack_uint8_tlv_value}, - { NFAPI_NR_PARAM_TLV_PUSCH_MAPPING_TYPE_TAG, &(pNfapiMsg->pusch_param.pusch_mapping_type), &unpack_uint8_tlv_value}, - { NFAPI_NR_PARAM_TLV_PUSCH_ALLOCATION_TYPES_TAG, &(pNfapiMsg->pusch_param.pusch_allocation_types), &unpack_uint8_tlv_value}, - { NFAPI_NR_PARAM_TLV_PUSCH_VRB_TO_PRB_MAPPING_TAG, &(pNfapiMsg->pusch_param.pusch_vrb_to_prb_mapping), &unpack_uint8_tlv_value}, - { NFAPI_NR_PARAM_TLV_PUSCH_MAX_PTRS_PORTS_TAG, &(pNfapiMsg->pusch_param.pusch_max_ptrs_ports), &unpack_uint8_tlv_value}, - { NFAPI_NR_PARAM_TLV_MAX_PDUSCHS_TBS_PER_SLOT_TAG, &(pNfapiMsg->pusch_param.max_pduschs_tbs_per_slot), &unpack_uint8_tlv_value}, - { NFAPI_NR_PARAM_TLV_MAX_NUMBER_MIMO_LAYERS_NON_CB_PUSCH_TAG, &(pNfapiMsg->pusch_param.max_number_mimo_layers_non_cb_pusch), &unpack_uint8_tlv_value}, - { NFAPI_NR_PARAM_TLV_SUPPORTED_MODULATION_ORDER_UL_TAG, &(pNfapiMsg->pusch_param.supported_modulation_order_ul), &unpack_uint8_tlv_value}, - { NFAPI_NR_PARAM_TLV_MAX_MU_MIMO_USERS_UL_TAG, &(pNfapiMsg->pusch_param.max_mu_mimo_users_ul), &unpack_uint8_tlv_value}, - { NFAPI_NR_PARAM_TLV_DFTS_OFDM_SUPPORT_TAG, &(pNfapiMsg->pusch_param.dfts_ofdm_support), &unpack_uint8_tlv_value}, - { NFAPI_NR_PARAM_TLV_PUSCH_AGGREGATION_FACTOR_TAG, &(pNfapiMsg->pusch_param.pusch_aggregation_factor), &unpack_uint8_tlv_value}, - - { NFAPI_NR_PARAM_TLV_PRACH_LONG_FORMATS_TAG, &(pNfapiMsg->prach_param.prach_long_formats), &unpack_uint8_tlv_value}, - { NFAPI_NR_PARAM_TLV_PRACH_SHORT_FORMATS_TAG, &(pNfapiMsg->prach_param.prach_short_formats), &unpack_uint8_tlv_value}, - { NFAPI_NR_PARAM_TLV_PRACH_RESTRICTED_SETS_TAG, &(pNfapiMsg->prach_param.prach_restricted_sets), &unpack_uint8_tlv_value}, - { NFAPI_NR_PARAM_TLV_MAX_PRACH_FD_OCCASIONS_IN_A_SLOT_TAG, &(pNfapiMsg->prach_param.max_prach_fd_occasions_in_a_slot), &unpack_uint8_tlv_value}, - - { NFAPI_NR_PARAM_TLV_RSSI_MEASUREMENT_SUPPORT_TAG, &(pNfapiMsg->measurement_param.rssi_measurement_support), &unpack_uint8_tlv_value}, - //config - { 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}, - { NFAPI_NR_NFAPI_P7_PNF_ADDRESS_IPV4_TAG, &pNfapiMsg->nfapi_config.p7_pnf_address_ipv4, &unpack_ipv4_address_value}, - { 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}, - { NFAPI_NR_NFAPI_TIMING_WINDOW_TAG, &pNfapiMsg->nfapi_config.timing_window, &unpack_uint8_tlv_value}, - { NFAPI_NR_NFAPI_TIMING_INFO_MODE_TAG, &pNfapiMsg->nfapi_config.timing_info_mode, &unpack_uint8_tlv_value}, - { NFAPI_NR_NFAPI_TIMING_INFO_PERIOD_TAG, &pNfapiMsg->nfapi_config.timing_info_period, &unpack_uint8_tlv_value}, - }; - // print ppReadPackedMsg - uint8_t *ptr = *ppReadPackedMsg; - printf("\n Read message unpack_param_response: "); - while(ptr < end){ - printf(" %d ", *ptr); - ptr++; - } - printf("\n"); - - - return ( pull8(ppReadPackedMsg, &pNfapiMsg->error_code, end) && - pull8(ppReadPackedMsg, &pNfapiMsg->num_tlv, end) && - unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); - -} - -static uint8_t unpack_config_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t* config) -{ - nfapi_config_request_t *pNfapiMsg = (nfapi_config_request_t*)msg; - - unpack_tlv_t unpack_fns[] = - { - { NFAPI_SUBFRAME_CONFIG_DUPLEX_MODE_TAG, &pNfapiMsg->subframe_config.duplex_mode, &unpack_uint16_tlv_value}, - { NFAPI_SUBFRAME_CONFIG_PCFICH_POWER_OFFSET_TAG, &pNfapiMsg->subframe_config.pcfich_power_offset, &unpack_uint16_tlv_value}, - { NFAPI_SUBFRAME_CONFIG_PB_TAG, &pNfapiMsg->subframe_config.pb, &unpack_uint16_tlv_value}, - { NFAPI_SUBFRAME_CONFIG_DL_CYCLIC_PREFIX_TYPE_TAG, &pNfapiMsg->subframe_config.dl_cyclic_prefix_type, &unpack_uint16_tlv_value}, - { NFAPI_SUBFRAME_CONFIG_UL_CYCLIC_PREFIX_TYPE_TAG, &pNfapiMsg->subframe_config.ul_cyclic_prefix_type, &unpack_uint16_tlv_value}, - - { NFAPI_RF_CONFIG_DL_CHANNEL_BANDWIDTH_TAG, &pNfapiMsg->rf_config.dl_channel_bandwidth, &unpack_uint16_tlv_value}, - { NFAPI_RF_CONFIG_UL_CHANNEL_BANDWIDTH_TAG, &pNfapiMsg->rf_config.ul_channel_bandwidth, &unpack_uint16_tlv_value}, - { NFAPI_RF_CONFIG_REFERENCE_SIGNAL_POWER_TAG, &pNfapiMsg->rf_config.reference_signal_power, &unpack_uint16_tlv_value}, - { NFAPI_RF_CONFIG_TX_ANTENNA_PORTS_TAG, &pNfapiMsg->rf_config.tx_antenna_ports, &unpack_uint16_tlv_value}, - { NFAPI_RF_CONFIG_RX_ANTENNA_PORTS_TAG, &pNfapiMsg->rf_config.rx_antenna_ports, &unpack_uint16_tlv_value}, - - { NFAPI_PHICH_CONFIG_PHICH_RESOURCE_TAG, &pNfapiMsg->phich_config.phich_resource, &unpack_uint16_tlv_value}, - { NFAPI_PHICH_CONFIG_PHICH_DURATION_TAG, &pNfapiMsg->phich_config.phich_duration, &unpack_uint16_tlv_value}, - { NFAPI_PHICH_CONFIG_PHICH_POWER_OFFSET_TAG, &pNfapiMsg->phich_config.phich_power_offset, &unpack_uint16_tlv_value}, - - { NFAPI_SCH_CONFIG_PRIMARY_SYNCHRONIZATION_SIGNAL_EPRE_EPRERS_TAG, &pNfapiMsg->sch_config.primary_synchronization_signal_epre_eprers, &unpack_uint16_tlv_value}, - { NFAPI_SCH_CONFIG_SECONDARY_SYNCHRONIZATION_SIGNAL_EPRE_EPRERS_TAG, &pNfapiMsg->sch_config.secondary_synchronization_signal_epre_eprers, &unpack_uint16_tlv_value}, - { NFAPI_SCH_CONFIG_PHYSICAL_CELL_ID_TAG, &pNfapiMsg->sch_config.physical_cell_id, &unpack_uint16_tlv_value}, - - { NFAPI_PRACH_CONFIG_CONFIGURATION_INDEX_TAG, &pNfapiMsg->prach_config.configuration_index, &unpack_uint16_tlv_value}, - { NFAPI_PRACH_CONFIG_ROOT_SEQUENCE_INDEX_TAG, &pNfapiMsg->prach_config.root_sequence_index, &unpack_uint16_tlv_value}, - { NFAPI_PRACH_CONFIG_ZERO_CORRELATION_ZONE_CONFIGURATION_TAG, &pNfapiMsg->prach_config.zero_correlation_zone_configuration, &unpack_uint16_tlv_value}, - { NFAPI_PRACH_CONFIG_HIGH_SPEED_FLAG_TAG, &pNfapiMsg->prach_config.high_speed_flag, &unpack_uint16_tlv_value}, - { NFAPI_PRACH_CONFIG_FREQUENCY_OFFSET_TAG, &pNfapiMsg->prach_config.frequency_offset, &unpack_uint16_tlv_value}, - - { NFAPI_PUSCH_CONFIG_HOPPING_MODE_TAG, &pNfapiMsg->pusch_config.hopping_mode, &unpack_uint16_tlv_value}, - { NFAPI_PUSCH_CONFIG_HOPPING_OFFSET_TAG, &pNfapiMsg->pusch_config.hopping_offset, &unpack_uint16_tlv_value}, - { NFAPI_PUSCH_CONFIG_NUMBER_OF_SUBBANDS_TAG, &pNfapiMsg->pusch_config.number_of_subbands, &unpack_uint16_tlv_value}, - - { NFAPI_PUCCH_CONFIG_DELTA_PUCCH_SHIFT_TAG, &pNfapiMsg->pucch_config.delta_pucch_shift, &unpack_uint16_tlv_value}, - { NFAPI_PUCCH_CONFIG_N_CQI_RB_TAG, &pNfapiMsg->pucch_config.n_cqi_rb, &unpack_uint16_tlv_value}, - { NFAPI_PUCCH_CONFIG_N_AN_CS_TAG, &pNfapiMsg->pucch_config.n_an_cs, &unpack_uint16_tlv_value}, - { NFAPI_PUCCH_CONFIG_N1_PUCCH_AN_TAG, &pNfapiMsg->pucch_config.n1_pucch_an, &unpack_uint16_tlv_value}, - - { NFAPI_SRS_CONFIG_BANDWIDTH_CONFIGURATION_TAG, &pNfapiMsg->srs_config.bandwidth_configuration, &unpack_uint16_tlv_value}, - { NFAPI_SRS_CONFIG_MAX_UP_PTS_TAG, &pNfapiMsg->srs_config.max_up_pts, &unpack_uint16_tlv_value}, - { NFAPI_SRS_CONFIG_SRS_SUBFRAME_CONFIGURATION_TAG, &pNfapiMsg->srs_config.srs_subframe_configuration, &unpack_uint16_tlv_value}, - { NFAPI_SRS_CONFIG_SRS_ACKNACK_SRS_SIMULTANEOUS_TRANSMISSION_TAG, &pNfapiMsg->srs_config.srs_acknack_srs_simultaneous_transmission, &unpack_uint16_tlv_value}, - - { NFAPI_UPLINK_REFERENCE_SIGNAL_CONFIG_UPLINK_RS_HOPPING_TAG, &pNfapiMsg->uplink_reference_signal_config.uplink_rs_hopping, &unpack_uint16_tlv_value}, - { NFAPI_UPLINK_REFERENCE_SIGNAL_CONFIG_GROUP_ASSIGNMENT_TAG, &pNfapiMsg->uplink_reference_signal_config.group_assignment, &unpack_uint16_tlv_value}, - { NFAPI_UPLINK_REFERENCE_SIGNAL_CONFIG_CYCLIC_SHIFT_1_FOR_DRMS_TAG, &pNfapiMsg->uplink_reference_signal_config.cyclic_shift_1_for_drms, &unpack_uint16_tlv_value}, - - - { NFAPI_LAA_CONFIG_ED_THRESHOLD_FOR_LBT_FOR_PDSCH_TAG, &pNfapiMsg->laa_config.ed_threshold_lbt_pdsch, &unpack_uint16_tlv_value}, - { NFAPI_LAA_CONFIG_ED_THRESHOLD_FOR_LBT_FOR_DRS_TAG, &pNfapiMsg->laa_config.ed_threshold_lbt_drs, &unpack_uint16_tlv_value}, - { NFAPI_LAA_CONFIG_PD_THRESHOLD_TAG, &pNfapiMsg->laa_config.pd_threshold, &unpack_uint16_tlv_value}, - { NFAPI_LAA_CONFIG_MULTI_CARRIER_TYPE_TAG, &pNfapiMsg->laa_config.multi_carrier_type, &unpack_uint16_tlv_value}, - { NFAPI_LAA_CONFIG_MULTI_CARRIER_TX_TAG, &pNfapiMsg->laa_config.multi_carrier_tx, &unpack_uint16_tlv_value}, - { NFAPI_LAA_CONFIG_MULTI_CARRIER_FREEZE_TAG, &pNfapiMsg->laa_config.multi_carrier_freeze, &unpack_uint16_tlv_value}, - { NFAPI_LAA_CONFIG_TX_ANTENNA_PORTS_FOR_DRS_TAG, &pNfapiMsg->laa_config.tx_antenna_ports_drs, &unpack_uint16_tlv_value}, - { NFAPI_LAA_CONFIG_TRANSMISSION_POWER_FOR_DRS_TAG, &pNfapiMsg->laa_config.tx_power_drs, &unpack_uint16_tlv_value}, - - { NFAPI_EMTC_CONFIG_PBCH_REPETITIONS_ENABLE_R13_TAG, &pNfapiMsg->emtc_config.pbch_repetitions_enable_r13, &unpack_uint16_tlv_value}, - { NFAPI_EMTC_CONFIG_PRACH_CATM_ROOT_SEQUENCE_INDEX_TAG, &pNfapiMsg->emtc_config.prach_catm_root_sequence_index, &unpack_uint16_tlv_value}, - { NFAPI_EMTC_CONFIG_PRACH_CATM_ZERO_CORRELATION_ZONE_CONFIGURATION_TAG, &pNfapiMsg->emtc_config.prach_catm_zero_correlation_zone_configuration, &unpack_uint16_tlv_value}, - { NFAPI_EMTC_CONFIG_PRACH_CATM_HIGH_SPEED_FLAG, &pNfapiMsg->emtc_config.prach_catm_high_speed_flag, &unpack_uint16_tlv_value}, - { NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_0_ENABLE_TAG, &pNfapiMsg->emtc_config.prach_ce_level_0_enable, &unpack_uint16_tlv_value}, - { NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_0_CONFIGURATION_INDEX_TAG, &pNfapiMsg->emtc_config.prach_ce_level_0_configuration_index, &unpack_uint16_tlv_value}, - { NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_0_FREQUENCY_OFFSET_TAG, &pNfapiMsg->emtc_config.prach_ce_level_0_frequency_offset, &unpack_uint16_tlv_value}, - { NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_0_NUMBER_OF_REPETITIONS_PER_ATTEMPT_TAG, &pNfapiMsg->emtc_config.prach_ce_level_0_number_of_repetitions_per_attempt, &unpack_uint16_tlv_value}, - { NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_0_STARTING_SUBFRAME_PERIODICITY_TAG, &pNfapiMsg->emtc_config.prach_ce_level_0_starting_subframe_periodicity, &unpack_uint16_tlv_value}, - { NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_0_HOPPING_ENABLE_TAG, &pNfapiMsg->emtc_config.prach_ce_level_0_hopping_enable, &unpack_uint16_tlv_value}, - { NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_0_HOPPING_OFFSET_TAG, &pNfapiMsg->emtc_config.prach_ce_level_0_hopping_offset, &unpack_uint16_tlv_value}, - { NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_1_ENABLE_TAG, &pNfapiMsg->emtc_config.prach_ce_level_1_enable, &unpack_uint16_tlv_value}, - { NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_1_CONFIGURATION_INDEX_TAG, &pNfapiMsg->emtc_config.prach_ce_level_1_configuration_index, &unpack_uint16_tlv_value}, - { NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_1_FREQUENCY_OFFSET_TAG, &pNfapiMsg->emtc_config.prach_ce_level_1_frequency_offset, &unpack_uint16_tlv_value}, - { NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_1_NUMBER_OF_REPETITIONS_PER_ATTEMPT_TAG, &pNfapiMsg->emtc_config.prach_ce_level_1_number_of_repetitions_per_attempt, &unpack_uint16_tlv_value}, - { NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_1_STARTING_SUBFRAME_PERIODICITY_TAG, &pNfapiMsg->emtc_config.prach_ce_level_1_starting_subframe_periodicity, &unpack_uint16_tlv_value}, - { NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_1_HOPPING_ENABLE_TAG, &pNfapiMsg->emtc_config.prach_ce_level_1_hopping_enable, &unpack_uint16_tlv_value}, - { NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_1_HOPPING_OFFSET_TAG, &pNfapiMsg->emtc_config.prach_ce_level_1_hopping_offset, &unpack_uint16_tlv_value}, - { NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_2_ENABLE_TAG, &pNfapiMsg->emtc_config.prach_ce_level_2_enable, &unpack_uint16_tlv_value}, - { NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_2_CONFIGURATION_INDEX_TAG, &pNfapiMsg->emtc_config.prach_ce_level_2_configuration_index, &unpack_uint16_tlv_value}, - { NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_2_FREQUENCY_OFFSET_TAG, &pNfapiMsg->emtc_config.prach_ce_level_2_frequency_offset, &unpack_uint16_tlv_value}, - { NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_2_NUMBER_OF_REPETITIONS_PER_ATTEMPT_TAG, &pNfapiMsg->emtc_config.prach_ce_level_2_number_of_repetitions_per_attempt, &unpack_uint16_tlv_value}, - { NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_2_STARTING_SUBFRAME_PERIODICITY_TAG, &pNfapiMsg->emtc_config.prach_ce_level_2_starting_subframe_periodicity, &unpack_uint16_tlv_value}, - { NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_2_HOPPING_ENABLE_TAG, &pNfapiMsg->emtc_config.prach_ce_level_2_hopping_enable, &unpack_uint16_tlv_value}, - { NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_2_HOPPING_OFFSET_TAG, &pNfapiMsg->emtc_config.prach_ce_level_2_hopping_offset, &unpack_uint16_tlv_value}, - { NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_3_ENABLE_TAG, &pNfapiMsg->emtc_config.prach_ce_level_3_enable, &unpack_uint16_tlv_value}, - { NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_3_CONFIGURATION_INDEX_TAG, &pNfapiMsg->emtc_config.prach_ce_level_3_configuration_index, &unpack_uint16_tlv_value}, - { NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_3_FREQUENCY_OFFSET_TAG, &pNfapiMsg->emtc_config.prach_ce_level_3_frequency_offset, &unpack_uint16_tlv_value}, - { NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_3_NUMBER_OF_REPETITIONS_PER_ATTEMPT_TAG, &pNfapiMsg->emtc_config.prach_ce_level_3_number_of_repetitions_per_attempt, &unpack_uint16_tlv_value}, - { NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_3_STARTING_SUBFRAME_PERIODICITY_TAG, &pNfapiMsg->emtc_config.prach_ce_level_3_starting_subframe_periodicity, &unpack_uint16_tlv_value}, - { NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_3_HOPPING_ENABLE_TAG, &pNfapiMsg->emtc_config.prach_ce_level_3_hopping_enable, &unpack_uint16_tlv_value}, - { NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_3_HOPPING_OFFSET_TAG, &pNfapiMsg->emtc_config.prach_ce_level_3_hopping_offset, &unpack_uint16_tlv_value}, - { NFAPI_EMTC_CONFIG_PUCCH_INTERVAL_ULHOPPINGCONFIGCOMMONMODEA_TAG, &pNfapiMsg->emtc_config.pucch_interval_ulhoppingconfigcommonmodea, &unpack_uint16_tlv_value}, - { NFAPI_EMTC_CONFIG_PUCCH_INTERVAL_ULHOPPINGCONFIGCOMMONMODEB_TAG, &pNfapiMsg->emtc_config.pucch_interval_ulhoppingconfigcommonmodeb, &unpack_uint16_tlv_value}, - - { NFAPI_TDD_FRAME_STRUCTURE_SUBFRAME_ASSIGNMENT_TAG, &pNfapiMsg->tdd_frame_structure_config.subframe_assignment, &unpack_uint16_tlv_value}, - { NFAPI_TDD_FRAME_STRUCTURE_SPECIAL_SUBFRAME_PATTERNS_TAG, &pNfapiMsg->tdd_frame_structure_config.special_subframe_patterns, &unpack_uint16_tlv_value}, - - { NFAPI_L23_CONFIG_DATA_REPORT_MODE_TAG, &pNfapiMsg->l23_config.data_report_mode, &unpack_uint16_tlv_value}, - { NFAPI_L23_CONFIG_SFNSF_TAG, &pNfapiMsg->l23_config.sfnsf, &unpack_uint16_tlv_value}, - - { NFAPI_NFAPI_P7_VNF_ADDRESS_IPV4_TAG, &pNfapiMsg->nfapi_config.p7_vnf_address_ipv4, &unpack_ipv4_address_value}, - { NFAPI_NFAPI_P7_VNF_ADDRESS_IPV6_TAG, &pNfapiMsg->nfapi_config.p7_vnf_address_ipv6, &unpack_ipv6_address_value}, - { NFAPI_NFAPI_P7_VNF_PORT_TAG, &pNfapiMsg->nfapi_config.p7_vnf_port, &unpack_uint16_tlv_value}, - { NFAPI_NFAPI_P7_PNF_ADDRESS_IPV4_TAG, &pNfapiMsg->nfapi_config.p7_pnf_address_ipv4, &unpack_ipv4_address_value}, - { NFAPI_NFAPI_P7_PNF_ADDRESS_IPV6_TAG, &pNfapiMsg->nfapi_config.p7_pnf_address_ipv6, &unpack_ipv6_address_value}, - { NFAPI_NFAPI_P7_PNF_PORT_TAG, &pNfapiMsg->nfapi_config.p7_pnf_port, &unpack_uint16_tlv_value}, - { NFAPI_NFAPI_DOWNLINK_UES_PER_SUBFRAME_TAG, &pNfapiMsg->nfapi_config.dl_ue_per_sf, &unpack_uint8_tlv_value}, - { NFAPI_NFAPI_UPLINK_UES_PER_SUBFRAME_TAG, &pNfapiMsg->nfapi_config.ul_ue_per_sf, &unpack_uint8_tlv_value}, - { NFAPI_NFAPI_RF_BANDS_TAG, &pNfapiMsg->nfapi_config.rf_bands, &unpack_rf_bands_value}, - { NFAPI_NFAPI_TIMING_WINDOW_TAG, &pNfapiMsg->nfapi_config.timing_window, &unpack_uint8_tlv_value}, - { NFAPI_NFAPI_TIMING_INFO_MODE_TAG, &pNfapiMsg->nfapi_config.timing_info_mode, &unpack_uint8_tlv_value}, - { NFAPI_NFAPI_TIMING_INFO_PERIOD_TAG, &pNfapiMsg->nfapi_config.timing_info_period, &unpack_uint8_tlv_value}, - { NFAPI_NFAPI_MAXIMUM_TRANSMIT_POWER_TAG, &pNfapiMsg->nfapi_config.max_transmit_power, &unpack_uint16_tlv_value}, - { NFAPI_NFAPI_EARFCN_TAG, &pNfapiMsg->nfapi_config.earfcn, &unpack_uint16_tlv_value}, - { NFAPI_NFAPI_NMM_GSM_FREQUENCY_BANDS_TAG, &pNfapiMsg->nfapi_config.nmm_gsm_frequency_bands, &unpack_nmm_frequency_bands_value}, - { NFAPI_NFAPI_NMM_UMTS_FREQUENCY_BANDS_TAG, &pNfapiMsg->nfapi_config.nmm_umts_frequency_bands, &unpack_nmm_frequency_bands_value}, - { NFAPI_NFAPI_NMM_LTE_FREQUENCY_BANDS_TAG, &pNfapiMsg->nfapi_config.nmm_lte_frequency_bands, &unpack_nmm_frequency_bands_value}, - { NFAPI_NFAPI_NMM_UPLINK_RSSI_SUPPORTED_TAG, &pNfapiMsg->nfapi_config.nmm_uplink_rssi_supported, &unpack_uint8_tlv_value}, - - }; - - return ( pull8(ppReadPackedMsg, &pNfapiMsg->num_tlv, end) && - unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); - -} -static uint8_t unpack_nr_config_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t* config) -{ - nfapi_nr_config_request_scf_t *pNfapiMsg = (nfapi_nr_config_request_scf_t*)msg; - - pNfapiMsg->tdd_table.max_tdd_periodicity_list = (nfapi_nr_max_tdd_periodicity_t*) malloc(20*sizeof(nfapi_nr_max_tdd_periodicity_t)); - for(int i=0;i<40;i++) - pNfapiMsg->tdd_table.max_tdd_periodicity_list[i].max_num_of_symbol_per_slot_list = (nfapi_nr_max_num_of_symbol_per_slot_t*) malloc(14*sizeof(nfapi_nr_max_num_of_symbol_per_slot_t)); - - pNfapiMsg->prach_config.num_prach_fd_occasions_list=(nfapi_nr_num_prach_fd_occasions_t *) malloc(sizeof(nfapi_nr_num_prach_fd_occasions_t)); - - unpack_tlv_t unpack_fns[] = - { - { NFAPI_NR_CONFIG_DL_BANDWIDTH_TAG, &(pNfapiMsg->carrier_config.dl_bandwidth), &unpack_uint16_tlv_value}, - { NFAPI_NR_CONFIG_DL_FREQUENCY_TAG, &(pNfapiMsg->carrier_config.dl_frequency), &unpack_uint32_tlv_value}, - { NFAPI_NR_CONFIG_DL_GRID_SIZE_TAG, &(pNfapiMsg->carrier_config.dl_grid_size[1]), &unpack_uint16_tlv_value}, - { NFAPI_NR_CONFIG_DL_K0_TAG, &(pNfapiMsg->carrier_config.dl_k0[1]), &unpack_uint16_tlv_value}, - { NFAPI_NR_CONFIG_NUM_RX_ANT_TAG, &(pNfapiMsg->carrier_config.num_rx_ant), &unpack_uint16_tlv_value}, - { NFAPI_NR_CONFIG_NUM_TX_ANT_TAG, &(pNfapiMsg->carrier_config.num_tx_ant), &unpack_uint16_tlv_value}, - { NFAPI_NR_CONFIG_UL_GRID_SIZE_TAG, &(pNfapiMsg->carrier_config.ul_grid_size[1]), &unpack_uint16_tlv_value}, - { NFAPI_NR_CONFIG_UL_K0_TAG, &(pNfapiMsg->carrier_config.ul_k0[1]), &unpack_uint16_tlv_value}, - { NFAPI_NR_CONFIG_UPLINK_BANDWIDTH_TAG, &(pNfapiMsg->carrier_config.uplink_bandwidth), &unpack_uint16_tlv_value}, - { NFAPI_NR_CONFIG_UPLINK_FREQUENCY_TAG, &(pNfapiMsg->carrier_config.uplink_frequency), &unpack_uint32_tlv_value}, - { NFAPI_NR_CONFIG_FRAME_DUPLEX_TYPE_TAG, &(pNfapiMsg->cell_config.frame_duplex_type), &unpack_uint8_tlv_value}, - { NFAPI_NR_CONFIG_PHY_CELL_ID_TAG, &(pNfapiMsg->cell_config.phy_cell_id), &unpack_uint8_tlv_value}, - { NFAPI_NR_CONFIG_NUM_PRACH_FD_OCCASIONS_TAG, &(pNfapiMsg->prach_config.num_prach_fd_occasions), &unpack_uint8_tlv_value}, - { NFAPI_NR_CONFIG_PRACH_SEQUENCE_LENGTH_TAG, &(pNfapiMsg->prach_config.prach_sequence_length), &unpack_uint8_tlv_value}, - { NFAPI_NR_CONFIG_RESTRICTED_SET_CONFIG_TAG, &(pNfapiMsg->prach_config.restricted_set_config), &unpack_uint8_tlv_value}, - { NFAPI_NR_CONFIG_SSB_PER_RACH_TAG, &(pNfapiMsg->prach_config.ssb_per_rach), &unpack_uint8_tlv_value}, - { NFAPI_NR_CONFIG_PRACH_SUB_C_SPACING_TAG, &(pNfapiMsg->prach_config.prach_sub_c_spacing), &unpack_uint8_tlv_value}, - { NFAPI_NR_CONFIG_PRACH_ROOT_SEQUENCE_INDEX_TAG, &(pNfapiMsg->prach_config.num_prach_fd_occasions_list[0].prach_root_sequence_index), &unpack_uint16_tlv_value}, - { NFAPI_NR_CONFIG_K1_TAG, &(pNfapiMsg->prach_config.num_prach_fd_occasions_list[0].k1), &unpack_uint16_tlv_value}, - { NFAPI_NR_CONFIG_PRACH_ZERO_CORR_CONF_TAG, &(pNfapiMsg->prach_config.num_prach_fd_occasions_list[0].prach_zero_corr_conf), &unpack_uint8_tlv_value}, - { NFAPI_NR_CONFIG_NUM_ROOT_SEQUENCES_TAG, &(pNfapiMsg->prach_config.num_prach_fd_occasions_list[0].num_root_sequences), &unpack_uint8_tlv_value}, - - { NFAPI_NR_CONFIG_SCS_COMMON_TAG, &(pNfapiMsg->ssb_config.scs_common), &unpack_uint8_tlv_value}, - { NFAPI_NR_CONFIG_SS_PBCH_POWER_TAG, &(pNfapiMsg->ssb_config.ss_pbch_power), &unpack_uint32_tlv_value}, - { NFAPI_NR_CONFIG_BETA_PSS_TAG, &(pNfapiMsg->ssb_table.beta_pss), &unpack_uint8_tlv_value}, - { NFAPI_NR_CONFIG_MIB_TAG, &(pNfapiMsg->ssb_table.MIB), &unpack_uint32_tlv_value}, - { NFAPI_NR_CONFIG_SSB_MASK_TAG, &(pNfapiMsg->ssb_table.ssb_mask_list[0].ssb_mask), &unpack_uint32_tlv_value}, - { NFAPI_NR_CONFIG_SSB_MASK_TAG, &(pNfapiMsg->ssb_table.ssb_mask_list[1].ssb_mask), &unpack_uint32_tlv_value}, - - { NFAPI_NR_CONFIG_SSB_OFFSET_POINT_A_TAG, &(pNfapiMsg->ssb_table.ssb_offset_point_a), &unpack_uint16_tlv_value}, - { NFAPI_NR_CONFIG_SSB_PERIOD_TAG, &(pNfapiMsg->ssb_table.ssb_period), &unpack_uint8_tlv_value}, - { NFAPI_NR_CONFIG_SSB_SUBCARRIER_OFFSET_TAG, &(pNfapiMsg->ssb_table.ssb_subcarrier_offset), &unpack_uint8_tlv_value}, - { NFAPI_NR_CONFIG_TDD_PERIOD_TAG, &(pNfapiMsg->tdd_table.tdd_period), &unpack_uint8_tlv_value}, - { NFAPI_NR_CONFIG_SLOT_CONFIG_TAG, &(pNfapiMsg->tdd_table.max_tdd_periodicity_list[0].max_num_of_symbol_per_slot_list[0].slot_config), &unpack_uint8_tlv_value}, - { NFAPI_NR_NFAPI_P7_PNF_ADDRESS_IPV4_TAG, &(pNfapiMsg->nfapi_config.p7_pnf_address_ipv4), &unpack_ipv4_address_value}, - { 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}, - { 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}, - { NFAPI_NR_NFAPI_TIMING_INFO_MODE_TAG, &(pNfapiMsg->nfapi_config.timing_info_mode), &unpack_uint8_tlv_value}, - { NFAPI_NR_NFAPI_TIMING_INFO_PERIOD_TAG, &(pNfapiMsg->nfapi_config.timing_info_period), &unpack_uint8_tlv_value}, - { NFAPI_NR_NFAPI_TIMING_WINDOW_TAG, &(pNfapiMsg->nfapi_config.timing_window), &unpack_uint8_tlv_value}, - }; - return ( pull8(ppReadPackedMsg, &pNfapiMsg->num_tlv, end) && - unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); - -} - -static uint8_t unpack_config_response(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t* config) -{ - nfapi_config_response_t *pNfapiMsg = (nfapi_config_response_t*)msg; - - unpack_tlv_t unpack_fns[] = - { - }; - - return ( pull32(ppReadPackedMsg, &pNfapiMsg->error_code, end) && - unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &(pNfapiMsg->vendor_extension))); -} - -static uint8_t unpack_nr_config_response(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t* config) -{ - nfapi_nr_config_response_scf_t *pNfapiMsg = (nfapi_nr_config_response_scf_t*)msg; - - unpack_tlv_t unpack_fns[] = - { - }; - - return ( pull8(ppReadPackedMsg, &pNfapiMsg->error_code, end) && - unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &(pNfapiMsg->vendor_extension))); -} - -static uint8_t unpack_nr_start_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t* config) -{ - nfapi_nr_start_request_scf_t *pNfapiMsg = ( nfapi_nr_start_request_scf_t*)msg; - - unpack_tlv_t unpack_fns[] = - { - }; - - return unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &(pNfapiMsg->vendor_extension)); -} - -static uint8_t unpack_start_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t* config) -{ - nfapi_start_request_t *pNfapiMsg = ( nfapi_start_request_t*)msg; - - unpack_tlv_t unpack_fns[] = - { - }; - - return unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &(pNfapiMsg->vendor_extension)); -} - -static uint8_t unpack_start_response(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t* config) -{ - nfapi_start_response_t *pNfapiMsg = (nfapi_start_response_t*)msg; - - unpack_tlv_t unpack_fns[] = - { - }; - - return ( pull32(ppReadPackedMsg, &pNfapiMsg->error_code, end) && - unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &(pNfapiMsg->vendor_extension))); - -} - -static uint8_t unpack_nr_start_response(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t* config) -{ - nfapi_nr_start_response_scf_t *pNfapiMsg = (nfapi_nr_start_response_scf_t*)msg; - - unpack_tlv_t unpack_fns[] = - { - }; - - return ( pull32(ppReadPackedMsg, &pNfapiMsg->error_code, end) && - unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &(pNfapiMsg->vendor_extension))); - -} - -static uint8_t unpack_stop_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t* config) -{ - nfapi_stop_request_t *pNfapiMsg = (nfapi_stop_request_t*)msg; - - unpack_tlv_t unpack_fns[] = - { - }; - - return unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &(pNfapiMsg->vendor_extension)); -} - -static uint8_t unpack_stop_response(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t* config) -{ - nfapi_stop_response_t *pNfapiMsg = (nfapi_stop_response_t*)msg; - - unpack_tlv_t unpack_fns[] = - { - }; - - return ( pull32(ppReadPackedMsg, &pNfapiMsg->error_code, end) && - unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &(pNfapiMsg->vendor_extension))); - -} -static uint8_t unpack_measurement_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t* config) -{ - nfapi_measurement_request_t *pNfapiMsg = (nfapi_measurement_request_t*)msg; - - unpack_tlv_t unpack_fns[] = - { - { NFAPI_MEASUREMENT_REQUEST_DL_RS_XTX_POWER_TAG, &pNfapiMsg->dl_rs_tx_power, &unpack_uint16_tlv_value}, - { NFAPI_MEASUREMENT_REQUEST_RECEIVED_INTERFERENCE_POWER_TAG, &pNfapiMsg->received_interference_power, &unpack_uint16_tlv_value}, - { NFAPI_MEASUREMENT_REQUEST_THERMAL_NOISE_POWER_TAG, &pNfapiMsg->thermal_noise_power, &unpack_uint16_tlv_value}, - }; - - return unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &(pNfapiMsg->vendor_extension)); - -} - -static uint8_t unpack_received_interference_power_measurement_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_received_interference_power_measurement_t* value = (nfapi_received_interference_power_measurement_t*)tlv; - - return ( pull16(ppReadPackedMsg, &value->number_of_resource_blocks, end) && - pullarrays16(ppReadPackedMsg, value->received_interference_power, NFAPI_MAX_RECEIVED_INTERFERENCE_POWER_RESULTS, value->number_of_resource_blocks, end)); -} - - -static uint8_t unpack_measurement_response(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t* config) -{ - nfapi_measurement_response_t *pNfapiMsg = (nfapi_measurement_response_t*)msg; - - unpack_tlv_t unpack_fns[] = - { - { NFAPI_MEASUREMENT_RESPONSE_DL_RS_POWER_MEASUREMENT_TAG, &pNfapiMsg->dl_rs_tx_power_measurement, &unpack_int16_tlv_value}, - { NFAPI_MEASUREMENT_RESPONSE_RECEIVED_INTERFERENCE_POWER_MEASUREMENT_TAG, &pNfapiMsg->received_interference_power_measurement, &unpack_received_interference_power_measurement_value}, - { NFAPI_MEASUREMENT_RESPONSE_THERMAL_NOISE_MEASUREMENT_TAG, &pNfapiMsg->thermal_noise_power_measurement, &unpack_int16_tlv_value}, - }; - - return ( pull32(ppReadPackedMsg, &pNfapiMsg->error_code, end) && - unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); - -} - -// unpack length check - -static int check_nr_unpack_length(nfapi_nr_phy_msg_type_e msgId, uint32_t unpackedBufLen) -{ - int retLen = 0; - - switch (msgId) - { - case NFAPI_NR_PHY_MSG_TYPE_PNF_PARAM_REQUEST: - if (unpackedBufLen >= sizeof(nfapi_pnf_param_request_t)) - retLen = sizeof(nfapi_pnf_param_request_t); - break; - - case NFAPI_NR_PHY_MSG_TYPE_PNF_PARAM_RESPONSE: - if (unpackedBufLen >= sizeof(nfapi_nr_pnf_param_response_t)) - retLen = sizeof(nfapi_nr_pnf_param_response_t); - break; - - case NFAPI_NR_PHY_MSG_TYPE_PNF_CONFIG_REQUEST: - if (unpackedBufLen >= sizeof(nfapi_nr_pnf_config_request_t)) - retLen = sizeof(nfapi_nr_pnf_config_request_t); - break; - - case NFAPI_NR_PHY_MSG_TYPE_PNF_CONFIG_RESPONSE: - if (unpackedBufLen >= sizeof(nfapi_nr_pnf_config_response_t)) - retLen = sizeof(nfapi_nr_pnf_config_response_t); - break; - - case NFAPI_NR_PHY_MSG_TYPE_PNF_START_REQUEST: - if (unpackedBufLen >= sizeof(nfapi_nr_pnf_start_request_t)) - retLen = sizeof(nfapi_nr_pnf_start_request_t); - break; - - case NFAPI_NR_PHY_MSG_TYPE_PNF_START_RESPONSE: - if (unpackedBufLen >= sizeof(nfapi_nr_pnf_start_response_t)) - retLen = sizeof(nfapi_nr_pnf_start_response_t); - break; - - case NFAPI_NR_PHY_MSG_TYPE_PNF_STOP_REQUEST: - if (unpackedBufLen >= sizeof(nfapi_nr_pnf_stop_request_t)) - retLen = sizeof(nfapi_nr_pnf_stop_request_t); - break; - - case NFAPI_NR_PHY_MSG_TYPE_PNF_STOP_RESPONSE: - if (unpackedBufLen >= sizeof(nfapi_nr_pnf_stop_response_t)) - retLen = sizeof(nfapi_nr_pnf_stop_response_t); - break; - - case NFAPI_NR_PHY_MSG_TYPE_PARAM_REQUEST: - if (unpackedBufLen >= sizeof(nfapi_nr_param_request_scf_t)) - retLen = sizeof(nfapi_nr_param_request_scf_t); - break; - - case NFAPI_NR_PHY_MSG_TYPE_PARAM_RESPONSE: - if (unpackedBufLen >= sizeof(nfapi_nr_param_response_scf_t)) - retLen = sizeof(nfapi_nr_param_response_scf_t); - break; - - case NFAPI_NR_PHY_MSG_TYPE_CONFIG_REQUEST: - if (unpackedBufLen >= sizeof(nfapi_nr_config_request_scf_t)) - retLen = sizeof(nfapi_nr_config_request_scf_t); - break; - - case NFAPI_NR_PHY_MSG_TYPE_CONFIG_RESPONSE: - if (unpackedBufLen >= sizeof(nfapi_nr_config_response_scf_t)) - retLen = sizeof(nfapi_nr_config_response_scf_t); - break; - - case NFAPI_NR_PHY_MSG_TYPE_START_REQUEST: - if (unpackedBufLen >= sizeof( nfapi_nr_start_request_scf_t)) - retLen = sizeof( nfapi_nr_start_request_scf_t); - break; - - case NFAPI_NR_PHY_MSG_TYPE_START_RESPONSE: - if (unpackedBufLen >= sizeof(nfapi_nr_start_response_scf_t)) - retLen = sizeof(nfapi_nr_start_response_scf_t); - break; - - case NFAPI_NR_PHY_MSG_TYPE_STOP_REQUEST: - if (unpackedBufLen >= sizeof(nfapi_stop_request_t)) - retLen = sizeof(nfapi_stop_request_t); - break; - - case NFAPI_NR_PHY_MSG_TYPE_STOP_RESPONSE: - if (unpackedBufLen >= sizeof(nfapi_stop_response_t)) - retLen = sizeof(nfapi_stop_response_t); - break; - default: - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s Unknown message ID %d\n", __FUNCTION__, msgId); - break; - } - - return retLen; -} - - -static int check_unpack_length(nfapi_message_id_e msgId, uint32_t unpackedBufLen) -{ - int retLen = 0; - - switch (msgId) - { - case NFAPI_PNF_PARAM_REQUEST: - if (unpackedBufLen >= sizeof(nfapi_pnf_param_request_t)) - retLen = sizeof(nfapi_pnf_param_request_t); - break; - - case NFAPI_PNF_PARAM_RESPONSE: - if (unpackedBufLen >= sizeof(nfapi_pnf_param_response_t)) - retLen = sizeof(nfapi_pnf_param_response_t); - break; - - case NFAPI_PNF_CONFIG_REQUEST: - if (unpackedBufLen >= sizeof(nfapi_pnf_config_request_t)) - retLen = sizeof(nfapi_pnf_config_request_t); - break; - - case NFAPI_PNF_CONFIG_RESPONSE: - if (unpackedBufLen >= sizeof(nfapi_pnf_config_response_t)) - retLen = sizeof(nfapi_pnf_config_response_t); - break; - - case NFAPI_PNF_START_REQUEST: - if (unpackedBufLen >= sizeof(nfapi_pnf_start_request_t)) - retLen = sizeof(nfapi_pnf_start_request_t); - break; - - case NFAPI_PNF_START_RESPONSE: - if (unpackedBufLen >= sizeof(nfapi_pnf_start_response_t)) - retLen = sizeof(nfapi_pnf_start_response_t); - break; - - case NFAPI_PNF_STOP_REQUEST: - if (unpackedBufLen >= sizeof(nfapi_pnf_stop_request_t)) - retLen = sizeof(nfapi_pnf_stop_request_t); - break; - - case NFAPI_PNF_STOP_RESPONSE: - if (unpackedBufLen >= sizeof(nfapi_pnf_stop_response_t)) - retLen = sizeof(nfapi_pnf_stop_response_t); - break; - - case NFAPI_PARAM_REQUEST: - if (unpackedBufLen >= sizeof(nfapi_param_request_t)) - retLen = sizeof(nfapi_param_request_t); - break; - - case NFAPI_PARAM_RESPONSE: - if (unpackedBufLen >= sizeof(nfapi_param_response_t)) - retLen = sizeof(nfapi_param_response_t); - break; - - case NFAPI_CONFIG_REQUEST: - if (unpackedBufLen >= sizeof(nfapi_config_request_t)) - retLen = sizeof(nfapi_config_request_t); - break; - - case NFAPI_CONFIG_RESPONSE: - if (unpackedBufLen >= sizeof(nfapi_config_response_t)) - retLen = sizeof(nfapi_config_response_t); - break; - - case NFAPI_START_REQUEST: - if (unpackedBufLen >= sizeof( nfapi_start_request_t)) - retLen = sizeof( nfapi_start_request_t); - break; - - case NFAPI_START_RESPONSE: - if (unpackedBufLen >= sizeof(nfapi_start_response_t)) - retLen = sizeof(nfapi_start_response_t); - break; - - case NFAPI_STOP_REQUEST: - if (unpackedBufLen >= sizeof(nfapi_stop_request_t)) - retLen = sizeof(nfapi_stop_request_t); - break; - - case NFAPI_STOP_RESPONSE: - if (unpackedBufLen >= sizeof(nfapi_stop_response_t)) - retLen = sizeof(nfapi_stop_response_t); - break; - - case NFAPI_MEASUREMENT_REQUEST: - if (unpackedBufLen >= sizeof(nfapi_measurement_request_t)) - retLen = sizeof(nfapi_measurement_request_t); - break; - - case NFAPI_MEASUREMENT_RESPONSE: - if (unpackedBufLen >= sizeof(nfapi_measurement_response_t)) - retLen = sizeof(nfapi_measurement_response_t); - break; - - default: - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s Unknown message ID %d\n", __FUNCTION__, msgId); - break; - } - - return retLen; -} - - -// Main unpack functions - public - -int nfapi_p5_message_header_unpack(void *pMessageBuf, uint32_t messageBufLen, void *pUnpackedBuf, uint32_t unpackedBufLen, nfapi_p4_p5_codec_config_t* config) -{ - nfapi_p4_p5_message_header_t *pMessageHeader = pUnpackedBuf; - uint8_t *pReadPackedMessage = pMessageBuf; - uint8_t *end = pMessageBuf + messageBufLen; - - if (pMessageBuf == NULL || pUnpackedBuf == NULL) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "P5 header unpack supplied pointers are null\n"); - return -1; - } - - if (messageBufLen < NFAPI_HEADER_LENGTH || unpackedBufLen < sizeof(nfapi_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; - } - - // process the header - return ( pull16(&pReadPackedMessage, &pMessageHeader->phy_id, end) && - pull16(&pReadPackedMessage, &pMessageHeader->message_id, end) && - pull16(&pReadPackedMessage, &pMessageHeader->message_length, end) && - pull16(&pReadPackedMessage, &pMessageHeader->spare, end) ); - -} - -int nfapi_nr_p5_message_unpack(void *pMessageBuf, uint32_t messageBufLen, void *pUnpackedBuf, uint32_t unpackedBufLen, nfapi_p4_p5_codec_config_t* config) -{ - nfapi_p4_p5_message_header_t *pMessageHeader = pUnpackedBuf; - uint8_t *pReadPackedMessage = pMessageBuf; - uint8_t *end = pMessageBuf + messageBufLen; - - if (pMessageBuf == NULL || pUnpackedBuf == NULL) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "P5 unpack supplied pointers are null\n"); - return -1; - } - - if (messageBufLen < NFAPI_HEADER_LENGTH || unpackedBufLen < sizeof(nfapi_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; - } - - uint8_t *ptr = pReadPackedMessage; - printf("\n Read message unpack: "); - while(ptr < end){ - printf(" %d ", *ptr); - ptr++; - } - printf("\n"); - - // clean the supplied buffer for - tag value blanking - (void)memset(pUnpackedBuf, 0, unpackedBufLen); - - // process the header - if( !(pull16(&pReadPackedMessage, &pMessageHeader->phy_id, end ) && - pull16(&pReadPackedMessage, &pMessageHeader->message_id, end) && - pull16(&pReadPackedMessage, &pMessageHeader->message_length, end) && - pull16(&pReadPackedMessage, &pMessageHeader->spare, end))) - { - // failed to read the header - return -1; - } - - int result = -1; - - - if(check_nr_unpack_length(pMessageHeader->message_id, unpackedBufLen) == 0) - { - // the unpack buffer is not big enough for the struct - return -1; - } - - // look for the specific message - switch (pMessageHeader->message_id) - { - case NFAPI_NR_PHY_MSG_TYPE_PNF_PARAM_REQUEST: - result = unpack_nr_pnf_param_request(&pReadPackedMessage, end, pMessageHeader, config); - break; - - case NFAPI_NR_PHY_MSG_TYPE_PNF_PARAM_RESPONSE: - result = unpack_nr_pnf_param_response(&pReadPackedMessage, end, pMessageHeader, config); - break; - - case NFAPI_NR_PHY_MSG_TYPE_PNF_CONFIG_REQUEST: - result = unpack_nr_pnf_config_request(&pReadPackedMessage, end, pMessageHeader, config); - break; - - case NFAPI_NR_PHY_MSG_TYPE_PNF_CONFIG_RESPONSE: - result = unpack_nr_pnf_config_response(&pReadPackedMessage, end, pMessageHeader, config); - break; - - case NFAPI_NR_PHY_MSG_TYPE_PNF_START_REQUEST: - result = unpack_nr_pnf_start_request(&pReadPackedMessage, end, pMessageHeader, config); - break; - - case NFAPI_NR_PHY_MSG_TYPE_PNF_START_RESPONSE: - result = unpack_nr_pnf_start_response(&pReadPackedMessage, end, pMessageHeader, config); - break; - - case NFAPI_NR_PHY_MSG_TYPE_PNF_STOP_REQUEST: - result = unpack_pnf_stop_request(&pReadPackedMessage, end, pMessageHeader, config); - break; - - case NFAPI_NR_PHY_MSG_TYPE_PNF_STOP_RESPONSE: - result = unpack_pnf_stop_response(&pReadPackedMessage, end, pMessageHeader, config); - break; - - case NFAPI_NR_PHY_MSG_TYPE_PARAM_REQUEST: - result = unpack_nr_param_request(&pReadPackedMessage, end, pMessageHeader, config); - break; - - case NFAPI_NR_PHY_MSG_TYPE_PARAM_RESPONSE: - result = unpack_nr_param_response(&pReadPackedMessage, end, pMessageHeader, config); - break; - - case NFAPI_NR_PHY_MSG_TYPE_CONFIG_REQUEST: - result = unpack_nr_config_request(&pReadPackedMessage, end, pMessageHeader, config); - break; - - case NFAPI_NR_PHY_MSG_TYPE_CONFIG_RESPONSE: - result = unpack_nr_config_response(&pReadPackedMessage, end, pMessageHeader, config); - break; - - case NFAPI_NR_PHY_MSG_TYPE_START_REQUEST: - result = unpack_nr_start_request(&pReadPackedMessage, end, pMessageHeader, config); - break; - - case NFAPI_NR_PHY_MSG_TYPE_START_RESPONSE: - result = unpack_nr_start_response(&pReadPackedMessage, end, pMessageHeader, config); - break; - - case NFAPI_NR_PHY_MSG_TYPE_STOP_REQUEST: - result = unpack_stop_request(&pReadPackedMessage, end, pMessageHeader, config); - break; - - case NFAPI_NR_PHY_MSG_TYPE_STOP_RESPONSE: - result = unpack_stop_response(&pReadPackedMessage, end, pMessageHeader, config); - break; - - case NFAPI_MEASUREMENT_REQUEST: - result = unpack_measurement_request(&pReadPackedMessage, end, pMessageHeader, config); - break; - - case NFAPI_MEASUREMENT_RESPONSE: - result = unpack_measurement_response(&pReadPackedMessage, end, pMessageHeader, config); - break; - - default: - if(pMessageHeader->message_id >= NFAPI_VENDOR_EXT_MSG_MIN && - pMessageHeader->message_id <= NFAPI_VENDOR_EXT_MSG_MAX) - { - if(config && config->unpack_p4_p5_vendor_extension) - { - result = (config->unpack_p4_p5_vendor_extension)(pMessageHeader, &pReadPackedMessage, end, config); - } - else - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s VE NFAPI message ID %d. No ve decoder provided\n", __FUNCTION__, pMessageHeader->message_id); - } - } - else - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s NFAPI Unknown P5 message ID %d\n", __FUNCTION__, pMessageHeader->message_id); - } - break; - } - - return result; -} - -int nfapi_p5_message_unpack(void *pMessageBuf, uint32_t messageBufLen, void *pUnpackedBuf, uint32_t unpackedBufLen, nfapi_p4_p5_codec_config_t* config) -{ - nfapi_p4_p5_message_header_t *pMessageHeader = pUnpackedBuf; - uint8_t *pReadPackedMessage = pMessageBuf; - uint8_t *end = pMessageBuf + messageBufLen; - - if (pMessageBuf == NULL || pUnpackedBuf == NULL) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "P5 unpack supplied pointers are null\n"); - return -1; - } - - if (messageBufLen < NFAPI_HEADER_LENGTH || unpackedBufLen < sizeof(nfapi_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; - } - - uint8_t *ptr = pReadPackedMessage; - printf("\n Read message unpack: "); - while(ptr < end){ - printf(" %d ", *ptr); - ptr++; - } - printf("\n"); - - // clean the supplied buffer for - tag value blanking - (void)memset(pUnpackedBuf, 0, unpackedBufLen); - - // process the header - if( !(pull16(&pReadPackedMessage, &pMessageHeader->phy_id, end ) && - pull16(&pReadPackedMessage, &pMessageHeader->message_id, end) && - pull16(&pReadPackedMessage, &pMessageHeader->message_length, end) && - pull16(&pReadPackedMessage, &pMessageHeader->spare, end))) - { - // failed to read the header - return -1; - } - - int result = -1; - - - if(check_unpack_length(pMessageHeader->message_id, unpackedBufLen) == 0) - { - // the unpack buffer is not big enough for the struct - return -1; - } - - // look for the specific message - switch (pMessageHeader->message_id) - { - case NFAPI_PNF_PARAM_REQUEST: - result = unpack_pnf_param_request(&pReadPackedMessage, end, pMessageHeader, config); - break; - - case NFAPI_PNF_PARAM_RESPONSE: - result = unpack_pnf_param_response(&pReadPackedMessage, end, pMessageHeader, config); - break; - - case NFAPI_PNF_CONFIG_REQUEST: - result = unpack_pnf_config_request(&pReadPackedMessage, end, pMessageHeader, config); - break; - - case NFAPI_PNF_CONFIG_RESPONSE: - result = unpack_pnf_config_response(&pReadPackedMessage, end, pMessageHeader, config); - break; - - case NFAPI_PNF_START_REQUEST: - result = unpack_pnf_start_request(&pReadPackedMessage, end, pMessageHeader, config); - break; - - case NFAPI_PNF_START_RESPONSE: - result = unpack_pnf_start_response(&pReadPackedMessage, end, pMessageHeader, config); - break; - - case NFAPI_PNF_STOP_REQUEST: - result = unpack_pnf_stop_request(&pReadPackedMessage, end, pMessageHeader, config); - break; - - case NFAPI_PNF_STOP_RESPONSE: - result = unpack_pnf_stop_response(&pReadPackedMessage, end, pMessageHeader, config); - break; - - case NFAPI_PARAM_REQUEST: - result = unpack_param_request(&pReadPackedMessage, end, pMessageHeader, config); - break; - - case NFAPI_PARAM_RESPONSE: - result = unpack_param_response(&pReadPackedMessage, end, pMessageHeader, config); - break; - - case NFAPI_CONFIG_REQUEST: - result = unpack_config_request(&pReadPackedMessage, end, pMessageHeader, config); - break; - - case NFAPI_CONFIG_RESPONSE: - result = unpack_config_response(&pReadPackedMessage, end, pMessageHeader, config); - break; - - case NFAPI_START_REQUEST: - result = unpack_start_request(&pReadPackedMessage, end, pMessageHeader, config); - break; - - case NFAPI_START_RESPONSE: - result = unpack_start_response(&pReadPackedMessage, end, pMessageHeader, config); - break; - - case NFAPI_STOP_REQUEST: - result = unpack_stop_request(&pReadPackedMessage, end, pMessageHeader, config); - break; - - case NFAPI_STOP_RESPONSE: - result = unpack_stop_response(&pReadPackedMessage, end, pMessageHeader, config); - break; - - case NFAPI_MEASUREMENT_REQUEST: - result = unpack_measurement_request(&pReadPackedMessage, end, pMessageHeader, config); - break; - - case NFAPI_MEASUREMENT_RESPONSE: - result = unpack_measurement_response(&pReadPackedMessage, end, pMessageHeader, config); - break; - - default: - if(pMessageHeader->message_id >= NFAPI_VENDOR_EXT_MSG_MIN && - pMessageHeader->message_id <= NFAPI_VENDOR_EXT_MSG_MAX) - { - if(config && config->unpack_p4_p5_vendor_extension) - { - result = (config->unpack_p4_p5_vendor_extension)(pMessageHeader, &pReadPackedMessage, end, config); - } - else - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s VE NFAPI message ID %d. No ve decoder provided\n", __FUNCTION__, pMessageHeader->message_id); - } - } - else - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s NFAPI Unknown P5 message ID %d\n", __FUNCTION__, pMessageHeader->message_id); - } - break; - } - - return result; -} - +/* + * 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. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include "nfapi_nr_interface.h" +#include "nfapi_nr_interface_scf.h" +#include + + +// Pack routines +//TODO: Add pacl/unpack fns for uint32 and uint64 +static uint8_t pack_nr_pnf_param_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t *config) { + nfapi_nr_pnf_param_request_t *request = (nfapi_nr_pnf_param_request_t *)msg; + return pack_vendor_extension_tlv(request->vendor_extension, ppWritePackedMsg, end, config); +} + +static uint8_t pack_pnf_param_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t *config) { + nfapi_pnf_param_request_t *request = (nfapi_pnf_param_request_t *)msg; + return pack_vendor_extension_tlv(request->vendor_extension, ppWritePackedMsg, end, config); +} + +static uint8_t pack_pnf_param_general_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_pnf_param_general_t *value = (nfapi_pnf_param_general_t *)tlv; + return ( push8(value->nfapi_sync_mode, ppWritePackedMsg, end) && + push8(value->location_mode, ppWritePackedMsg, end) && + push16(value->location_coordinates_length, ppWritePackedMsg, end) && + pusharray8(value->location_coordinates, NFAPI_PNF_PARAM_GENERAL_LOCATION_LENGTH, value->location_coordinates_length, ppWritePackedMsg, end) && + push32(value->dl_config_timing, ppWritePackedMsg, end) && + push32(value->tx_timing, ppWritePackedMsg, end) && + push32(value->ul_config_timing, ppWritePackedMsg, end) && + push32(value->hi_dci0_timing, ppWritePackedMsg, end) && + push16(value->maximum_number_phys, ppWritePackedMsg, end) && + push16(value->maximum_total_bandwidth, ppWritePackedMsg, end) && + push8(value->maximum_total_number_dl_layers, ppWritePackedMsg, end) && + push8(value->maximum_total_number_ul_layers, ppWritePackedMsg, end) && + push8(value->shared_bands, ppWritePackedMsg, end) && + push8(value->shared_pa, ppWritePackedMsg, end) && + pushs16(value->maximum_total_power, ppWritePackedMsg, end) && + pusharray8(value->oui, NFAPI_PNF_PARAM_GENERAL_OUI_LENGTH, NFAPI_PNF_PARAM_GENERAL_OUI_LENGTH, ppWritePackedMsg, end)); +} + +static uint8_t pack_rf_config_info(void *elem, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_rf_config_info_t *rf = (nfapi_rf_config_info_t *)elem; + return (push16(rf->rf_config_index, ppWritePackedMsg, end)); +} + + +static uint8_t pack_pnf_phy_info(void *elem, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_pnf_phy_info_t *phy = (nfapi_pnf_phy_info_t *)elem; + return ( push16(phy->phy_config_index, ppWritePackedMsg, end) && + push16(phy->number_of_rfs, ppWritePackedMsg, end) && + packarray(phy->rf_config, sizeof(nfapi_rf_config_info_t), NFAPI_MAX_PNF_PHY_RF_CONFIG, phy->number_of_rfs, ppWritePackedMsg, end, &pack_rf_config_info) && + push16(phy->number_of_rf_exclusions, ppWritePackedMsg, end) && + packarray(phy->excluded_rf_config, sizeof(nfapi_rf_config_info_t), NFAPI_MAX_PNF_PHY_RF_CONFIG, phy->number_of_rf_exclusions, ppWritePackedMsg, end, &pack_rf_config_info) && + push16(phy->downlink_channel_bandwidth_supported, ppWritePackedMsg, end) && + push16(phy->uplink_channel_bandwidth_supported, ppWritePackedMsg, end) && + push8(phy->number_of_dl_layers_supported, ppWritePackedMsg, end) && + push8(phy->number_of_ul_layers_supported, ppWritePackedMsg, end) && + push16(phy->maximum_3gpp_release_supported, ppWritePackedMsg, end) && + push8(phy->nmm_modes_supported, ppWritePackedMsg, end)); +} + +static uint8_t pack_pnf_phy_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_pnf_phy_t *value = (nfapi_pnf_phy_t *)tlv; + return ( push16(value->number_of_phys, ppWritePackedMsg, end) && + packarray(value->phy, sizeof(nfapi_pnf_phy_info_t), NFAPI_MAX_PNF_PHY, value->number_of_phys, ppWritePackedMsg, end, &pack_pnf_phy_info)); +} + +static uint8_t pack_pnf_rf_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_pnf_rf_t *value = (nfapi_pnf_rf_t *)tlv; + uint16_t rf_index = 0; + + if(push16(value->number_of_rfs, ppWritePackedMsg, end) == 0) + return 0; + + for(; rf_index < value->number_of_rfs; ++rf_index) { + if( !(push16(value->rf[rf_index].rf_config_index, ppWritePackedMsg, end) && + push16(value->rf[rf_index].band, ppWritePackedMsg, end) && + pushs16(value->rf[rf_index].maximum_transmit_power, ppWritePackedMsg, end) && + pushs16(value->rf[rf_index].minimum_transmit_power, ppWritePackedMsg, end) && + push8(value->rf[rf_index].number_of_antennas_suppported, ppWritePackedMsg, end) && + push32(value->rf[rf_index].minimum_downlink_frequency, ppWritePackedMsg, end) && + push32(value->rf[rf_index].maximum_downlink_frequency, ppWritePackedMsg, end) && + push32(value->rf[rf_index].minimum_uplink_frequency, ppWritePackedMsg, end) && + push32(value->rf[rf_index].maximum_uplink_frequency, ppWritePackedMsg, end))) + return 0; + } + + return 1; +} +static uint8_t pack_pnf_phy_rel10_info(void *elem, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_pnf_phy_rel10_info_t *phy = (nfapi_pnf_phy_rel10_info_t *)elem; + return(push16(phy->phy_config_index, ppWritePackedMsg, end) && + push16(phy->transmission_mode_7_supported, ppWritePackedMsg, end) && + push16(phy->transmission_mode_8_supported, ppWritePackedMsg, end) && + push16(phy->two_antenna_ports_for_pucch, ppWritePackedMsg, end) && + push16(phy->transmission_mode_9_supported, ppWritePackedMsg, end) && + push16(phy->simultaneous_pucch_pusch, ppWritePackedMsg, end) && + push16(phy->four_layer_tx_with_tm3_and_tm4, ppWritePackedMsg, end)); +} + +static uint8_t pack_pnf_phy_rel10_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_pnf_phy_rel10_t *value = (nfapi_pnf_phy_rel10_t *)tlv; + return (push16(value->number_of_phys, ppWritePackedMsg, end) && + packarray(value->phy, sizeof(nfapi_pnf_phy_rel10_info_t), NFAPI_MAX_PNF_PHY, value->number_of_phys, ppWritePackedMsg, end, &pack_pnf_phy_rel10_info)); +} + +static uint8_t pack_pnf_phy_rel11_info(void *elem, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_pnf_phy_rel11_info_t *phy = (nfapi_pnf_phy_rel11_info_t *)elem; + return (push16(phy->phy_config_index, ppWritePackedMsg, end) && + push16(phy->edpcch_supported, ppWritePackedMsg, end) && + push16(phy->multi_ack_csi_reporting, ppWritePackedMsg, end) && + push16(phy->pucch_tx_diversity, ppWritePackedMsg, end) && + push16(phy->ul_comp_supported, ppWritePackedMsg, end) && + push16(phy->transmission_mode_5_supported, ppWritePackedMsg, end )); +} +static uint8_t pack_pnf_phy_rel11_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_pnf_phy_rel11_t *value = (nfapi_pnf_phy_rel11_t *)tlv; + return (push16(value->number_of_phys, ppWritePackedMsg, end) && + packarray(value->phy, sizeof(nfapi_pnf_phy_rel11_info_t), NFAPI_MAX_PNF_PHY, value->number_of_phys, ppWritePackedMsg, end, &pack_pnf_phy_rel11_info)); +} +static uint8_t pack_pnf_phy_rel12_info(void *elem, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_pnf_phy_rel12_info_t *phy = (nfapi_pnf_phy_rel12_info_t *)elem; + return( push16(phy->phy_config_index, ppWritePackedMsg, end) && + push16(phy->csi_subframe_set, ppWritePackedMsg, end) && + push16(phy->enhanced_4tx_codebook, ppWritePackedMsg, end) && + push16(phy->drs_supported, ppWritePackedMsg, end) && + push16(phy->ul_64qam_supported, ppWritePackedMsg, end) && + push16(phy->transmission_mode_10_supported, ppWritePackedMsg, end) && + push16(phy->alternative_bts_indices, ppWritePackedMsg, end)); +} +static uint8_t pack_pnf_phy_rel12_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_pnf_phy_rel12_t *value = (nfapi_pnf_phy_rel12_t *)tlv; + return (push16(value->number_of_phys, ppWritePackedMsg, end) && + packarray(value->phy, sizeof(nfapi_pnf_phy_rel12_info_t), NFAPI_MAX_PNF_PHY, value->number_of_phys, ppWritePackedMsg, end, &pack_pnf_phy_rel12_info)); +} + +static uint8_t pack_pnf_phy_rel13_info(void *elem, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_pnf_phy_rel13_info_t *phy = (nfapi_pnf_phy_rel13_info_t *)elem; + return( push16(phy->phy_config_index, ppWritePackedMsg, end) && + push16(phy->pucch_format4_supported, ppWritePackedMsg, end) && + push16(phy->pucch_format5_supported, ppWritePackedMsg, end) && + push16(phy->more_than_5_ca_support, ppWritePackedMsg, end) && + push16(phy->laa_supported, ppWritePackedMsg, end) && + push16(phy->laa_ending_in_dwpts_supported, ppWritePackedMsg, end) && + push16(phy->laa_starting_in_second_slot_supported, ppWritePackedMsg, end) && + push16(phy->beamforming_supported, ppWritePackedMsg, end) && + push16(phy->csi_rs_enhancement_supported, ppWritePackedMsg, end) && + push16(phy->drms_enhancement_supported, ppWritePackedMsg, end) && + push16(phy->srs_enhancement_supported, ppWritePackedMsg, end) ); +} + +static uint8_t pack_pnf_phy_rel13_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_pnf_phy_rel13_t *value = (nfapi_pnf_phy_rel13_t *)tlv; + return (push16(value->number_of_phys, ppWritePackedMsg, end) && + packarray(value->phy, sizeof(nfapi_pnf_phy_rel13_info_t), NFAPI_MAX_PNF_PHY, value->number_of_phys, ppWritePackedMsg, end, &pack_pnf_phy_rel13_info)); +} + +static uint8_t pack_pnf_phy_rel13_nb_iot_info(void *elem, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_pnf_phy_rel13_nb_iot_info_t *phy = (nfapi_pnf_phy_rel13_nb_iot_info_t *)elem; + return( push16(phy->phy_config_index, ppWritePackedMsg, end) && + push16(phy->number_of_rfs, ppWritePackedMsg, end) && + packarray(phy->rf_config, sizeof(nfapi_rf_config_info_t), NFAPI_MAX_PNF_PHY_RF_CONFIG, phy->number_of_rfs, ppWritePackedMsg, end, &pack_rf_config_info) && + push16(phy->number_of_rf_exclusions, ppWritePackedMsg, end) && + packarray(phy->excluded_rf_config, sizeof(nfapi_rf_config_info_t), NFAPI_MAX_PNF_PHY_RF_CONFIG, phy->number_of_rf_exclusions, ppWritePackedMsg, end, &pack_rf_config_info) && + push8(phy->number_of_dl_layers_supported, ppWritePackedMsg, end) && + push8(phy->number_of_ul_layers_supported, ppWritePackedMsg, end) && + push16(phy->maximum_3gpp_release_supported, ppWritePackedMsg, end) && + push8(phy->nmm_modes_supported, ppWritePackedMsg, end)); +} + +static uint8_t pack_pnf_phy_rel13_nb_iot_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_pnf_phy_rel13_nb_iot_t *value = (nfapi_pnf_phy_rel13_nb_iot_t *)tlv; + return (push16(value->number_of_phys, ppWritePackedMsg, end) && + packarray(value->phy, sizeof(nfapi_pnf_phy_rel13_nb_iot_info_t), NFAPI_MAX_PNF_PHY, value->number_of_phys, ppWritePackedMsg, end, &pack_pnf_phy_rel13_nb_iot_info)); +} +/* +static uint8_t pack_nr_pnf_param_response(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t* config) +{ + nfapi_nr_pnf_param_response_t *pNfapiMsg = (nfapi_nr_pnf_param_response_t*)msg; + + return (push32(pNfapiMsg->error_code, ppWritePackedMsg, end) && + pack_tlv(NFAPI_PNF_PARAM_GENERAL_TAG, &pNfapiMsg->pnf_param_general, ppWritePackedMsg, end, &pack_pnf_param_general_value) && + pack_tlv(NFAPI_PNF_PHY_TAG, &pNfapiMsg->pnf_phy, ppWritePackedMsg, end, &pack_pnf_phy_value) && + pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); +} +*/ +static uint8_t pack_nr_pnf_param_response(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t *config) { + nfapi_nr_pnf_param_response_t *pNfapiMsg = (nfapi_nr_pnf_param_response_t *)msg; + return (push32(pNfapiMsg->error_code, ppWritePackedMsg, end) && + pack_tlv(NFAPI_PNF_PARAM_GENERAL_TAG, &pNfapiMsg->pnf_param_general, ppWritePackedMsg, end, &pack_pnf_param_general_value) && + pack_tlv(NFAPI_PNF_PHY_TAG, &pNfapiMsg->pnf_phy, ppWritePackedMsg, end, &pack_pnf_phy_value) && + pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); +} + + +static uint8_t pack_pnf_param_response(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t *config) { + nfapi_pnf_param_response_t *pNfapiMsg = (nfapi_pnf_param_response_t *)msg; + return (push32(pNfapiMsg->error_code, ppWritePackedMsg, end) && + pack_tlv(NFAPI_PNF_PARAM_GENERAL_TAG, &pNfapiMsg->pnf_param_general, ppWritePackedMsg, end, &pack_pnf_param_general_value) && + pack_tlv(NFAPI_PNF_PHY_TAG, &pNfapiMsg->pnf_phy, ppWritePackedMsg, end, &pack_pnf_phy_value) && + pack_tlv(NFAPI_PNF_RF_TAG, &pNfapiMsg->pnf_rf, ppWritePackedMsg, end, &pack_pnf_rf_value) && + pack_tlv(NFAPI_PNF_PHY_REL10_TAG, &pNfapiMsg->pnf_phy_rel10, ppWritePackedMsg, end, &pack_pnf_phy_rel10_value) && + pack_tlv(NFAPI_PNF_PHY_REL11_TAG, &pNfapiMsg->pnf_phy_rel11, ppWritePackedMsg, end, &pack_pnf_phy_rel11_value) && + pack_tlv(NFAPI_PNF_PHY_REL12_TAG, &pNfapiMsg->pnf_phy_rel12, ppWritePackedMsg, end, &pack_pnf_phy_rel12_value) && + pack_tlv(NFAPI_PNF_PHY_REL13_TAG, &pNfapiMsg->pnf_phy_rel13, ppWritePackedMsg, end, &pack_pnf_phy_rel13_value) && + pack_tlv(NFAPI_PNF_PHY_REL13_NB_IOT_TAG, &pNfapiMsg->pnf_phy_rel13_nb_iot, ppWritePackedMsg, end, &pack_pnf_phy_rel13_nb_iot_value) && + pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); +} + + +static uint8_t pack_phy_rf_config_info(void *elem, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_phy_rf_config_info_t *rf = (nfapi_phy_rf_config_info_t *)elem; + return (push16(rf->phy_id, ppWritePackedMsg, end) && + push16(rf->phy_config_index, ppWritePackedMsg, end) && + push16(rf->rf_config_index, ppWritePackedMsg, end)); +} + + +static uint8_t pack_pnf_phy_rf_config_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_pnf_phy_rf_config_t *value = (nfapi_pnf_phy_rf_config_t *)tlv; + return(push16(value->number_phy_rf_config_info, ppWritePackedMsg, end) && + packarray(value->phy_rf_config, sizeof(nfapi_phy_rf_config_info_t), NFAPI_MAX_PHY_RF_INSTANCES, value->number_phy_rf_config_info, ppWritePackedMsg, end, &pack_phy_rf_config_info)); +} + +static uint8_t pack_nr_pnf_config_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t *config) { + nfapi_nr_pnf_config_request_t *pNfapiMsg = (nfapi_nr_pnf_config_request_t *)msg; + return (pack_tlv(NFAPI_PNF_PHY_RF_TAG, &pNfapiMsg->pnf_phy_rf_config, ppWritePackedMsg, end, &pack_pnf_phy_rf_config_value) && + //push8(pNfapiMsg->num_tlvs,ppWritePackedMsg,end) && + pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); +} + +static uint8_t pack_pnf_config_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t *config) { + nfapi_pnf_config_request_t *pNfapiMsg = (nfapi_pnf_config_request_t *)msg; + return (pack_tlv(NFAPI_PNF_PHY_RF_TAG, &pNfapiMsg->pnf_phy_rf_config, ppWritePackedMsg, end, &pack_pnf_phy_rf_config_value) && + push8(pNfapiMsg->num_tlvs,ppWritePackedMsg,end) && + pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); +} + + +static uint8_t pack_nr_pnf_config_response(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t *config) { + nfapi_nr_pnf_config_response_t *pNfapiMsg = (nfapi_nr_pnf_config_response_t *)msg; + return ( push32(pNfapiMsg->error_code, ppWritePackedMsg, end) && + pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); +} + + +static uint8_t pack_pnf_config_response(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t *config) { + nfapi_pnf_config_response_t *pNfapiMsg = (nfapi_pnf_config_response_t *)msg; + return ( push32(pNfapiMsg->error_code, ppWritePackedMsg, end) && + pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); +} + +static uint8_t pack_nr_pnf_start_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t *config) { + nfapi_nr_pnf_start_request_t *pNfapiMsg = (nfapi_nr_pnf_start_request_t *)msg; + return ( pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); +} + +static uint8_t pack_pnf_start_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t *config) { + nfapi_pnf_start_request_t *pNfapiMsg = (nfapi_pnf_start_request_t *)msg; + return ( pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); +} + + +static uint8_t pack_nr_pnf_start_response(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t *config) { + nfapi_nr_pnf_start_response_t *pNfapiMsg = (nfapi_nr_pnf_start_response_t *)msg; + return( push32(pNfapiMsg->error_code, ppWritePackedMsg, end) && + pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); +} + + +static uint8_t pack_pnf_start_response(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t *config) { + nfapi_pnf_start_response_t *pNfapiMsg = (nfapi_pnf_start_response_t *)msg; + return( push32(pNfapiMsg->error_code, ppWritePackedMsg, end) && + pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); +} + + +static uint8_t pack_nr_pnf_stop_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t *config) { + nfapi_nr_pnf_stop_request_t *pNfapiMsg = (nfapi_nr_pnf_stop_request_t *)msg; + return ( pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config) ); +} + + + +static uint8_t pack_pnf_stop_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t *config) { + nfapi_pnf_stop_request_t *pNfapiMsg = (nfapi_pnf_stop_request_t *)msg; + return ( pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config) ); +} + + +static uint8_t pack_nr_pnf_stop_response(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t *config) { + nfapi_nr_pnf_stop_response_t *pNfapiMsg = (nfapi_nr_pnf_stop_response_t *)msg; + return ( push32(pNfapiMsg->error_code, ppWritePackedMsg, end) && + pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); +} + + +static uint8_t pack_pnf_stop_response(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t *config) { + nfapi_pnf_stop_response_t *pNfapiMsg = (nfapi_pnf_stop_response_t *)msg; + return ( push32(pNfapiMsg->error_code, ppWritePackedMsg, end) && + pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); +} + +static uint8_t pack_nr_param_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t *config) { + nfapi_nr_param_request_scf_t *pNfapiMsg = (nfapi_nr_param_request_scf_t *)msg; + return (pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); +} + +static uint8_t pack_param_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t *config) { + nfapi_param_request_t *pNfapiMsg = (nfapi_param_request_t *)msg; + return (pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); +} + +static uint8_t pack_uint32_tlv_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_uint32_tlv_t *value = (nfapi_uint32_tlv_t *)tlv; + return push32(value->value, ppWritePackedMsg, end); +} + +static uint8_t unpack_uint32_tlv_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_uint32_tlv_t *value = (nfapi_uint32_tlv_t *)tlv; + return pull32(ppReadPackedMsg, &value->value, end); +} + + +static uint8_t pack_uint16_tlv_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_uint16_tlv_t *value = (nfapi_uint16_tlv_t *)tlv; + return push16(value->value, ppWritePackedMsg, end); +} + +static uint8_t unpack_uint16_tlv_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_uint16_tlv_t *value = (nfapi_uint16_tlv_t *)tlv; + return pull16(ppReadPackedMsg, &value->value, end); +} + +static uint8_t pack_int16_tlv_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_int16_tlv_t *value = (nfapi_int16_tlv_t *)tlv; + return pushs16(value->value, ppWritePackedMsg, end); +} + +static uint8_t unpack_int16_tlv_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_int16_tlv_t *value = (nfapi_int16_tlv_t *)tlv; + return pulls16(ppReadPackedMsg, &value->value, end); +} + +static uint8_t pack_uint8_tlv_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_uint8_tlv_t *value = (nfapi_uint8_tlv_t *)tlv; + return push8(value->value, ppWritePackedMsg, end); +} +static uint8_t unpack_uint8_tlv_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_uint8_tlv_t *value = (nfapi_uint8_tlv_t *)tlv; + return pull8(ppReadPackedMsg, &value->value, end); +} + +static uint8_t pack_ipv4_address_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_ipv4_address_t *value = (nfapi_ipv4_address_t *)tlv; + return pusharray8(value->address, NFAPI_IPV4_ADDRESS_LENGTH, NFAPI_IPV4_ADDRESS_LENGTH, ppWritePackedMsg, end); +} +static uint8_t unpack_ipv4_address_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_ipv4_address_t *value = (nfapi_ipv4_address_t *)tlv; + return pullarray8(ppReadPackedMsg, value->address, NFAPI_IPV4_ADDRESS_LENGTH, NFAPI_IPV4_ADDRESS_LENGTH, end); +} +static uint8_t pack_ipv6_address_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_ipv6_address_t *value = (nfapi_ipv6_address_t *)tlv; + return pusharray8(value->address, NFAPI_IPV6_ADDRESS_LENGTH, NFAPI_IPV6_ADDRESS_LENGTH, ppWritePackedMsg, end); +} +static uint8_t unpack_ipv6_address_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_ipv4_address_t *value = (nfapi_ipv4_address_t *)tlv; + return pullarray8(ppReadPackedMsg, value->address, NFAPI_IPV6_ADDRESS_LENGTH, NFAPI_IPV6_ADDRESS_LENGTH, end); +} + +static uint8_t pack_rf_bands_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_rf_bands_t *value = (nfapi_rf_bands_t *)tlv; + return ( push16(value->number_rf_bands, ppWritePackedMsg, end) && + pusharray16(value->rf_band, NFAPI_MAX_NUM_RF_BANDS, value->number_rf_bands, ppWritePackedMsg, end)); +} +static uint8_t unpack_rf_bands_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_rf_bands_t *value = (nfapi_rf_bands_t *)tlv; + return ( pull16(ppReadPackedMsg, &value->number_rf_bands, end) && + pullarray16(ppReadPackedMsg, value->rf_band, NFAPI_MAX_NUM_RF_BANDS, value->number_rf_bands, end)); +} + +static uint8_t pack_nmm_frequency_bands_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_nmm_frequency_bands_t *value = (nfapi_nmm_frequency_bands_t *)tlv; + return( push16(value->number_of_rf_bands, ppWritePackedMsg, end) && + pusharray16(value->bands, NFAPI_MAX_NMM_FREQUENCY_BANDS, value->number_of_rf_bands, ppWritePackedMsg, end)); +} +static uint8_t unpack_nmm_frequency_bands_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_nmm_frequency_bands_t *value = (nfapi_nmm_frequency_bands_t *)tlv; + return ( pull16(ppReadPackedMsg, &value->number_of_rf_bands, end) && + pullarray16(ppReadPackedMsg, value->bands, NFAPI_MAX_NMM_FREQUENCY_BANDS, value->number_of_rf_bands, end)); +} +static uint8_t pack_embms_mbsfn_config_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_embms_mbsfn_config_t *value = (nfapi_embms_mbsfn_config_t *)tlv; + return ( push16(value->num_mbsfn_config, ppWritePackedMsg, end) && + pusharray16(value->radioframe_allocation_period, 8,value->num_mbsfn_config,ppWritePackedMsg, end) && + pusharray16(value->radioframe_allocation_offset, 8,value->num_mbsfn_config,ppWritePackedMsg, end) && + pusharray8(value->fourframes_flag, 8,value->num_mbsfn_config,ppWritePackedMsg, end) && + pusharrays32(value->mbsfn_subframeconfig, 8, value->num_mbsfn_config, ppWritePackedMsg, end)); +} +// static uint8_t unpack_embms_mbsfn_config_value(void* tlv, uint8_t **ppReadPackedMsg, uint8_t* end) +// { +// nfapi_embms_mbsfn_config_t* value = (nfapi_embms_mbsfn_config_t*)tlv; + +// return ( pull16(ppReadPackedMsg, &value->num_mbsfn_config, end) && +// pull16(ppReadPackedMsg, &value->radioframe_allocation_period, end) && +// pull16(ppReadPackedMsg, &value->radioframe_allocation_offset, end) && +// pull8(ppReadPackedMsg, &value->fourframes_flag, end) && +// pullarrays32(ppReadPackedMsg, value->mbsfn_subframeconfig, 8, value->num_mbsfn_config, end)); +// } + +static uint8_t pack_param_response(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t *config) { + nfapi_param_response_t *pNfapiMsg = (nfapi_param_response_t *)msg; + return( push8(pNfapiMsg->error_code, ppWritePackedMsg, end) && + push8(pNfapiMsg->num_tlv, ppWritePackedMsg, end) && + pack_tlv(NFAPI_L1_STATUS_PHY_STATE_TAG, &pNfapiMsg->l1_status.phy_state, ppWritePackedMsg, end, &pack_uint16_tlv_value) && + // Do we check the phy state and then just fill those sepecified, however + // we do not know the duplex mode, so just attempt to pack all and assumme + // that the callee has set the right tlvs + pack_tlv(NFAPI_PHY_CAPABILITIES_DL_BANDWIDTH_SUPPORT_TAG, &(pNfapiMsg->phy_capabilities.dl_bandwidth_support), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_PHY_CAPABILITIES_UL_BANDWIDTH_SUPPORT_TAG, &(pNfapiMsg->phy_capabilities.ul_bandwidth_support), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_PHY_CAPABILITIES_DL_MODULATION_SUPPORT_TAG, &(pNfapiMsg->phy_capabilities.dl_modulation_support), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_PHY_CAPABILITIES_UL_MODULATION_SUPPORT_TAG, &(pNfapiMsg->phy_capabilities.ul_modulation_support), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_PHY_CAPABILITIES_PHY_ANTENNA_CAPABILITY_TAG, &(pNfapiMsg->phy_capabilities.phy_antenna_capability), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_PHY_CAPABILITIES_RELEASE_CAPABILITY_TAG, &(pNfapiMsg->phy_capabilities.release_capability), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_PHY_CAPABILITIES_MBSFN_CAPABILITY_TAG, &(pNfapiMsg->phy_capabilities.mbsfn_capability), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + // laa capability + pack_tlv(NFAPI_SUBFRAME_CONFIG_DUPLEX_MODE_TAG, &(pNfapiMsg->subframe_config.duplex_mode), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_SUBFRAME_CONFIG_PCFICH_POWER_OFFSET_TAG, &(pNfapiMsg->subframe_config.pcfich_power_offset), ppWritePackedMsg, end, &pack_uint16_tlv_value)&& + pack_tlv(NFAPI_SUBFRAME_CONFIG_PB_TAG, &(pNfapiMsg->subframe_config.pb), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_SUBFRAME_CONFIG_DL_CYCLIC_PREFIX_TYPE_TAG, &(pNfapiMsg->subframe_config.dl_cyclic_prefix_type), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_SUBFRAME_CONFIG_UL_CYCLIC_PREFIX_TYPE_TAG, &(pNfapiMsg->subframe_config.ul_cyclic_prefix_type), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_RF_CONFIG_DL_CHANNEL_BANDWIDTH_TAG, &(pNfapiMsg->rf_config.dl_channel_bandwidth), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_RF_CONFIG_UL_CHANNEL_BANDWIDTH_TAG, &(pNfapiMsg->rf_config.ul_channel_bandwidth), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_RF_CONFIG_REFERENCE_SIGNAL_POWER_TAG, &(pNfapiMsg->rf_config.reference_signal_power), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_RF_CONFIG_TX_ANTENNA_PORTS_TAG, &(pNfapiMsg->rf_config.tx_antenna_ports), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_RF_CONFIG_RX_ANTENNA_PORTS_TAG, &(pNfapiMsg->rf_config.rx_antenna_ports), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_PHICH_CONFIG_PHICH_RESOURCE_TAG, &(pNfapiMsg->phich_config.phich_resource), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_PHICH_CONFIG_PHICH_DURATION_TAG, &(pNfapiMsg->phich_config.phich_duration), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_PHICH_CONFIG_PHICH_POWER_OFFSET_TAG, &(pNfapiMsg->phich_config.phich_power_offset), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_SCH_CONFIG_PRIMARY_SYNCHRONIZATION_SIGNAL_EPRE_EPRERS_TAG, &(pNfapiMsg->sch_config.primary_synchronization_signal_epre_eprers), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_SCH_CONFIG_SECONDARY_SYNCHRONIZATION_SIGNAL_EPRE_EPRERS_TAG, &(pNfapiMsg->sch_config.secondary_synchronization_signal_epre_eprers), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_SCH_CONFIG_PHYSICAL_CELL_ID_TAG, &(pNfapiMsg->sch_config.physical_cell_id), ppWritePackedMsg, end,&pack_uint16_tlv_value) && + pack_tlv(NFAPI_PRACH_CONFIG_CONFIGURATION_INDEX_TAG, &(pNfapiMsg->prach_config.configuration_index), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_PRACH_CONFIG_ROOT_SEQUENCE_INDEX_TAG, &(pNfapiMsg->prach_config.root_sequence_index), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_PRACH_CONFIG_ZERO_CORRELATION_ZONE_CONFIGURATION_TAG, &(pNfapiMsg->prach_config.zero_correlation_zone_configuration), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_PRACH_CONFIG_HIGH_SPEED_FLAG_TAG, &(pNfapiMsg->prach_config.high_speed_flag), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_PRACH_CONFIG_FREQUENCY_OFFSET_TAG, &(pNfapiMsg->prach_config.frequency_offset), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_PUSCH_CONFIG_HOPPING_MODE_TAG, &(pNfapiMsg->pusch_config.hopping_mode), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_PUSCH_CONFIG_HOPPING_OFFSET_TAG, &(pNfapiMsg->pusch_config.hopping_offset), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_PUSCH_CONFIG_NUMBER_OF_SUBBANDS_TAG, &(pNfapiMsg->pusch_config.number_of_subbands), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_PUCCH_CONFIG_DELTA_PUCCH_SHIFT_TAG, &(pNfapiMsg->pucch_config.delta_pucch_shift), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_PUCCH_CONFIG_N_CQI_RB_TAG, &(pNfapiMsg->pucch_config.n_cqi_rb), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_PUCCH_CONFIG_N_AN_CS_TAG, &(pNfapiMsg->pucch_config.n_an_cs), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_PUCCH_CONFIG_N1_PUCCH_AN_TAG, &(pNfapiMsg->pucch_config.n1_pucch_an), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_EMBMS_MBSFN_CONFIG_AREA_IDX_TAG, &(pNfapiMsg->embms_sib13_config.mbsfn_area_idx), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + pack_tlv(NFAPI_EMBMS_MBSFN_CONFIG_AREA_IDR9_TAG, &(pNfapiMsg->embms_sib13_config.mbsfn_area_id_r9), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_EMBMS_MBSFN_CONFIG_TAG, &(pNfapiMsg->embms_mbsfn_config), ppWritePackedMsg, end, &pack_embms_mbsfn_config_value) && + pack_tlv(NFAPI_FEMBMS_CONFIG_RADIOFRAME_ALLOCATION_PERIOD_TAG, &(pNfapiMsg->fembms_config.radioframe_allocation_period), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + pack_tlv(NFAPI_FEMBMS_CONFIG_RADIOFRAME_ALLOCATION_OFFSET_TAG, &(pNfapiMsg->fembms_config.radioframe_allocation_offset), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + pack_tlv(NFAPI_FEMBMS_CONFIG_NON_MBSFN_FLAG_TAG, &(pNfapiMsg->fembms_config.non_mbsfn_config_flag), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + pack_tlv(NFAPI_FEMBMS_CONFIG_NON_MBSFN_SUBFRAMECONFIG_TAG, &(pNfapiMsg->fembms_config.non_mbsfn_subframeconfig), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_SRS_CONFIG_BANDWIDTH_CONFIGURATION_TAG, &(pNfapiMsg->srs_config.bandwidth_configuration), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_SRS_CONFIG_MAX_UP_PTS_TAG, &(pNfapiMsg->srs_config.max_up_pts), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_SRS_CONFIG_SRS_SUBFRAME_CONFIGURATION_TAG, &(pNfapiMsg->srs_config.srs_subframe_configuration), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_SRS_CONFIG_SRS_ACKNACK_SRS_SIMULTANEOUS_TRANSMISSION_TAG, &(pNfapiMsg->srs_config.srs_acknack_srs_simultaneous_transmission), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_UPLINK_REFERENCE_SIGNAL_CONFIG_UPLINK_RS_HOPPING_TAG, &(pNfapiMsg->uplink_reference_signal_config.uplink_rs_hopping), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_UPLINK_REFERENCE_SIGNAL_CONFIG_GROUP_ASSIGNMENT_TAG, &(pNfapiMsg->uplink_reference_signal_config.group_assignment), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_UPLINK_REFERENCE_SIGNAL_CONFIG_CYCLIC_SHIFT_1_FOR_DRMS_TAG, &(pNfapiMsg->uplink_reference_signal_config.cyclic_shift_1_for_drms), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_TDD_FRAME_STRUCTURE_SUBFRAME_ASSIGNMENT_TAG, &(pNfapiMsg->tdd_frame_structure_config.subframe_assignment), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_TDD_FRAME_STRUCTURE_SPECIAL_SUBFRAME_PATTERNS_TAG, &(pNfapiMsg->tdd_frame_structure_config.special_subframe_patterns), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_L23_CONFIG_DATA_REPORT_MODE_TAG, &(pNfapiMsg->l23_config.data_report_mode), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_L23_CONFIG_SFNSF_TAG, &(pNfapiMsg->l23_config.sfnsf), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_NFAPI_P7_VNF_ADDRESS_IPV4_TAG, &(pNfapiMsg->nfapi_config.p7_vnf_address_ipv4), ppWritePackedMsg, end, &pack_ipv4_address_value) && + pack_tlv(NFAPI_NFAPI_P7_VNF_ADDRESS_IPV6_TAG, &(pNfapiMsg->nfapi_config.p7_vnf_address_ipv6), ppWritePackedMsg, end, &pack_ipv6_address_value) && + pack_tlv(NFAPI_NFAPI_P7_VNF_PORT_TAG, &(pNfapiMsg->nfapi_config.p7_vnf_port), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_NFAPI_P7_PNF_ADDRESS_IPV4_TAG, &(pNfapiMsg->nfapi_config.p7_pnf_address_ipv4), ppWritePackedMsg, end, &pack_ipv4_address_value) && + pack_tlv(NFAPI_NFAPI_P7_PNF_ADDRESS_IPV6_TAG, &(pNfapiMsg->nfapi_config.p7_pnf_address_ipv6), ppWritePackedMsg, end, &pack_ipv6_address_value) && + pack_tlv(NFAPI_NFAPI_P7_PNF_PORT_TAG, &(pNfapiMsg->nfapi_config.p7_pnf_port), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_NFAPI_DOWNLINK_UES_PER_SUBFRAME_TAG, &(pNfapiMsg->nfapi_config.dl_ue_per_sf), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + pack_tlv(NFAPI_NFAPI_UPLINK_UES_PER_SUBFRAME_TAG, &(pNfapiMsg->nfapi_config.ul_ue_per_sf), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + pack_tlv(NFAPI_NFAPI_RF_BANDS_TAG, &(pNfapiMsg->nfapi_config.rf_bands), ppWritePackedMsg, end, &pack_rf_bands_value) && + pack_tlv(NFAPI_NFAPI_TIMING_WINDOW_TAG, &(pNfapiMsg->nfapi_config.timing_window), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + pack_tlv(NFAPI_NFAPI_TIMING_INFO_MODE_TAG, &(pNfapiMsg->nfapi_config.timing_info_mode), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + pack_tlv(NFAPI_NFAPI_TIMING_INFO_PERIOD_TAG, &(pNfapiMsg->nfapi_config.timing_info_period), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + pack_tlv(NFAPI_NFAPI_MAXIMUM_TRANSMIT_POWER_TAG, &(pNfapiMsg->nfapi_config.max_transmit_power), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_NFAPI_EARFCN_TAG, &(pNfapiMsg->nfapi_config.earfcn), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_NFAPI_NMM_GSM_FREQUENCY_BANDS_TAG, &(pNfapiMsg->nfapi_config.nmm_gsm_frequency_bands), ppWritePackedMsg, end, &pack_nmm_frequency_bands_value) && + pack_tlv(NFAPI_NFAPI_NMM_UMTS_FREQUENCY_BANDS_TAG, &(pNfapiMsg->nfapi_config.nmm_umts_frequency_bands), ppWritePackedMsg, end, &pack_nmm_frequency_bands_value) && + pack_tlv(NFAPI_NFAPI_NMM_LTE_FREQUENCY_BANDS_TAG, &(pNfapiMsg->nfapi_config.nmm_lte_frequency_bands), ppWritePackedMsg, end, &pack_nmm_frequency_bands_value) && + pack_tlv(NFAPI_NFAPI_NMM_UPLINK_RSSI_SUPPORTED_TAG, &(pNfapiMsg->nfapi_config.nmm_uplink_rssi_supported), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config) ); +} + +static uint8_t pack_nr_param_response(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t *config) { + printf("\nRUNNING pack_param_response\n"); + nfapi_nr_param_response_scf_t *pNfapiMsg = (nfapi_nr_param_response_scf_t *)msg; + return (push8(pNfapiMsg->error_code, ppWritePackedMsg, end) && + push8(pNfapiMsg->num_tlv, ppWritePackedMsg, end) && + pack_tlv(NFAPI_NR_PARAM_TLV_RELEASE_CAPABILITY_TAG, &(pNfapiMsg->cell_param.release_capability), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_NR_PARAM_TLV_PHY_STATE_TAG, &(pNfapiMsg->cell_param.phy_state), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_NR_PARAM_TLV_SKIP_BLANK_DL_CONFIG_TAG, &(pNfapiMsg->cell_param.skip_blank_dl_config), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + pack_tlv(NFAPI_NR_PARAM_TLV_SKIP_BLANK_UL_CONFIG_TAG, &(pNfapiMsg->cell_param.skip_blank_ul_config), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + pack_tlv(NFAPI_NR_PARAM_TLV_NUM_CONFIG_TLVS_TO_REPORT_TAG, &(pNfapiMsg->cell_param.num_config_tlvs_to_report ), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_NR_PARAM_TLV_CYCLIC_PREFIX_TAG, &(pNfapiMsg->carrier_param.cyclic_prefix), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + pack_tlv(NFAPI_NR_PARAM_TLV_SUPPORTED_SUBCARRIER_SPACINGS_DL_TAG, &(pNfapiMsg->carrier_param.supported_subcarrier_spacings_dl), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_NR_PARAM_TLV_SUPPORTED_BANDWIDTH_DL_TAG, &(pNfapiMsg->carrier_param.supported_bandwidth_dl), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_NR_PARAM_TLV_SUPPORTED_SUBCARRIER_SPACINGS_UL_TAG, &(pNfapiMsg->carrier_param.supported_subcarrier_spacings_ul), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + pack_tlv(NFAPI_NR_PARAM_TLV_SUPPORTED_BANDWIDTH_UL_TAG, &(pNfapiMsg->carrier_param.supported_bandwidth_ul), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_NR_PARAM_TLV_CCE_MAPPING_TYPE_TAG, &(pNfapiMsg->pdcch_param.cce_mapping_type), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + pack_tlv(NFAPI_NR_PARAM_TLV_CORESET_OUTSIDE_FIRST_3_OFDM_SYMS_OF_SLOT_TAG, &(pNfapiMsg->pdcch_param.coreset_outside_first_3_of_ofdm_syms_of_slot), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + pack_tlv(NFAPI_NR_PARAM_TLV_PRECODER_GRANULARITY_CORESET_TAG, &(pNfapiMsg->pdcch_param.coreset_precoder_granularity_coreset), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + pack_tlv(NFAPI_NR_PARAM_TLV_PDCCH_MU_MIMO_TAG, &(pNfapiMsg->pdcch_param.pdcch_mu_mimo), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + pack_tlv(NFAPI_NR_PARAM_TLV_PDCCH_PRECODER_CYCLING_TAG, &(pNfapiMsg->pdcch_param.pdcch_precoder_cycling), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + pack_tlv(NFAPI_NR_PARAM_TLV_MAX_PDCCHS_PER_SLOT_TAG, &(pNfapiMsg->pdcch_param.max_pdcch_per_slot), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + pack_tlv(NFAPI_NR_PARAM_TLV_PUCCH_FORMATS_TAG, &(pNfapiMsg->pucch_param.pucch_formats), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + pack_tlv(NFAPI_NR_PARAM_TLV_MAX_PUCCHS_PER_SLOT_TAG, &(pNfapiMsg->pucch_param.max_pucchs_per_slot), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + pack_tlv(NFAPI_NR_PARAM_TLV_PDSCH_MAPPING_TYPE_TAG, &(pNfapiMsg->pdsch_param.pdsch_mapping_type), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + pack_tlv(NFAPI_NR_PARAM_TLV_PDSCH_ALLOCATION_TYPES_TAG, &(pNfapiMsg->pdsch_param.pdsch_allocation_types), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + pack_tlv(NFAPI_NR_PARAM_TLV_PDSCH_VRB_TO_PRB_MAPPING_TAG, &(pNfapiMsg->pdsch_param.pdsch_vrb_to_prb_mapping), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + pack_tlv(NFAPI_NR_PARAM_TLV_PDSCH_CBG_TAG, &(pNfapiMsg->pdsch_param.pdsch_cbg), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + pack_tlv(NFAPI_NR_PARAM_TLV_PDSCH_DMRS_CONFIG_TYPES_TAG, &(pNfapiMsg->pdsch_param.pdsch_dmrs_config_types), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + pack_tlv(NFAPI_NR_PARAM_TLV_PDSCH_DMRS_MAX_LENGTH_TAG, &(pNfapiMsg->pdsch_param.pdsch_dmrs_max_length), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + pack_tlv(NFAPI_NR_PARAM_TLV_PDSCH_DMRS_ADDITIONAL_POS_TAG, &(pNfapiMsg->pdsch_param.pdsch_dmrs_additional_pos), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + pack_tlv(NFAPI_NR_PARAM_TLV_MAX_PDSCH_S_YBS_PER_SLOT_TAG, &(pNfapiMsg->pdsch_param.max_pdsch_tbs_per_slot), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + pack_tlv(NFAPI_NR_PARAM_TLV_MAX_NUMBER_MIMO_LAYERS_PDSCH_TAG, &(pNfapiMsg->pdsch_param.max_number_mimo_layers_pdsch), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + pack_tlv(NFAPI_NR_PARAM_TLV_MAX_MU_MIMO_USERS_DL_TAG, &(pNfapiMsg->pdsch_param.max_mu_mimo_users_dl), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + pack_tlv(NFAPI_NR_PARAM_TLV_PDSCH_DATA_IN_DMRS_SYMBOLS_TAG, &(pNfapiMsg->pdsch_param.pdsch_data_in_dmrs_symbols), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + pack_tlv(NFAPI_NR_PARAM_TLV_PREMPTION_SUPPORT_TAG, &(pNfapiMsg->pdsch_param.premption_support), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + pack_tlv(NFAPI_NR_PARAM_TLV_PDSCH_NON_SLOT_SUPPORT_TAG, &(pNfapiMsg->pdsch_param.pdsch_non_slot_support), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + pack_tlv(NFAPI_NR_PARAM_TLV_UCI_MUX_ULSCH_IN_PUSCH_TAG, &(pNfapiMsg->pusch_param.uci_mux_ulsch_in_pusch), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + pack_tlv(NFAPI_NR_PARAM_TLV_UCI_ONLY_PUSCH_TAG, &(pNfapiMsg->pusch_param.uci_only_pusch), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + pack_tlv(NFAPI_NR_PARAM_TLV_PUSCH_FREQUENCY_HOPPING_TAG, &(pNfapiMsg->pusch_param.pusch_frequency_hopping), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + pack_tlv(NFAPI_NR_PARAM_TLV_PUSCH_DMRS_CONFIG_TYPES_TAG, &(pNfapiMsg->pusch_param.pusch_dmrs_config_types), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + pack_tlv(NFAPI_NR_PARAM_TLV_PUSCH_DMRS_MAX_LEN_TAG, &(pNfapiMsg->pusch_param.pusch_dmrs_max_len), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + pack_tlv(NFAPI_NR_PARAM_TLV_PUSCH_DMRS_ADDITIONAL_POS_TAG, &(pNfapiMsg->pusch_param.pusch_dmrs_additional_pos), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + pack_tlv(NFAPI_NR_PARAM_TLV_PUSCH_CBG_TAG, &(pNfapiMsg->pusch_param.pusch_cbg), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + pack_tlv(NFAPI_NR_PARAM_TLV_PUSCH_MAPPING_TYPE_TAG, &(pNfapiMsg->pusch_param.pusch_mapping_type), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + pack_tlv(NFAPI_NR_PARAM_TLV_PUSCH_ALLOCATION_TYPES_TAG, &(pNfapiMsg->pusch_param.pusch_allocation_types), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + pack_tlv(NFAPI_NR_PARAM_TLV_PUSCH_VRB_TO_PRB_MAPPING_TAG, &(pNfapiMsg->pusch_param.pusch_vrb_to_prb_mapping), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + pack_tlv(NFAPI_NR_PARAM_TLV_PUSCH_MAX_PTRS_PORTS_TAG, &(pNfapiMsg->pusch_param.pusch_max_ptrs_ports), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + pack_tlv(NFAPI_NR_PARAM_TLV_MAX_PDUSCHS_TBS_PER_SLOT_TAG, &(pNfapiMsg->pusch_param.max_pduschs_tbs_per_slot), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + pack_tlv(NFAPI_NR_PARAM_TLV_MAX_NUMBER_MIMO_LAYERS_NON_CB_PUSCH_TAG, &(pNfapiMsg->pusch_param.max_number_mimo_layers_non_cb_pusch), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + pack_tlv(NFAPI_NR_PARAM_TLV_SUPPORTED_MODULATION_ORDER_UL_TAG, &(pNfapiMsg->pusch_param.supported_modulation_order_ul), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + pack_tlv(NFAPI_NR_PARAM_TLV_MAX_MU_MIMO_USERS_UL_TAG, &(pNfapiMsg->pusch_param.max_mu_mimo_users_ul), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + pack_tlv(NFAPI_NR_PARAM_TLV_DFTS_OFDM_SUPPORT_TAG, &(pNfapiMsg->pusch_param.dfts_ofdm_support), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + pack_tlv(NFAPI_NR_PARAM_TLV_PUSCH_AGGREGATION_FACTOR_TAG, &(pNfapiMsg->pusch_param.pusch_aggregation_factor), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + pack_tlv(NFAPI_NR_PARAM_TLV_PRACH_LONG_FORMATS_TAG, &(pNfapiMsg->prach_param.prach_long_formats), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + pack_tlv(NFAPI_NR_PARAM_TLV_PRACH_SHORT_FORMATS_TAG, &(pNfapiMsg->prach_param.prach_short_formats), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + pack_tlv(NFAPI_NR_PARAM_TLV_PRACH_RESTRICTED_SETS_TAG, &(pNfapiMsg->prach_param.prach_restricted_sets), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + pack_tlv(NFAPI_NR_PARAM_TLV_MAX_PRACH_FD_OCCASIONS_IN_A_SLOT_TAG, &(pNfapiMsg->prach_param.max_prach_fd_occasions_in_a_slot), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + pack_tlv(NFAPI_NR_PARAM_TLV_RSSI_MEASUREMENT_SUPPORT_TAG, &(pNfapiMsg->measurement_param.rssi_measurement_support), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + // config: + pack_tlv(NFAPI_NR_NFAPI_P7_VNF_ADDRESS_IPV4_TAG, &(pNfapiMsg->nfapi_config.p7_vnf_address_ipv4), ppWritePackedMsg, end, &pack_ipv4_address_value) && + pack_tlv(NFAPI_NR_NFAPI_P7_VNF_ADDRESS_IPV6_TAG, &(pNfapiMsg->nfapi_config.p7_vnf_address_ipv6), ppWritePackedMsg, end, &pack_ipv6_address_value) && + pack_tlv(NFAPI_NR_NFAPI_P7_VNF_PORT_TAG, &(pNfapiMsg->nfapi_config.p7_vnf_port), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_NR_NFAPI_P7_PNF_ADDRESS_IPV4_TAG, &(pNfapiMsg->nfapi_config.p7_pnf_address_ipv4), ppWritePackedMsg, end, &pack_ipv4_address_value) && + pack_tlv(NFAPI_NR_NFAPI_P7_PNF_ADDRESS_IPV6_TAG, &(pNfapiMsg->nfapi_config.p7_pnf_address_ipv6), ppWritePackedMsg, end, &pack_ipv6_address_value) && + pack_tlv(NFAPI_NR_NFAPI_P7_PNF_PORT_TAG, &(pNfapiMsg->nfapi_config.p7_pnf_port), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_NR_NFAPI_TIMING_WINDOW_TAG, &(pNfapiMsg->nfapi_config.timing_window), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + pack_tlv(NFAPI_NR_NFAPI_TIMING_INFO_MODE_TAG, &(pNfapiMsg->nfapi_config.timing_info_mode), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + pack_tlv(NFAPI_NR_NFAPI_TIMING_INFO_PERIOD_TAG, &(pNfapiMsg->nfapi_config.timing_info_period), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); +} + +static uint8_t pack_config_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t *config) { + nfapi_config_request_t *pNfapiMsg = (nfapi_config_request_t *)msg; + return ( push8(pNfapiMsg->num_tlv, ppWritePackedMsg, end) && + // Do we check the phy state and then just fill those sepecified, however + // we do not know the duplex mode, so just attempt to pack all and assumme + // that the callee has set the right tlvs + pack_tlv(NFAPI_SUBFRAME_CONFIG_DUPLEX_MODE_TAG, &(pNfapiMsg->subframe_config.duplex_mode), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_SUBFRAME_CONFIG_PCFICH_POWER_OFFSET_TAG, &(pNfapiMsg->subframe_config.pcfich_power_offset), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_SUBFRAME_CONFIG_PB_TAG, &(pNfapiMsg->subframe_config.pb), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_SUBFRAME_CONFIG_DL_CYCLIC_PREFIX_TYPE_TAG, &(pNfapiMsg->subframe_config.dl_cyclic_prefix_type), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_SUBFRAME_CONFIG_UL_CYCLIC_PREFIX_TYPE_TAG, &(pNfapiMsg->subframe_config.ul_cyclic_prefix_type), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_RF_CONFIG_DL_CHANNEL_BANDWIDTH_TAG, &(pNfapiMsg->rf_config.dl_channel_bandwidth), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_RF_CONFIG_UL_CHANNEL_BANDWIDTH_TAG, &(pNfapiMsg->rf_config.ul_channel_bandwidth), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_RF_CONFIG_REFERENCE_SIGNAL_POWER_TAG, &(pNfapiMsg->rf_config.reference_signal_power), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_RF_CONFIG_TX_ANTENNA_PORTS_TAG, &(pNfapiMsg->rf_config.tx_antenna_ports), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_RF_CONFIG_RX_ANTENNA_PORTS_TAG, &(pNfapiMsg->rf_config.rx_antenna_ports), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_PHICH_CONFIG_PHICH_RESOURCE_TAG, &(pNfapiMsg->phich_config.phich_resource), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_PHICH_CONFIG_PHICH_DURATION_TAG, &(pNfapiMsg->phich_config.phich_duration), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_PHICH_CONFIG_PHICH_POWER_OFFSET_TAG, &(pNfapiMsg->phich_config.phich_power_offset), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_SCH_CONFIG_PRIMARY_SYNCHRONIZATION_SIGNAL_EPRE_EPRERS_TAG, &(pNfapiMsg->sch_config.primary_synchronization_signal_epre_eprers), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_SCH_CONFIG_SECONDARY_SYNCHRONIZATION_SIGNAL_EPRE_EPRERS_TAG, &(pNfapiMsg->sch_config.secondary_synchronization_signal_epre_eprers), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_SCH_CONFIG_PHYSICAL_CELL_ID_TAG, &(pNfapiMsg->sch_config.physical_cell_id), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_PRACH_CONFIG_CONFIGURATION_INDEX_TAG, &(pNfapiMsg->prach_config.configuration_index), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_PRACH_CONFIG_ROOT_SEQUENCE_INDEX_TAG, &(pNfapiMsg->prach_config.root_sequence_index), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_PRACH_CONFIG_ZERO_CORRELATION_ZONE_CONFIGURATION_TAG, &(pNfapiMsg->prach_config.zero_correlation_zone_configuration), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_PRACH_CONFIG_HIGH_SPEED_FLAG_TAG, &(pNfapiMsg->prach_config.high_speed_flag), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_PRACH_CONFIG_FREQUENCY_OFFSET_TAG, &(pNfapiMsg->prach_config.frequency_offset), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_PUSCH_CONFIG_HOPPING_MODE_TAG, &(pNfapiMsg->pusch_config.hopping_mode), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_PUSCH_CONFIG_HOPPING_OFFSET_TAG, &(pNfapiMsg->pusch_config.hopping_offset), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_PUSCH_CONFIG_NUMBER_OF_SUBBANDS_TAG, &(pNfapiMsg->pusch_config.number_of_subbands), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_PUCCH_CONFIG_DELTA_PUCCH_SHIFT_TAG, &(pNfapiMsg->pucch_config.delta_pucch_shift), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_PUCCH_CONFIG_N_CQI_RB_TAG, &(pNfapiMsg->pucch_config.n_cqi_rb), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_PUCCH_CONFIG_N_AN_CS_TAG, &(pNfapiMsg->pucch_config.n_an_cs), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_PUCCH_CONFIG_N1_PUCCH_AN_TAG, &(pNfapiMsg->pucch_config.n1_pucch_an), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_SRS_CONFIG_BANDWIDTH_CONFIGURATION_TAG, &(pNfapiMsg->srs_config.bandwidth_configuration), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_SRS_CONFIG_MAX_UP_PTS_TAG, &(pNfapiMsg->srs_config.max_up_pts), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_SRS_CONFIG_SRS_SUBFRAME_CONFIGURATION_TAG, &(pNfapiMsg->srs_config.srs_subframe_configuration), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_SRS_CONFIG_SRS_ACKNACK_SRS_SIMULTANEOUS_TRANSMISSION_TAG, &(pNfapiMsg->srs_config.srs_acknack_srs_simultaneous_transmission), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_UPLINK_REFERENCE_SIGNAL_CONFIG_UPLINK_RS_HOPPING_TAG, &(pNfapiMsg->uplink_reference_signal_config.uplink_rs_hopping), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_UPLINK_REFERENCE_SIGNAL_CONFIG_GROUP_ASSIGNMENT_TAG, &(pNfapiMsg->uplink_reference_signal_config.group_assignment), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_UPLINK_REFERENCE_SIGNAL_CONFIG_CYCLIC_SHIFT_1_FOR_DRMS_TAG, &(pNfapiMsg->uplink_reference_signal_config.cyclic_shift_1_for_drms), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_LAA_CONFIG_ED_THRESHOLD_FOR_LBT_FOR_PDSCH_TAG, &(pNfapiMsg->laa_config.ed_threshold_lbt_pdsch), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_LAA_CONFIG_ED_THRESHOLD_FOR_LBT_FOR_DRS_TAG, &(pNfapiMsg->laa_config.ed_threshold_lbt_drs), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_LAA_CONFIG_PD_THRESHOLD_TAG, &(pNfapiMsg->laa_config.pd_threshold), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_LAA_CONFIG_MULTI_CARRIER_TYPE_TAG, &(pNfapiMsg->laa_config.multi_carrier_type), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_LAA_CONFIG_MULTI_CARRIER_TX_TAG, &(pNfapiMsg->laa_config.multi_carrier_tx), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_LAA_CONFIG_MULTI_CARRIER_FREEZE_TAG, &(pNfapiMsg->laa_config.multi_carrier_freeze), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_LAA_CONFIG_TX_ANTENNA_PORTS_FOR_DRS_TAG, &(pNfapiMsg->laa_config.tx_antenna_ports_drs), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_LAA_CONFIG_TRANSMISSION_POWER_FOR_DRS_TAG, &(pNfapiMsg->laa_config.tx_power_drs), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_EMTC_CONFIG_PBCH_REPETITIONS_ENABLE_R13_TAG, &(pNfapiMsg->emtc_config.pbch_repetitions_enable_r13), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_EMTC_CONFIG_PRACH_CATM_ROOT_SEQUENCE_INDEX_TAG, &(pNfapiMsg->emtc_config.prach_catm_root_sequence_index), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_EMTC_CONFIG_PRACH_CATM_ZERO_CORRELATION_ZONE_CONFIGURATION_TAG, &(pNfapiMsg->emtc_config.prach_catm_zero_correlation_zone_configuration), ppWritePackedMsg, end, + &pack_uint16_tlv_value) && + pack_tlv(NFAPI_EMTC_CONFIG_PRACH_CATM_HIGH_SPEED_FLAG, &(pNfapiMsg->emtc_config.prach_catm_high_speed_flag), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_0_ENABLE_TAG, &(pNfapiMsg->emtc_config.prach_ce_level_0_enable), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_0_CONFIGURATION_INDEX_TAG, &(pNfapiMsg->emtc_config.prach_ce_level_0_configuration_index), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_0_FREQUENCY_OFFSET_TAG, &(pNfapiMsg->emtc_config.prach_ce_level_0_frequency_offset), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_0_NUMBER_OF_REPETITIONS_PER_ATTEMPT_TAG, &(pNfapiMsg->emtc_config.prach_ce_level_0_number_of_repetitions_per_attempt), ppWritePackedMsg, end, + &pack_uint16_tlv_value) && + pack_tlv(NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_0_STARTING_SUBFRAME_PERIODICITY_TAG, &(pNfapiMsg->emtc_config.prach_ce_level_0_starting_subframe_periodicity), ppWritePackedMsg, end, + &pack_uint16_tlv_value) && + pack_tlv(NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_0_HOPPING_ENABLE_TAG, &(pNfapiMsg->emtc_config.prach_ce_level_0_hopping_enable), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_0_HOPPING_OFFSET_TAG, &(pNfapiMsg->emtc_config.prach_ce_level_0_hopping_offset), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_1_ENABLE_TAG, &(pNfapiMsg->emtc_config.prach_ce_level_1_enable), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_1_CONFIGURATION_INDEX_TAG, &(pNfapiMsg->emtc_config.prach_ce_level_1_configuration_index), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_1_FREQUENCY_OFFSET_TAG, &(pNfapiMsg->emtc_config.prach_ce_level_1_frequency_offset), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_1_NUMBER_OF_REPETITIONS_PER_ATTEMPT_TAG, &(pNfapiMsg->emtc_config.prach_ce_level_1_number_of_repetitions_per_attempt), ppWritePackedMsg, end, + &pack_uint16_tlv_value) && + pack_tlv(NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_1_STARTING_SUBFRAME_PERIODICITY_TAG, &(pNfapiMsg->emtc_config.prach_ce_level_1_starting_subframe_periodicity), ppWritePackedMsg, end, + &pack_uint16_tlv_value) && + pack_tlv(NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_1_HOPPING_ENABLE_TAG, &(pNfapiMsg->emtc_config.prach_ce_level_1_hopping_enable), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_1_HOPPING_OFFSET_TAG, &(pNfapiMsg->emtc_config.prach_ce_level_1_hopping_offset), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_2_ENABLE_TAG, &(pNfapiMsg->emtc_config.prach_ce_level_2_enable), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_2_CONFIGURATION_INDEX_TAG, &(pNfapiMsg->emtc_config.prach_ce_level_2_configuration_index), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_2_FREQUENCY_OFFSET_TAG, &(pNfapiMsg->emtc_config.prach_ce_level_2_frequency_offset), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_2_NUMBER_OF_REPETITIONS_PER_ATTEMPT_TAG, &(pNfapiMsg->emtc_config.prach_ce_level_2_number_of_repetitions_per_attempt), ppWritePackedMsg, end, + &pack_uint16_tlv_value) && + pack_tlv(NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_2_STARTING_SUBFRAME_PERIODICITY_TAG, &(pNfapiMsg->emtc_config.prach_ce_level_2_starting_subframe_periodicity), ppWritePackedMsg, end, + &pack_uint16_tlv_value) && + pack_tlv(NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_2_HOPPING_ENABLE_TAG, &(pNfapiMsg->emtc_config.prach_ce_level_2_hopping_enable), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_2_HOPPING_OFFSET_TAG, &(pNfapiMsg->emtc_config.prach_ce_level_2_hopping_offset), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_3_ENABLE_TAG, &(pNfapiMsg->emtc_config.prach_ce_level_3_enable), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_3_CONFIGURATION_INDEX_TAG, &(pNfapiMsg->emtc_config.prach_ce_level_3_configuration_index), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_3_FREQUENCY_OFFSET_TAG, &(pNfapiMsg->emtc_config.prach_ce_level_3_frequency_offset), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_3_NUMBER_OF_REPETITIONS_PER_ATTEMPT_TAG, &(pNfapiMsg->emtc_config.prach_ce_level_3_number_of_repetitions_per_attempt), ppWritePackedMsg, end, + &pack_uint16_tlv_value) && + pack_tlv(NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_3_STARTING_SUBFRAME_PERIODICITY_TAG, &(pNfapiMsg->emtc_config.prach_ce_level_3_starting_subframe_periodicity), ppWritePackedMsg, end, + &pack_uint16_tlv_value) && + pack_tlv(NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_3_HOPPING_ENABLE_TAG, &(pNfapiMsg->emtc_config.prach_ce_level_3_hopping_enable), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_3_HOPPING_OFFSET_TAG, &(pNfapiMsg->emtc_config.prach_ce_level_3_hopping_offset), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_EMTC_CONFIG_PUCCH_INTERVAL_ULHOPPINGCONFIGCOMMONMODEA_TAG, &(pNfapiMsg->emtc_config.pucch_interval_ulhoppingconfigcommonmodea), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_EMTC_CONFIG_PUCCH_INTERVAL_ULHOPPINGCONFIGCOMMONMODEB_TAG, &(pNfapiMsg->emtc_config.pucch_interval_ulhoppingconfigcommonmodeb), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_TDD_FRAME_STRUCTURE_SUBFRAME_ASSIGNMENT_TAG, &(pNfapiMsg->tdd_frame_structure_config.subframe_assignment), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_TDD_FRAME_STRUCTURE_SPECIAL_SUBFRAME_PATTERNS_TAG, &(pNfapiMsg->tdd_frame_structure_config.special_subframe_patterns), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_L23_CONFIG_DATA_REPORT_MODE_TAG, &(pNfapiMsg->l23_config.data_report_mode), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_L23_CONFIG_SFNSF_TAG, &(pNfapiMsg->l23_config.sfnsf), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_NFAPI_P7_VNF_ADDRESS_IPV4_TAG, &(pNfapiMsg->nfapi_config.p7_vnf_address_ipv4), ppWritePackedMsg, end, &pack_ipv4_address_value) && + pack_tlv(NFAPI_NFAPI_P7_VNF_ADDRESS_IPV6_TAG, &(pNfapiMsg->nfapi_config.p7_vnf_address_ipv6), ppWritePackedMsg, end, &pack_ipv6_address_value) && + pack_tlv(NFAPI_NFAPI_P7_VNF_PORT_TAG, &(pNfapiMsg->nfapi_config.p7_vnf_port), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_NFAPI_P7_PNF_ADDRESS_IPV4_TAG, &(pNfapiMsg->nfapi_config.p7_pnf_address_ipv4), ppWritePackedMsg, end, &pack_ipv4_address_value) && + pack_tlv(NFAPI_NFAPI_P7_PNF_ADDRESS_IPV6_TAG, &(pNfapiMsg->nfapi_config.p7_pnf_address_ipv6), ppWritePackedMsg, end, &pack_ipv6_address_value) && + pack_tlv(NFAPI_NFAPI_P7_PNF_PORT_TAG, &(pNfapiMsg->nfapi_config.p7_pnf_port), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_NFAPI_DOWNLINK_UES_PER_SUBFRAME_TAG, &(pNfapiMsg->nfapi_config.dl_ue_per_sf), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + pack_tlv(NFAPI_NFAPI_UPLINK_UES_PER_SUBFRAME_TAG, &(pNfapiMsg->nfapi_config.ul_ue_per_sf), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + pack_tlv(NFAPI_PHY_RF_BANDS_TAG, &(pNfapiMsg->nfapi_config.rf_bands), ppWritePackedMsg, end, &pack_rf_bands_value) && + pack_tlv(NFAPI_NFAPI_TIMING_WINDOW_TAG, &(pNfapiMsg->nfapi_config.timing_window), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + pack_tlv(NFAPI_NFAPI_TIMING_INFO_MODE_TAG, &(pNfapiMsg->nfapi_config.timing_info_mode), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + pack_tlv(NFAPI_NFAPI_TIMING_INFO_PERIOD_TAG, &(pNfapiMsg->nfapi_config.timing_info_period), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + pack_tlv(NFAPI_NFAPI_MAXIMUM_TRANSMIT_POWER_TAG, &(pNfapiMsg->nfapi_config.max_transmit_power), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_NFAPI_EARFCN_TAG, &(pNfapiMsg->nfapi_config.earfcn), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_NFAPI_NMM_GSM_FREQUENCY_BANDS_TAG, &(pNfapiMsg->nfapi_config.nmm_gsm_frequency_bands), ppWritePackedMsg, end, &pack_nmm_frequency_bands_value) && + pack_tlv(NFAPI_NFAPI_NMM_UMTS_FREQUENCY_BANDS_TAG, &(pNfapiMsg->nfapi_config.nmm_umts_frequency_bands), ppWritePackedMsg, end, &pack_nmm_frequency_bands_value) && + pack_tlv(NFAPI_NFAPI_NMM_LTE_FREQUENCY_BANDS_TAG, &(pNfapiMsg->nfapi_config.nmm_lte_frequency_bands), ppWritePackedMsg, end, &pack_nmm_frequency_bands_value) && + pack_tlv(NFAPI_NFAPI_NMM_UPLINK_RSSI_SUPPORTED_TAG, &(pNfapiMsg->nfapi_config.nmm_uplink_rssi_supported), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config) ); +} + + +static uint8_t pack_nr_config_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t *config) { + printf("\n\nEntering pack_config_request\n"); + nfapi_nr_config_request_scf_t *pNfapiMsg = (nfapi_nr_config_request_scf_t *)msg; + return (push8(pNfapiMsg->num_tlv, ppWritePackedMsg, end) && + pack_tlv(NFAPI_NR_CONFIG_DL_BANDWIDTH_TAG, &(pNfapiMsg->carrier_config.dl_bandwidth), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_NR_CONFIG_DL_FREQUENCY_TAG, &(pNfapiMsg->carrier_config.dl_frequency), ppWritePackedMsg, end, &pack_uint32_tlv_value) && + pack_tlv(NFAPI_NR_CONFIG_DL_GRID_SIZE_TAG, &(pNfapiMsg->carrier_config.dl_grid_size[1]), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_NR_CONFIG_DL_K0_TAG, &(pNfapiMsg->carrier_config.dl_k0[1]), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_NR_CONFIG_NUM_RX_ANT_TAG, &(pNfapiMsg->carrier_config.num_rx_ant), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_NR_CONFIG_NUM_TX_ANT_TAG, &(pNfapiMsg->carrier_config.num_tx_ant), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_NR_CONFIG_UL_GRID_SIZE_TAG, &(pNfapiMsg->carrier_config.ul_grid_size[1]), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_NR_CONFIG_UL_K0_TAG, &(pNfapiMsg->carrier_config.ul_k0[1]), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_NR_CONFIG_UPLINK_BANDWIDTH_TAG, &(pNfapiMsg->carrier_config.uplink_bandwidth), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_NR_CONFIG_UPLINK_FREQUENCY_TAG, &(pNfapiMsg->carrier_config.uplink_frequency), ppWritePackedMsg, end, &pack_uint32_tlv_value) && + pack_tlv(NFAPI_NR_CONFIG_FRAME_DUPLEX_TYPE_TAG, &(pNfapiMsg->cell_config.frame_duplex_type), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + pack_tlv(NFAPI_NR_CONFIG_PHY_CELL_ID_TAG, &(pNfapiMsg->cell_config.phy_cell_id), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + pack_tlv(NFAPI_NR_CONFIG_NUM_PRACH_FD_OCCASIONS_TAG, &(pNfapiMsg->prach_config.num_prach_fd_occasions), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + pack_tlv(NFAPI_NR_CONFIG_PRACH_SEQUENCE_LENGTH_TAG, &(pNfapiMsg->prach_config.prach_sequence_length), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + pack_tlv(NFAPI_NR_CONFIG_RESTRICTED_SET_CONFIG_TAG, &(pNfapiMsg->prach_config.restricted_set_config), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + pack_tlv(NFAPI_NR_CONFIG_SSB_PER_RACH_TAG, &(pNfapiMsg->prach_config.ssb_per_rach), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + pack_tlv(NFAPI_NR_CONFIG_PRACH_SUB_C_SPACING_TAG, &(pNfapiMsg->prach_config.prach_sub_c_spacing), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + pack_tlv(NFAPI_NR_CONFIG_PRACH_ROOT_SEQUENCE_INDEX_TAG, &(pNfapiMsg->prach_config.num_prach_fd_occasions_list[0].prach_root_sequence_index), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_NR_CONFIG_K1_TAG, &(pNfapiMsg->prach_config.num_prach_fd_occasions_list[0].k1), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_NR_CONFIG_PRACH_ZERO_CORR_CONF_TAG, &(pNfapiMsg->prach_config.num_prach_fd_occasions_list[0].prach_zero_corr_conf), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + pack_tlv(NFAPI_NR_CONFIG_NUM_ROOT_SEQUENCES_TAG, &(pNfapiMsg->prach_config.num_prach_fd_occasions_list[0].num_root_sequences), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + pack_tlv(NFAPI_NR_CONFIG_SCS_COMMON_TAG, &(pNfapiMsg->ssb_config.scs_common), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + pack_tlv(NFAPI_NR_CONFIG_SS_PBCH_POWER_TAG, &(pNfapiMsg->ssb_config.ss_pbch_power), ppWritePackedMsg, end, &pack_uint32_tlv_value) && + pack_tlv(NFAPI_NR_CONFIG_BETA_PSS_TAG, &(pNfapiMsg->ssb_table.beta_pss), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + pack_tlv(NFAPI_NR_CONFIG_MIB_TAG, &(pNfapiMsg->ssb_table.MIB), ppWritePackedMsg, end, &pack_uint32_tlv_value) && + pack_tlv(NFAPI_NR_CONFIG_SSB_MASK_TAG, &(pNfapiMsg->ssb_table.ssb_mask_list[0].ssb_mask), ppWritePackedMsg, end, &pack_uint32_tlv_value) && + pack_tlv(NFAPI_NR_CONFIG_SSB_MASK_TAG, &(pNfapiMsg->ssb_table.ssb_mask_list[1].ssb_mask), ppWritePackedMsg, end, &pack_uint32_tlv_value) && + pack_tlv(NFAPI_NR_CONFIG_SSB_OFFSET_POINT_A_TAG, &(pNfapiMsg->ssb_table.ssb_offset_point_a), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_NR_CONFIG_SSB_PERIOD_TAG, &(pNfapiMsg->ssb_table.ssb_period), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + pack_tlv(NFAPI_NR_CONFIG_SSB_SUBCARRIER_OFFSET_TAG, &(pNfapiMsg->ssb_table.ssb_subcarrier_offset), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + pack_tlv(NFAPI_NR_CONFIG_TDD_PERIOD_TAG, &(pNfapiMsg->tdd_table.tdd_period), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + pack_tlv(NFAPI_NR_CONFIG_SLOT_CONFIG_TAG, &(pNfapiMsg->tdd_table.max_tdd_periodicity_list[0].max_num_of_symbol_per_slot_list[0].slot_config), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + //pack_tlv(NFAPI_NR_NFAPI_DOWNLINK_UES_PER_SUBFRAME_TAG, &(pNfapiMsg->nfapi_config.dl_ue_per_sf), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + //pack_tlv(NFAPI_NR_NFAPI_MAXIMUM_TRANSMIT_POWER_TAG, &(pNfapiMsg->nfapi_config.max_transmit_power), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + //pack_tlv(NFAPI_NR_NFAPI_NRARFCN_TAG, &(pNfapiMsg->nfapi_config.nrarfcn), ppWritePackedMsg, end, &pack_uint32_tlv_value) && + pack_tlv(NFAPI_NR_NFAPI_P7_PNF_ADDRESS_IPV4_TAG, &(pNfapiMsg->nfapi_config.p7_pnf_address_ipv4), ppWritePackedMsg, end, &pack_ipv4_address_value) && + pack_tlv(NFAPI_NR_NFAPI_P7_PNF_ADDRESS_IPV6_TAG, &(pNfapiMsg->nfapi_config.p7_pnf_address_ipv6), ppWritePackedMsg, end, &pack_ipv6_address_value) && + pack_tlv(NFAPI_NR_NFAPI_P7_PNF_PORT_TAG, &(pNfapiMsg->nfapi_config.p7_pnf_port), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_NR_NFAPI_P7_VNF_ADDRESS_IPV4_TAG, &(pNfapiMsg->nfapi_config.p7_vnf_address_ipv4), ppWritePackedMsg, end, &pack_ipv4_address_value) && + pack_tlv(NFAPI_NR_NFAPI_P7_VNF_ADDRESS_IPV6_TAG, &(pNfapiMsg->nfapi_config.p7_vnf_address_ipv6), ppWritePackedMsg, end, &pack_ipv6_address_value) && + pack_tlv(NFAPI_NR_NFAPI_P7_VNF_PORT_TAG, &(pNfapiMsg->nfapi_config.p7_vnf_port), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + //pack_tlv(NFAPI_NR_NFAPI_RF_BANDS_TAG, &(pNfapiMsg->nfapi_config.rf_bands), ppWritePackedMsg, end, &pack_rf_bands_value) && + pack_tlv(NFAPI_NR_NFAPI_TIMING_INFO_MODE_TAG, &(pNfapiMsg->nfapi_config.timing_info_mode), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + pack_tlv(NFAPI_NR_NFAPI_TIMING_INFO_PERIOD_TAG, &(pNfapiMsg->nfapi_config.timing_info_period), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + pack_tlv(NFAPI_NR_NFAPI_TIMING_WINDOW_TAG, &(pNfapiMsg->nfapi_config.timing_window), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + //pack_tlv(NFAPI_NR_NFAPI_UPLINK_UES_PER_SUBFRAME_TAG, &(pNfapiMsg->nfapi_config.ul_ue_per_sf), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config) ); +} + +static uint8_t pack_nr_config_response(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t *config) { + nfapi_nr_config_response_scf_t *pNfapiMsg = (nfapi_nr_config_response_scf_t *)msg; + return ( push8(pNfapiMsg->error_code, ppWritePackedMsg, end) && + pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config) ); +} + +static uint8_t pack_config_response(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t *config) { + nfapi_config_response_t *pNfapiMsg = (nfapi_config_response_t *)msg; + return ( push8(pNfapiMsg->error_code, ppWritePackedMsg, end) && + pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config) ); +} + +static uint8_t pack_nr_start_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t *config) { + nfapi_nr_start_request_scf_t *pNfapiMsg = (nfapi_nr_start_request_scf_t *)msg; + return pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config); +} + +static uint8_t pack_start_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t *config) { + nfapi_start_request_t *pNfapiMsg = (nfapi_start_request_t *)msg; + return pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config); +} + +static uint8_t pack_nr_start_response(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t *config) { + nfapi_nr_start_response_scf_t *pNfapiMsg = (nfapi_nr_start_response_scf_t *)msg; + return ( push32(pNfapiMsg->error_code, ppWritePackedMsg, end ) && + pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config) ); +} + +static uint8_t pack_start_response(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t *config) { + nfapi_start_response_t *pNfapiMsg = (nfapi_start_response_t *)msg; + return ( push32(pNfapiMsg->error_code, ppWritePackedMsg, end ) && + pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config) ); +} + + +static uint8_t pack_stop_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t *config) { + nfapi_stop_request_t *pNfapiMsg = (nfapi_stop_request_t *)msg; + return pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config); +} + +static uint8_t pack_stop_response(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t *config) { + nfapi_stop_response_t *pNfapiMsg = (nfapi_stop_response_t *)msg; + return ( push32(pNfapiMsg->error_code, ppWritePackedMsg, end) && + pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config) ); +} + +static uint8_t pack_measurement_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t *config) { + nfapi_measurement_request_t *pNfapiMsg = (nfapi_measurement_request_t *)msg; + return( pack_tlv(NFAPI_MEASUREMENT_REQUEST_DL_RS_XTX_POWER_TAG, &(pNfapiMsg->dl_rs_tx_power), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_MEASUREMENT_REQUEST_RECEIVED_INTERFERENCE_POWER_TAG, &(pNfapiMsg->received_interference_power), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_MEASUREMENT_REQUEST_THERMAL_NOISE_POWER_TAG, &(pNfapiMsg->thermal_noise_power), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); +} + +static uint8_t pack_recevied_interference_power_measurement_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_received_interference_power_measurement_t *value = (nfapi_received_interference_power_measurement_t *)tlv; + return ( push16(value->number_of_resource_blocks, ppWritePackedMsg, end) && + pusharrays16(value->received_interference_power, NFAPI_MAX_RECEIVED_INTERFERENCE_POWER_RESULTS, value->number_of_resource_blocks, ppWritePackedMsg, end)); +} + +static uint8_t pack_measurement_response(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t *config) { + nfapi_measurement_response_t *pNfapiMsg = (nfapi_measurement_response_t *)msg; + return( push32(pNfapiMsg->error_code, ppWritePackedMsg, end) && + pack_tlv(NFAPI_MEASUREMENT_RESPONSE_DL_RS_POWER_MEASUREMENT_TAG, &(pNfapiMsg->dl_rs_tx_power_measurement), ppWritePackedMsg, end, &pack_int16_tlv_value) && + pack_tlv(NFAPI_MEASUREMENT_RESPONSE_RECEIVED_INTERFERENCE_POWER_MEASUREMENT_TAG, &(pNfapiMsg->received_interference_power_measurement), ppWritePackedMsg, end, + &pack_recevied_interference_power_measurement_value) && + pack_tlv(NFAPI_MEASUREMENT_RESPONSE_THERMAL_NOISE_MEASUREMENT_TAG, &(pNfapiMsg->thermal_noise_power_measurement), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); +} + +static uint8_t pack_nr_p5_message_body(nfapi_p4_p5_message_header_t *header, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t *config) { + uint8_t result = 0; + + // look for the specific message + switch (header->message_id) { + case NFAPI_NR_PHY_MSG_TYPE_PNF_PARAM_REQUEST: + result = pack_nr_pnf_param_request(header, ppWritePackedMsg, end, config); + break; + + case NFAPI_PNF_PARAM_RESPONSE: + result = pack_nr_pnf_param_response(header, ppWritePackedMsg, end, config); + break; + + case NFAPI_NR_PHY_MSG_TYPE_PNF_CONFIG_REQUEST: + result = pack_nr_pnf_config_request(header, ppWritePackedMsg, end, config); + break; + + case NFAPI_NR_PHY_MSG_TYPE_PNF_CONFIG_RESPONSE: + result = pack_nr_pnf_config_response(header, ppWritePackedMsg, end, config); + break; + + case NFAPI_NR_PHY_MSG_TYPE_PNF_START_REQUEST: + result = pack_nr_pnf_start_request(header, ppWritePackedMsg, end, config); + break; + + case NFAPI_NR_PHY_MSG_TYPE_PNF_START_RESPONSE: + result = pack_nr_pnf_start_response(header, ppWritePackedMsg, end, config); + break; + + case NFAPI_NR_PHY_MSG_TYPE_PNF_STOP_REQUEST: + result = pack_nr_pnf_stop_request(header, ppWritePackedMsg, end, config); + break; + + case NFAPI_PNF_STOP_RESPONSE: + result = pack_nr_pnf_stop_response(header, ppWritePackedMsg, end, config); + break; + + case NFAPI_NR_PHY_MSG_TYPE_PARAM_REQUEST: + result = pack_nr_param_request(header, ppWritePackedMsg, end, config); + break; + + case NFAPI_NR_PHY_MSG_TYPE_PARAM_RESPONSE: + result = pack_nr_param_response(header, ppWritePackedMsg, end, config); + break; + + case NFAPI_NR_PHY_MSG_TYPE_CONFIG_REQUEST: + result = pack_nr_config_request(header, ppWritePackedMsg, end, config); + break; + + case NFAPI_NR_PHY_MSG_TYPE_CONFIG_RESPONSE: + result = pack_nr_config_response(header, ppWritePackedMsg, end, config); + break; + + case NFAPI_NR_PHY_MSG_TYPE_START_REQUEST: + result = pack_nr_start_request(header, ppWritePackedMsg, end, config); + break; + + case NFAPI_NR_PHY_MSG_TYPE_START_RESPONSE: + result = pack_nr_start_response(header, ppWritePackedMsg, end, config); + break; + + case NFAPI_NR_PHY_MSG_TYPE_STOP_REQUEST: + result = pack_stop_request(header, ppWritePackedMsg, end, config); + break; + + case NFAPI_NR_PHY_MSG_TYPE_STOP_RESPONSE: + result = pack_stop_response(header, ppWritePackedMsg, end, config); + break; + + default: { + if(header->message_id >= NFAPI_VENDOR_EXT_MSG_MIN && + header->message_id <= NFAPI_VENDOR_EXT_MSG_MAX) { + if(config && config->pack_p4_p5_vendor_extension) { + result = (config->pack_p4_p5_vendor_extension)(header, ppWritePackedMsg, end, config); + } else { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s VE NFAPI message ID %d. No ve ecoder provided\n", __FUNCTION__, header->message_id); + } + } else { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s NFAPI Unknown message ID %d\n", __FUNCTION__, header->message_id); + } + } + break; + } + + return result; +} + + +static uint8_t pack_p5_message_body(nfapi_p4_p5_message_header_t *header, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t *config) { + uint8_t result = 0; + + // look for the specific message + switch (header->message_id) { + case NFAPI_PNF_PARAM_REQUEST: + result = pack_pnf_param_request(header, ppWritePackedMsg, end, config); + break; + + case NFAPI_PNF_PARAM_RESPONSE: + result = pack_pnf_param_response(header, ppWritePackedMsg, end, config); + break; + + case NFAPI_PNF_CONFIG_REQUEST: + result = pack_pnf_config_request(header, ppWritePackedMsg, end, config); + break; + + case NFAPI_PNF_CONFIG_RESPONSE: + result = pack_pnf_config_response(header, ppWritePackedMsg, end, config); + break; + + case NFAPI_PNF_START_REQUEST: + result = pack_pnf_start_request(header, ppWritePackedMsg, end, config); + break; + + case NFAPI_PNF_START_RESPONSE: + result = pack_pnf_start_response(header, ppWritePackedMsg, end, config); + break; + + case NFAPI_PNF_STOP_REQUEST: + result = pack_pnf_stop_request(header, ppWritePackedMsg, end, config); + break; + + case NFAPI_PNF_STOP_RESPONSE: + result = pack_pnf_stop_response(header, ppWritePackedMsg, end, config); + break; + + case NFAPI_PARAM_REQUEST: + result = pack_param_request(header, ppWritePackedMsg, end, config); + break; + + case NFAPI_PARAM_RESPONSE: + result = pack_param_response(header, ppWritePackedMsg, end, config); + break; + + case NFAPI_CONFIG_REQUEST: + result = pack_config_request(header, ppWritePackedMsg, end, config); + break; + + case NFAPI_CONFIG_RESPONSE: + result = pack_config_response(header, ppWritePackedMsg, end, config); + break; + + case NFAPI_START_REQUEST: + result = pack_start_request(header, ppWritePackedMsg, end, config); + break; + + case NFAPI_START_RESPONSE: + result = pack_start_response(header, ppWritePackedMsg, end, config); + break; + + case NFAPI_STOP_REQUEST: + result = pack_stop_request(header, ppWritePackedMsg, end, config); + break; + + case NFAPI_STOP_RESPONSE: + result = pack_stop_response(header, ppWritePackedMsg, end, config); + break; + + case NFAPI_MEASUREMENT_REQUEST: + result = pack_measurement_request(header, ppWritePackedMsg, end, config); + break; + + case NFAPI_MEASUREMENT_RESPONSE: + result = pack_measurement_response(header, ppWritePackedMsg, end, config); + break; + + default: { + if(header->message_id >= NFAPI_VENDOR_EXT_MSG_MIN && + header->message_id <= NFAPI_VENDOR_EXT_MSG_MAX) { + if(config && config->pack_p4_p5_vendor_extension) { + result = (config->pack_p4_p5_vendor_extension)(header, ppWritePackedMsg, end, config); + } else { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s VE NFAPI message ID %d. No ve ecoder provided\n", __FUNCTION__, header->message_id); + } + } else { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s NFAPI Unknown message ID %d\n", __FUNCTION__, header->message_id); + } + } + break; + } + + return result; +} + + +// helper function for message length calculation - +// takes the pointers to the start of message to end of message + +static uint32_t get_packed_msg_len(uintptr_t msgHead, uintptr_t msgEnd) { + if (msgEnd < msgHead) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "get_packed_msg_len: Error in pointers supplied %d, %d\n", msgHead, msgEnd); + return 0; + } + + return (msgEnd - msgHead); +} + +// Main pack function - public +int nfapi_nr_p5_message_pack(void *pMessageBuf, uint32_t messageBufLen, void *pPackedBuf, uint32_t packedBufLen, nfapi_p4_p5_codec_config_t *config) { + nfapi_p4_p5_message_header_t *pMessageHeader = pMessageBuf; + uint8_t *pWritePackedMessage = pPackedBuf; + uint8_t *pPackMessageEnd = pPackedBuf + packedBufLen; + uint8_t *pPackedLengthField = &pWritePackedMessage[4]; + uint32_t packedMsgLen; + uint16_t packedMsgLen16; + + if (pMessageBuf == NULL || pPackedBuf == NULL) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "P5 Pack supplied pointers are null\n"); + return -1; + } + + // pack the message + if(push16(pMessageHeader->phy_id, &pWritePackedMessage, pPackMessageEnd) && + push16(pMessageHeader->message_id, &pWritePackedMessage, pPackMessageEnd) && + push16(0, &pWritePackedMessage, pPackMessageEnd) && + push16(pMessageHeader->spare, &pWritePackedMessage, pPackMessageEnd) && + pack_nr_p5_message_body(pMessageHeader, &pWritePackedMessage, pPackMessageEnd, config)) { + // check for a valid message length + packedMsgLen = get_packed_msg_len((uintptr_t)pPackedBuf, (uintptr_t)pWritePackedMessage); + + if (packedMsgLen > 0xFFFF || packedMsgLen > packedBufLen) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "Packed message length error %d, buffer supplied %d\n", packedMsgLen, packedBufLen); + return -1; + } else { + packedMsgLen16 = (uint16_t)packedMsgLen; + } + + // Update the message length in the header + if(!push16(packedMsgLen16, &pPackedLengthField, pPackMessageEnd)) + return -1; + + // return the packed length + return (packedMsgLen); + } else { + // Failed to pack the meassage + NFAPI_TRACE(NFAPI_TRACE_ERROR, "P5 Failed to pack message\n"); + return -1; + } +} + +int nfapi_p5_message_pack(void *pMessageBuf, uint32_t messageBufLen, void *pPackedBuf, uint32_t packedBufLen, nfapi_p4_p5_codec_config_t *config) { + nfapi_p4_p5_message_header_t *pMessageHeader = pMessageBuf; + uint8_t *pWritePackedMessage = pPackedBuf; + uint8_t *pPackMessageEnd = pPackedBuf + packedBufLen; + uint8_t *pPackedLengthField = &pWritePackedMessage[4]; + uint32_t packedMsgLen; + uint16_t packedMsgLen16; + + if (pMessageBuf == NULL || pPackedBuf == NULL) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "P5 Pack supplied pointers are null\n"); + return -1; + } + + // pack the message + if(push16(pMessageHeader->phy_id, &pWritePackedMessage, pPackMessageEnd) && + push16(pMessageHeader->message_id, &pWritePackedMessage, pPackMessageEnd) && + push16(0/*pMessageHeader->message_length*/, &pWritePackedMessage, pPackMessageEnd) && + push16(pMessageHeader->spare, &pWritePackedMessage, pPackMessageEnd) && + pack_p5_message_body(pMessageHeader, &pWritePackedMessage, pPackMessageEnd, config)) { + // check for a valid message length + packedMsgLen = get_packed_msg_len((uintptr_t)pPackedBuf, (uintptr_t)pWritePackedMessage); + + if (packedMsgLen > 0xFFFF || packedMsgLen > packedBufLen) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "Packed message length error %d, buffer supplied %d\n", packedMsgLen, packedBufLen); + return -1; + } else { + packedMsgLen16 = (uint16_t)packedMsgLen; + } + + // Update the message length in the header + if(!push16(packedMsgLen16, &pPackedLengthField, pPackMessageEnd)) + return -1; + + // return the packed length + return (packedMsgLen); + } else { + // Failed to pack the meassage + NFAPI_TRACE(NFAPI_TRACE_ERROR, "P5 Failed to pack message\n"); + return -1; + } +} + + + +// Unpack routines + + +static uint8_t unpack_nr_pnf_param_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t *config) { + nfapi_nr_pnf_param_request_t *pNfapiMsg = (nfapi_nr_pnf_param_request_t *)msg; + return unpack_tlv_list(NULL, 0, ppReadPackedMsg, end, config, &(pNfapiMsg->vendor_extension)); +} + + +static uint8_t unpack_pnf_param_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t *config) { + nfapi_pnf_param_request_t *pNfapiMsg = (nfapi_pnf_param_request_t *)msg; + return unpack_tlv_list(NULL, 0, ppReadPackedMsg, end, config, &(pNfapiMsg->vendor_extension)); +} + +static uint8_t unpack_pnf_param_general_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_pnf_param_general_t *value = (nfapi_pnf_param_general_t *)tlv; + return( pull8(ppReadPackedMsg, &value->nfapi_sync_mode, end) && + pull8(ppReadPackedMsg, &value->location_mode, end) && + pull16(ppReadPackedMsg, &value->location_coordinates_length, end) && + pullarray8(ppReadPackedMsg, value->location_coordinates, NFAPI_PNF_PARAM_GENERAL_LOCATION_LENGTH, value->location_coordinates_length, end) && + pull32(ppReadPackedMsg, &value->dl_config_timing, end) && + pull32(ppReadPackedMsg, &value->tx_timing, end) && + pull32(ppReadPackedMsg, &value->ul_config_timing, end) && + pull32(ppReadPackedMsg, &value->hi_dci0_timing, end) && + pull16(ppReadPackedMsg, &value->maximum_number_phys, end) && + pull16(ppReadPackedMsg, &value->maximum_total_bandwidth, end) && + pull8(ppReadPackedMsg, &value->maximum_total_number_dl_layers, end) && + pull8(ppReadPackedMsg, &value->maximum_total_number_ul_layers, end) && + pull8(ppReadPackedMsg, &value->shared_bands, end) && + pull8(ppReadPackedMsg, &value->shared_pa, end) && + pulls16(ppReadPackedMsg, &value->maximum_total_power, end) && + pullarray8(ppReadPackedMsg, value->oui, NFAPI_PNF_PARAM_GENERAL_OUI_LENGTH, NFAPI_PNF_PARAM_GENERAL_OUI_LENGTH, end)); +} + +static uint8_t unpack_rf_config_info(void *elem, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_rf_config_info_t *info = (nfapi_rf_config_info_t *)elem; + return pull16(ppReadPackedMsg, &info->rf_config_index, end); +} + +static uint8_t unpack_pnf_phy_info(void *elem, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_pnf_phy_info_t *phy = (nfapi_pnf_phy_info_t *)elem; + return ( pull16(ppReadPackedMsg, &phy->phy_config_index, end) && + pull16(ppReadPackedMsg, &phy->number_of_rfs, end) && + unpackarray(ppReadPackedMsg, phy->rf_config, sizeof(nfapi_rf_config_info_t), NFAPI_MAX_PNF_PHY_RF_CONFIG, phy->number_of_rfs, end, &unpack_rf_config_info) && + pull16(ppReadPackedMsg, &phy->number_of_rf_exclusions, end) && + unpackarray(ppReadPackedMsg, phy->excluded_rf_config, sizeof(nfapi_rf_config_info_t), NFAPI_MAX_PNF_PHY_RF_CONFIG, phy->number_of_rf_exclusions, end, &unpack_rf_config_info) && + pull16(ppReadPackedMsg, &phy->downlink_channel_bandwidth_supported, end) && + pull16(ppReadPackedMsg, &phy->uplink_channel_bandwidth_supported, end) && + pull8(ppReadPackedMsg, &phy->number_of_dl_layers_supported, end) && + pull8(ppReadPackedMsg, &phy->number_of_ul_layers_supported, end) && + pull16(ppReadPackedMsg, &phy->maximum_3gpp_release_supported, end) && + pull8(ppReadPackedMsg, &phy->nmm_modes_supported, end)); +} + + +static uint8_t unpack_pnf_phy_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_pnf_phy_t *value = (nfapi_pnf_phy_t *)tlv; + return ( pull16(ppReadPackedMsg, &value->number_of_phys, end) && + unpackarray(ppReadPackedMsg, value->phy, sizeof(nfapi_pnf_phy_info_t), NFAPI_MAX_PNF_PHY, value->number_of_phys, end, &unpack_pnf_phy_info)); +} + +static uint8_t unpack_pnf_rf_info(void *elem, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_pnf_rf_info_t *rf = (nfapi_pnf_rf_info_t *)elem; + return( pull16(ppReadPackedMsg, &rf->rf_config_index, end) && + pull16(ppReadPackedMsg, &rf->band, end) && + pulls16(ppReadPackedMsg, &rf->maximum_transmit_power, end) && + pulls16(ppReadPackedMsg, &rf->minimum_transmit_power, end) && + pull8(ppReadPackedMsg, &rf->number_of_antennas_suppported, end) && + pull32(ppReadPackedMsg, &rf->minimum_downlink_frequency, end) && + pull32(ppReadPackedMsg, &rf->maximum_downlink_frequency, end) && + pull32(ppReadPackedMsg, &rf->minimum_uplink_frequency, end) && + pull32(ppReadPackedMsg, &rf->maximum_uplink_frequency, end)); +} +static uint8_t unpack_pnf_rf_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_pnf_rf_t *value = (nfapi_pnf_rf_t *)tlv; + return ( pull16(ppReadPackedMsg, &value->number_of_rfs, end) && + unpackarray(ppReadPackedMsg, value->rf, sizeof(nfapi_pnf_rf_info_t), NFAPI_MAX_PNF_RF, value->number_of_rfs, end, &unpack_pnf_rf_info)); +} + +static uint8_t unpack_pnf_phy_rel10_info(void *elem, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_pnf_phy_rel10_info_t *phy = (nfapi_pnf_phy_rel10_info_t *)elem; + return( pull16(ppReadPackedMsg, &phy->phy_config_index, end) && + pull16(ppReadPackedMsg, &phy->transmission_mode_7_supported, end) && + pull16(ppReadPackedMsg, &phy->transmission_mode_8_supported, end) && + pull16(ppReadPackedMsg, &phy->two_antenna_ports_for_pucch, end) && + pull16(ppReadPackedMsg, &phy->transmission_mode_9_supported, end) && + pull16(ppReadPackedMsg, &phy->simultaneous_pucch_pusch, end) && + pull16(ppReadPackedMsg, &phy->four_layer_tx_with_tm3_and_tm4, end)); +} +static uint8_t unpack_pnf_phy_rel10_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_pnf_phy_rel10_t *value = (nfapi_pnf_phy_rel10_t *)tlv; + return ( pull16(ppReadPackedMsg, &value->number_of_phys, end) && + unpackarray(ppReadPackedMsg, value->phy, sizeof(nfapi_pnf_phy_rel10_info_t), NFAPI_MAX_PNF_PHY, value->number_of_phys, end, &unpack_pnf_phy_rel10_info)); +} + + +static uint8_t unpack_pnf_phy_rel11_info(void *elem, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_pnf_phy_rel11_info_t *phy = (nfapi_pnf_phy_rel11_info_t *)elem; + return( pull16(ppReadPackedMsg, &phy->phy_config_index, end) && + pull16(ppReadPackedMsg, &phy->edpcch_supported, end) && + pull16(ppReadPackedMsg, &phy->multi_ack_csi_reporting, end ) && + pull16(ppReadPackedMsg, &phy->pucch_tx_diversity, end) && + pull16(ppReadPackedMsg, &phy->ul_comp_supported, end) && + pull16(ppReadPackedMsg, &phy->transmission_mode_5_supported, end)); +} + +static uint8_t unpack_pnf_phy_rel11_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_pnf_phy_rel11_t *value = (nfapi_pnf_phy_rel11_t *)tlv; + return ( pull16(ppReadPackedMsg, &value->number_of_phys, end) && + unpackarray(ppReadPackedMsg, value->phy, sizeof(nfapi_pnf_phy_rel11_info_t), NFAPI_MAX_PNF_PHY, value->number_of_phys, end, &unpack_pnf_phy_rel11_info)); +} + +static uint8_t unpack_phy_phy_rel12_info(void *elem, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_pnf_phy_rel12_info_t *phy = (nfapi_pnf_phy_rel12_info_t *)elem; + return( pull16(ppReadPackedMsg, &phy->phy_config_index, end) && + pull16(ppReadPackedMsg, &phy->csi_subframe_set, end) && + pull16(ppReadPackedMsg, &phy->enhanced_4tx_codebook, end) && + pull16(ppReadPackedMsg, &phy->drs_supported, end) && + pull16(ppReadPackedMsg, &phy->ul_64qam_supported, end) && + pull16(ppReadPackedMsg, &phy->transmission_mode_10_supported, end) && + pull16(ppReadPackedMsg, &phy->alternative_bts_indices, end)); +} + +static uint8_t unpack_pnf_phy_rel12_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_pnf_phy_rel12_t *value = (nfapi_pnf_phy_rel12_t *)tlv; + return (pull16(ppReadPackedMsg, &value->number_of_phys, end) && + unpackarray(ppReadPackedMsg, value->phy, sizeof(nfapi_pnf_phy_rel12_t), NFAPI_MAX_PNF_PHY, value->number_of_phys, end, &unpack_phy_phy_rel12_info)); +} + +static uint8_t unpack_pnf_phy_rel13_info(void *elem, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_pnf_phy_rel13_info_t *phy = (nfapi_pnf_phy_rel13_info_t *)elem; + return( pull16(ppReadPackedMsg, &phy->phy_config_index, end) && + pull16(ppReadPackedMsg, &phy->pucch_format4_supported, end) && + pull16(ppReadPackedMsg, &phy->pucch_format5_supported, end) && + pull16(ppReadPackedMsg, &phy->more_than_5_ca_support, end) && + pull16(ppReadPackedMsg, &phy->laa_supported, end) && + pull16(ppReadPackedMsg, &phy->laa_ending_in_dwpts_supported, end) && + pull16(ppReadPackedMsg, &phy->laa_starting_in_second_slot_supported, end) && + pull16(ppReadPackedMsg, &phy->beamforming_supported, end) && + pull16(ppReadPackedMsg, &phy->csi_rs_enhancement_supported, end) && + pull16(ppReadPackedMsg, &phy->drms_enhancement_supported, end) && + pull16(ppReadPackedMsg, &phy->srs_enhancement_supported, end)); +} + +static uint8_t unpack_pnf_phy_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_pnf_phy_rel13_t *value = (nfapi_pnf_phy_rel13_t *)tlv; + return ( pull16(ppReadPackedMsg, &value->number_of_phys, end) && + unpackarray(ppReadPackedMsg, value->phy, sizeof(nfapi_pnf_phy_rel13_info_t), NFAPI_MAX_PNF_PHY, value->number_of_phys, end, &unpack_pnf_phy_rel13_info)); +} + +static uint8_t unpack_pnf_phy_rel13_nb_info_info(void *elem, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_pnf_phy_rel13_nb_iot_info_t *phy = (nfapi_pnf_phy_rel13_nb_iot_info_t *)elem; + return( pull16(ppReadPackedMsg, &phy->phy_config_index, end) && + pull16(ppReadPackedMsg, &phy->number_of_rfs, end) && + unpackarray(ppReadPackedMsg, phy->rf_config, sizeof(nfapi_rf_config_info_t), NFAPI_MAX_PNF_PHY_RF_CONFIG, phy->number_of_rfs, end, &unpack_rf_config_info) && + pull16(ppReadPackedMsg, &phy->number_of_rf_exclusions, end) && + unpackarray(ppReadPackedMsg, phy->excluded_rf_config, sizeof(nfapi_rf_config_info_t), NFAPI_MAX_PNF_PHY_RF_CONFIG, phy->number_of_rf_exclusions, end, &unpack_rf_config_info) && + pull8(ppReadPackedMsg, &phy->number_of_dl_layers_supported, end) && + pull8(ppReadPackedMsg, &phy->number_of_ul_layers_supported, end) && + pull16(ppReadPackedMsg, &phy->maximum_3gpp_release_supported, end) && + pull8(ppReadPackedMsg, &phy->nmm_modes_supported, end)); +} + +static uint8_t unpack_pnf_phy_rel13_nb_iot_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_pnf_phy_rel13_nb_iot_t *value = (nfapi_pnf_phy_rel13_nb_iot_t *)tlv; + return ( pull16(ppReadPackedMsg, &value->number_of_phys, end) && + unpackarray(ppReadPackedMsg, value->phy, sizeof(nfapi_pnf_phy_rel13_nb_iot_info_t), NFAPI_MAX_PNF_PHY, value->number_of_phys, end, &unpack_pnf_phy_rel13_nb_info_info)); +} + +static uint8_t unpack_nr_pnf_param_response(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t *config) { + nfapi_nr_pnf_param_response_t *pNfapiMsg = (nfapi_nr_pnf_param_response_t *)msg; + unpack_tlv_t unpack_fns[] = { + { NFAPI_PNF_PARAM_GENERAL_TAG, &pNfapiMsg->pnf_param_general, &unpack_pnf_param_general_value}, + { NFAPI_PNF_PHY_TAG, &pNfapiMsg->pnf_phy, &unpack_pnf_phy_value}, + }; + return ( pull32(ppReadPackedMsg, &pNfapiMsg->error_code, end) && + unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); +} + + + +static uint8_t unpack_pnf_param_response(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t *config) { + nfapi_pnf_param_response_t *pNfapiMsg = (nfapi_pnf_param_response_t *)msg; + unpack_tlv_t unpack_fns[] = { + { NFAPI_PNF_PARAM_GENERAL_TAG, &pNfapiMsg->pnf_param_general, &unpack_pnf_param_general_value}, + { NFAPI_PNF_PHY_TAG, &pNfapiMsg->pnf_phy, &unpack_pnf_phy_value}, + { NFAPI_PNF_RF_TAG, &pNfapiMsg->pnf_rf, &unpack_pnf_rf_value}, + { NFAPI_PNF_PHY_REL10_TAG, &pNfapiMsg->pnf_phy_rel10, &unpack_pnf_phy_rel10_value}, + { NFAPI_PNF_PHY_REL11_TAG, &pNfapiMsg->pnf_phy_rel11, &unpack_pnf_phy_rel11_value}, + { NFAPI_PNF_PHY_REL12_TAG, &pNfapiMsg->pnf_phy_rel12, &unpack_pnf_phy_rel12_value}, + { NFAPI_PNF_PHY_REL13_TAG, &pNfapiMsg->pnf_phy_rel13, &unpack_pnf_phy_rel13_value}, + { NFAPI_PNF_PHY_REL13_NB_IOT_TAG, &pNfapiMsg->pnf_phy_rel13_nb_iot, &unpack_pnf_phy_rel13_nb_iot_value}, + + }; + return ( pull32(ppReadPackedMsg, &pNfapiMsg->error_code, end) && + unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); +} + + +static uint8_t unpack_phy_rf_config_info(void *elem, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_phy_rf_config_info_t *rf = (nfapi_phy_rf_config_info_t *)elem; + return( pull16(ppReadPackedMsg, &rf->phy_id, end) && + pull16(ppReadPackedMsg, &rf->phy_config_index, end) && + pull16(ppReadPackedMsg, &rf->rf_config_index, end)); +} + +static uint8_t unpack_pnf_phy_rf_config_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_pnf_phy_rf_config_t *value = (nfapi_pnf_phy_rf_config_t *)tlv; + return ( pull16(ppReadPackedMsg, &value->number_phy_rf_config_info, end) && + unpackarray(ppReadPackedMsg, value->phy_rf_config, sizeof(nfapi_phy_rf_config_info_t), NFAPI_MAX_PHY_RF_INSTANCES, value->number_phy_rf_config_info, end, &unpack_phy_rf_config_info)); +} + +static uint8_t unpack_nr_pnf_config_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t *config) { + nfapi_nr_pnf_config_request_t *pNfapiMsg = (nfapi_nr_pnf_config_request_t *)msg; + unpack_tlv_t unpack_fns[] = { + { NFAPI_PNF_PHY_RF_TAG, &pNfapiMsg->pnf_phy_rf_config, &unpack_pnf_phy_rf_config_value}, + }; + return unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension); +} + + + +static uint8_t unpack_pnf_config_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t *config) { + nfapi_pnf_config_request_t *pNfapiMsg = (nfapi_pnf_config_request_t *)msg; + unpack_tlv_t unpack_fns[] = { + { NFAPI_PNF_PHY_RF_TAG, &pNfapiMsg->pnf_phy_rf_config, &unpack_pnf_phy_rf_config_value}, + }; + return unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension); +} + + +static uint8_t unpack_nr_pnf_config_response(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t *config) { + nfapi_nr_pnf_config_response_t *pNfapiMsg = (nfapi_nr_pnf_config_response_t *)msg; + return ( pull32(ppReadPackedMsg, &pNfapiMsg->error_code, end) && + unpack_tlv_list(NULL, 0, ppReadPackedMsg, end, config, &(pNfapiMsg->vendor_extension))); +} + +static uint8_t unpack_pnf_config_response(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t *config) { + nfapi_pnf_config_response_t *pNfapiMsg = (nfapi_pnf_config_response_t *)msg; + return ( pull32(ppReadPackedMsg, &pNfapiMsg->error_code, end) && + unpack_tlv_list(NULL, 0, ppReadPackedMsg, end, config, &(pNfapiMsg->vendor_extension))); +} + +static uint8_t unpack_nr_pnf_start_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t *config) { + nfapi_nr_pnf_start_request_t *pNfapiMsg = (nfapi_nr_pnf_start_request_t *)msg; + return unpack_tlv_list(NULL, 0, ppReadPackedMsg, end, config, &(pNfapiMsg->vendor_extension)); +} + + +static uint8_t unpack_pnf_start_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t *config) { + nfapi_pnf_start_request_t *pNfapiMsg = (nfapi_pnf_start_request_t *)msg; + return unpack_tlv_list(NULL, 0, ppReadPackedMsg, end, config, &(pNfapiMsg->vendor_extension)); +} + + +static uint8_t unpack_pnf_start_response(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t *config) { + nfapi_pnf_start_response_t *pNfapiMsg = (nfapi_pnf_start_response_t *)msg; + return ( pull32(ppReadPackedMsg, &pNfapiMsg->error_code, end ) && + unpack_tlv_list(NULL, 0, ppReadPackedMsg, end, config, &(pNfapiMsg->vendor_extension))); +} + +static uint8_t unpack_nr_pnf_start_response(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t *config) { + nfapi_nr_pnf_start_response_t *pNfapiMsg = (nfapi_nr_pnf_start_response_t *)msg; + return ( pull32(ppReadPackedMsg, &pNfapiMsg->error_code, end ) && + unpack_tlv_list(NULL, 0, ppReadPackedMsg, end, config, &(pNfapiMsg->vendor_extension))); +} + + +static uint8_t unpack_pnf_stop_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t *config) { + nfapi_pnf_stop_request_t *pNfapiMsg = (nfapi_pnf_stop_request_t *)msg; + return unpack_tlv_list(NULL, 0, ppReadPackedMsg, end, config, &(pNfapiMsg->vendor_extension)); +} + +static uint8_t unpack_pnf_stop_response(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t *config) { + nfapi_pnf_stop_response_t *pNfapiMsg = (nfapi_pnf_stop_response_t *)msg; + return ( pull32(ppReadPackedMsg, &pNfapiMsg->error_code, end) && + unpack_tlv_list(NULL, 0, ppReadPackedMsg, end, config, &(pNfapiMsg->vendor_extension))); +} + +static uint8_t unpack_param_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t *config) { + nfapi_param_request_t *pNfapiMsg = (nfapi_param_request_t *)msg; + return unpack_tlv_list(NULL, 0, ppReadPackedMsg, end, config, &(pNfapiMsg->vendor_extension)); +} + +static uint8_t unpack_nr_param_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t *config) { + nfapi_nr_param_request_scf_t *pNfapiMsg = (nfapi_nr_param_request_scf_t *)msg; + return unpack_tlv_list(NULL, 0, ppReadPackedMsg, end, config, &(pNfapiMsg->vendor_extension)); +} + +static uint8_t unpack_param_response(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t *config) { + nfapi_param_response_t *pNfapiMsg = (nfapi_param_response_t *)msg; + unpack_tlv_t unpack_fns[] = { + { NFAPI_L1_STATUS_PHY_STATE_TAG, &pNfapiMsg->l1_status.phy_state, &unpack_uint16_tlv_value}, + + { NFAPI_PHY_CAPABILITIES_DL_BANDWIDTH_SUPPORT_TAG, &pNfapiMsg->phy_capabilities.dl_bandwidth_support, &unpack_uint16_tlv_value}, + { NFAPI_PHY_CAPABILITIES_UL_BANDWIDTH_SUPPORT_TAG, &pNfapiMsg->phy_capabilities.ul_bandwidth_support, &unpack_uint16_tlv_value}, + { NFAPI_PHY_CAPABILITIES_DL_MODULATION_SUPPORT_TAG, &pNfapiMsg->phy_capabilities.dl_modulation_support, &unpack_uint16_tlv_value}, + { NFAPI_PHY_CAPABILITIES_UL_MODULATION_SUPPORT_TAG, &pNfapiMsg->phy_capabilities.ul_modulation_support, &unpack_uint16_tlv_value}, + { NFAPI_PHY_CAPABILITIES_PHY_ANTENNA_CAPABILITY_TAG, &pNfapiMsg->phy_capabilities.phy_antenna_capability, &unpack_uint16_tlv_value}, + { NFAPI_PHY_CAPABILITIES_RELEASE_CAPABILITY_TAG, &pNfapiMsg->phy_capabilities.release_capability, &unpack_uint16_tlv_value}, + { NFAPI_PHY_CAPABILITIES_MBSFN_CAPABILITY_TAG, &pNfapiMsg->phy_capabilities.mbsfn_capability, &unpack_uint16_tlv_value}, + + { NFAPI_LAA_CAPABILITY_LAA_SUPPORT_TAG, &pNfapiMsg->laa_capability.laa_support, &unpack_uint16_tlv_value}, + { NFAPI_LAA_CAPABILITY_PD_SENSING_LBT_SUPPORT_TAG, &pNfapiMsg->laa_capability.pd_sensing_lbt_support, &unpack_uint16_tlv_value}, + { NFAPI_LAA_CAPABILITY_MULTI_CARRIER_LBT_SUPPORT_TAG, &pNfapiMsg->laa_capability.multi_carrier_lbt_support, &unpack_uint16_tlv_value}, + { NFAPI_LAA_CAPABILITY_PARTIAL_SF_SUPPORT_TAG, &pNfapiMsg->laa_capability.partial_sf_support, &unpack_uint16_tlv_value}, + + { NFAPI_SUBFRAME_CONFIG_DUPLEX_MODE_TAG, &pNfapiMsg->subframe_config.duplex_mode, &unpack_uint16_tlv_value}, + { NFAPI_SUBFRAME_CONFIG_PCFICH_POWER_OFFSET_TAG, &pNfapiMsg->subframe_config.pcfich_power_offset, &unpack_uint16_tlv_value}, + { NFAPI_SUBFRAME_CONFIG_PB_TAG, &pNfapiMsg->subframe_config.pb, &unpack_uint16_tlv_value}, + { NFAPI_SUBFRAME_CONFIG_DL_CYCLIC_PREFIX_TYPE_TAG, &pNfapiMsg->subframe_config.dl_cyclic_prefix_type, &unpack_uint16_tlv_value}, + { NFAPI_SUBFRAME_CONFIG_UL_CYCLIC_PREFIX_TYPE_TAG, &pNfapiMsg->subframe_config.ul_cyclic_prefix_type, &unpack_uint16_tlv_value}, + + { NFAPI_RF_CONFIG_DL_CHANNEL_BANDWIDTH_TAG, &pNfapiMsg->rf_config.dl_channel_bandwidth, &unpack_uint16_tlv_value}, + { NFAPI_RF_CONFIG_UL_CHANNEL_BANDWIDTH_TAG, &pNfapiMsg->rf_config.ul_channel_bandwidth, &unpack_uint16_tlv_value}, + { NFAPI_RF_CONFIG_REFERENCE_SIGNAL_POWER_TAG, &pNfapiMsg->rf_config.reference_signal_power, &unpack_uint16_tlv_value}, + { NFAPI_RF_CONFIG_TX_ANTENNA_PORTS_TAG, &pNfapiMsg->rf_config.tx_antenna_ports, &unpack_uint16_tlv_value}, + { NFAPI_RF_CONFIG_RX_ANTENNA_PORTS_TAG, &pNfapiMsg->rf_config.rx_antenna_ports, &unpack_uint16_tlv_value}, + + { NFAPI_PHICH_CONFIG_PHICH_RESOURCE_TAG, &pNfapiMsg->phich_config.phich_resource, &unpack_uint16_tlv_value}, + { NFAPI_PHICH_CONFIG_PHICH_DURATION_TAG, &pNfapiMsg->phich_config.phich_duration, &unpack_uint16_tlv_value}, + { NFAPI_PHICH_CONFIG_PHICH_POWER_OFFSET_TAG, &pNfapiMsg->phich_config.phich_power_offset, &unpack_uint16_tlv_value}, + + { NFAPI_SCH_CONFIG_PRIMARY_SYNCHRONIZATION_SIGNAL_EPRE_EPRERS_TAG, &pNfapiMsg->sch_config.primary_synchronization_signal_epre_eprers, &unpack_uint16_tlv_value}, + { NFAPI_SCH_CONFIG_SECONDARY_SYNCHRONIZATION_SIGNAL_EPRE_EPRERS_TAG, &pNfapiMsg->sch_config.secondary_synchronization_signal_epre_eprers, &unpack_uint16_tlv_value}, + { NFAPI_SCH_CONFIG_PHYSICAL_CELL_ID_TAG, &pNfapiMsg->sch_config.physical_cell_id, &unpack_uint16_tlv_value}, + + { NFAPI_PRACH_CONFIG_CONFIGURATION_INDEX_TAG, &pNfapiMsg->prach_config.configuration_index, &unpack_uint16_tlv_value}, + { NFAPI_PRACH_CONFIG_ROOT_SEQUENCE_INDEX_TAG, &pNfapiMsg->prach_config.root_sequence_index, &unpack_uint16_tlv_value}, + { NFAPI_PRACH_CONFIG_ZERO_CORRELATION_ZONE_CONFIGURATION_TAG, &pNfapiMsg->prach_config.zero_correlation_zone_configuration, &unpack_uint16_tlv_value}, + { NFAPI_PRACH_CONFIG_HIGH_SPEED_FLAG_TAG, &pNfapiMsg->prach_config.high_speed_flag, &unpack_uint16_tlv_value}, + { NFAPI_PRACH_CONFIG_FREQUENCY_OFFSET_TAG, &pNfapiMsg->prach_config.frequency_offset, &unpack_uint16_tlv_value}, + + { NFAPI_PUSCH_CONFIG_HOPPING_MODE_TAG, &pNfapiMsg->pusch_config.hopping_mode, &unpack_uint16_tlv_value}, + { NFAPI_PUSCH_CONFIG_HOPPING_OFFSET_TAG, &pNfapiMsg->pusch_config.hopping_offset, &unpack_uint16_tlv_value}, + { NFAPI_PUSCH_CONFIG_NUMBER_OF_SUBBANDS_TAG, &pNfapiMsg->pusch_config.number_of_subbands, &unpack_uint16_tlv_value}, + + { NFAPI_PUCCH_CONFIG_DELTA_PUCCH_SHIFT_TAG, &pNfapiMsg->pucch_config.delta_pucch_shift, &unpack_uint16_tlv_value}, + { NFAPI_PUCCH_CONFIG_N_CQI_RB_TAG, &pNfapiMsg->pucch_config.n_cqi_rb, &unpack_uint16_tlv_value}, + { NFAPI_PUCCH_CONFIG_N_AN_CS_TAG, &pNfapiMsg->pucch_config.n_an_cs, &unpack_uint16_tlv_value}, + { NFAPI_PUCCH_CONFIG_N1_PUCCH_AN_TAG, &pNfapiMsg->pucch_config.n1_pucch_an, &unpack_uint16_tlv_value}, + + { NFAPI_SRS_CONFIG_BANDWIDTH_CONFIGURATION_TAG, &pNfapiMsg->srs_config.bandwidth_configuration, &unpack_uint16_tlv_value}, + { NFAPI_SRS_CONFIG_MAX_UP_PTS_TAG, &pNfapiMsg->srs_config.max_up_pts, &unpack_uint16_tlv_value}, + { NFAPI_SRS_CONFIG_SRS_SUBFRAME_CONFIGURATION_TAG, &pNfapiMsg->srs_config.srs_subframe_configuration, &unpack_uint16_tlv_value}, + { NFAPI_SRS_CONFIG_SRS_ACKNACK_SRS_SIMULTANEOUS_TRANSMISSION_TAG, &pNfapiMsg->srs_config.srs_acknack_srs_simultaneous_transmission, &unpack_uint16_tlv_value}, + + { NFAPI_UPLINK_REFERENCE_SIGNAL_CONFIG_UPLINK_RS_HOPPING_TAG, &pNfapiMsg->uplink_reference_signal_config.uplink_rs_hopping, &unpack_uint16_tlv_value}, + { NFAPI_UPLINK_REFERENCE_SIGNAL_CONFIG_GROUP_ASSIGNMENT_TAG, &pNfapiMsg->uplink_reference_signal_config.group_assignment, &unpack_uint16_tlv_value}, + { NFAPI_UPLINK_REFERENCE_SIGNAL_CONFIG_CYCLIC_SHIFT_1_FOR_DRMS_TAG, &pNfapiMsg->uplink_reference_signal_config.cyclic_shift_1_for_drms, &unpack_uint16_tlv_value}, + + { NFAPI_TDD_FRAME_STRUCTURE_SUBFRAME_ASSIGNMENT_TAG, &pNfapiMsg->tdd_frame_structure_config.subframe_assignment, &unpack_uint16_tlv_value}, + { NFAPI_TDD_FRAME_STRUCTURE_SPECIAL_SUBFRAME_PATTERNS_TAG, &pNfapiMsg->tdd_frame_structure_config.special_subframe_patterns, &unpack_uint16_tlv_value}, + + { NFAPI_L23_CONFIG_DATA_REPORT_MODE_TAG, &pNfapiMsg->l23_config.data_report_mode, &unpack_uint16_tlv_value}, + { NFAPI_L23_CONFIG_SFNSF_TAG, &pNfapiMsg->l23_config.sfnsf, &unpack_uint16_tlv_value}, + + { NFAPI_NFAPI_P7_VNF_ADDRESS_IPV4_TAG, &pNfapiMsg->nfapi_config.p7_vnf_address_ipv4, &unpack_ipv4_address_value}, + { NFAPI_NFAPI_P7_VNF_ADDRESS_IPV6_TAG, &pNfapiMsg->nfapi_config.p7_vnf_address_ipv6, &unpack_ipv6_address_value}, + { NFAPI_NFAPI_P7_VNF_PORT_TAG, &pNfapiMsg->nfapi_config.p7_vnf_port, &unpack_uint16_tlv_value}, + { NFAPI_NFAPI_P7_PNF_ADDRESS_IPV4_TAG, &pNfapiMsg->nfapi_config.p7_pnf_address_ipv4, &unpack_ipv4_address_value}, + { NFAPI_NFAPI_P7_PNF_ADDRESS_IPV6_TAG, &pNfapiMsg->nfapi_config.p7_pnf_address_ipv6, &unpack_ipv6_address_value}, + { NFAPI_NFAPI_P7_PNF_PORT_TAG, &pNfapiMsg->nfapi_config.p7_pnf_port, &unpack_uint16_tlv_value}, + { NFAPI_NFAPI_DOWNLINK_UES_PER_SUBFRAME_TAG, &pNfapiMsg->nfapi_config.dl_ue_per_sf, &unpack_uint8_tlv_value}, + { NFAPI_NFAPI_UPLINK_UES_PER_SUBFRAME_TAG, &pNfapiMsg->nfapi_config.ul_ue_per_sf, &unpack_uint8_tlv_value}, + { NFAPI_NFAPI_RF_BANDS_TAG, &pNfapiMsg->nfapi_config.rf_bands, &unpack_rf_bands_value}, + { NFAPI_NFAPI_TIMING_WINDOW_TAG, &pNfapiMsg->nfapi_config.timing_window, &unpack_uint8_tlv_value}, + { NFAPI_NFAPI_TIMING_INFO_MODE_TAG, &pNfapiMsg->nfapi_config.timing_info_mode, &unpack_uint8_tlv_value}, + { NFAPI_NFAPI_TIMING_INFO_PERIOD_TAG, &pNfapiMsg->nfapi_config.timing_info_period, &unpack_uint8_tlv_value}, + { NFAPI_NFAPI_MAXIMUM_TRANSMIT_POWER_TAG, &pNfapiMsg->nfapi_config.max_transmit_power, &unpack_uint16_tlv_value}, + { NFAPI_NFAPI_EARFCN_TAG, &pNfapiMsg->nfapi_config.earfcn, &unpack_uint16_tlv_value}, + { NFAPI_NFAPI_NMM_GSM_FREQUENCY_BANDS_TAG, &pNfapiMsg->nfapi_config.nmm_gsm_frequency_bands, &unpack_nmm_frequency_bands_value}, + { NFAPI_NFAPI_NMM_UMTS_FREQUENCY_BANDS_TAG, &pNfapiMsg->nfapi_config.nmm_umts_frequency_bands, &unpack_nmm_frequency_bands_value}, + { NFAPI_NFAPI_NMM_LTE_FREQUENCY_BANDS_TAG, &pNfapiMsg->nfapi_config.nmm_lte_frequency_bands, &unpack_nmm_frequency_bands_value}, + { NFAPI_NFAPI_NMM_UPLINK_RSSI_SUPPORTED_TAG, &pNfapiMsg->nfapi_config.nmm_uplink_rssi_supported, &unpack_uint8_tlv_value}, + + }; + return ( pull8(ppReadPackedMsg, &pNfapiMsg->error_code, end) && + pull8(ppReadPackedMsg, &pNfapiMsg->num_tlv, end) && + unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); +} + +static uint8_t unpack_nr_param_response(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t *config) { + nfapi_nr_param_response_scf_t *pNfapiMsg = (nfapi_nr_param_response_scf_t *)msg; + unpack_tlv_t unpack_fns[] = { + { NFAPI_NR_PARAM_TLV_RELEASE_CAPABILITY_TAG, &(pNfapiMsg->cell_param.release_capability), &unpack_uint16_tlv_value}, + { NFAPI_NR_PARAM_TLV_PHY_STATE_TAG, &(pNfapiMsg->cell_param.phy_state),&unpack_uint16_tlv_value}, + { NFAPI_NR_PARAM_TLV_SKIP_BLANK_DL_CONFIG_TAG, &(pNfapiMsg->cell_param.skip_blank_dl_config), &unpack_uint8_tlv_value}, + { NFAPI_NR_PARAM_TLV_SKIP_BLANK_UL_CONFIG_TAG, &(pNfapiMsg->cell_param.skip_blank_ul_config), &unpack_uint8_tlv_value}, + { NFAPI_NR_PARAM_TLV_NUM_CONFIG_TLVS_TO_REPORT_TAG, &(pNfapiMsg->cell_param.num_config_tlvs_to_report ), &unpack_uint16_tlv_value}, + + { NFAPI_NR_PARAM_TLV_CYCLIC_PREFIX_TAG, &(pNfapiMsg->carrier_param.cyclic_prefix), &unpack_uint8_tlv_value}, + { NFAPI_NR_PARAM_TLV_SUPPORTED_SUBCARRIER_SPACINGS_DL_TAG, &(pNfapiMsg->carrier_param.supported_subcarrier_spacings_dl), &unpack_uint16_tlv_value}, + { NFAPI_NR_PARAM_TLV_SUPPORTED_BANDWIDTH_DL_TAG, &(pNfapiMsg->carrier_param.supported_bandwidth_dl), &unpack_uint16_tlv_value}, + { NFAPI_NR_PARAM_TLV_SUPPORTED_SUBCARRIER_SPACINGS_UL_TAG, &(pNfapiMsg->carrier_param.supported_subcarrier_spacings_ul), &unpack_uint8_tlv_value}, + { NFAPI_NR_PARAM_TLV_SUPPORTED_BANDWIDTH_UL_TAG, &(pNfapiMsg->carrier_param.supported_bandwidth_ul), &unpack_uint16_tlv_value}, + + + { NFAPI_NR_PARAM_TLV_CCE_MAPPING_TYPE_TAG, &(pNfapiMsg->pdcch_param.cce_mapping_type), &unpack_uint8_tlv_value}, + { NFAPI_NR_PARAM_TLV_CORESET_OUTSIDE_FIRST_3_OFDM_SYMS_OF_SLOT_TAG, &(pNfapiMsg->pdcch_param.coreset_outside_first_3_of_ofdm_syms_of_slot), &unpack_uint8_tlv_value}, + { NFAPI_NR_PARAM_TLV_PRECODER_GRANULARITY_CORESET_TAG, &(pNfapiMsg->pdcch_param.coreset_precoder_granularity_coreset), &unpack_uint8_tlv_value}, + { NFAPI_NR_PARAM_TLV_PDCCH_MU_MIMO_TAG, &(pNfapiMsg->pdcch_param.pdcch_mu_mimo), &unpack_uint8_tlv_value}, + { NFAPI_NR_PARAM_TLV_PDCCH_PRECODER_CYCLING_TAG, &(pNfapiMsg->pdcch_param.pdcch_precoder_cycling), &unpack_uint8_tlv_value}, + { NFAPI_NR_PARAM_TLV_MAX_PDCCHS_PER_SLOT_TAG, &(pNfapiMsg->pdcch_param.max_pdcch_per_slot), &unpack_uint8_tlv_value}, + + { NFAPI_NR_PARAM_TLV_PUCCH_FORMATS_TAG, &(pNfapiMsg->pucch_param.pucch_formats), &unpack_uint8_tlv_value}, + { NFAPI_NR_PARAM_TLV_MAX_PUCCHS_PER_SLOT_TAG, &(pNfapiMsg->pucch_param.max_pucchs_per_slot), &unpack_uint8_tlv_value}, + + { NFAPI_NR_PARAM_TLV_PDSCH_MAPPING_TYPE_TAG, &(pNfapiMsg->pdsch_param.pdsch_mapping_type), &unpack_uint8_tlv_value}, + { NFAPI_NR_PARAM_TLV_PDSCH_ALLOCATION_TYPES_TAG, &(pNfapiMsg->pdsch_param.pdsch_allocation_types), &unpack_uint8_tlv_value}, + { NFAPI_NR_PARAM_TLV_PDSCH_VRB_TO_PRB_MAPPING_TAG, &(pNfapiMsg->pdsch_param.pdsch_vrb_to_prb_mapping), &unpack_uint8_tlv_value}, + { NFAPI_NR_PARAM_TLV_PDSCH_CBG_TAG, &(pNfapiMsg->pdsch_param.pdsch_cbg), &unpack_uint8_tlv_value}, + { NFAPI_NR_PARAM_TLV_PDSCH_DMRS_CONFIG_TYPES_TAG, &(pNfapiMsg->pdsch_param.pdsch_dmrs_config_types), &unpack_uint8_tlv_value}, + { NFAPI_NR_PARAM_TLV_PDSCH_DMRS_MAX_LENGTH_TAG, &(pNfapiMsg->pdsch_param.pdsch_dmrs_max_length), &unpack_uint8_tlv_value}, + { NFAPI_NR_PARAM_TLV_PDSCH_DMRS_ADDITIONAL_POS_TAG, &(pNfapiMsg->pdsch_param.pdsch_dmrs_additional_pos), &unpack_uint8_tlv_value}, + { NFAPI_NR_PARAM_TLV_MAX_PDSCH_S_YBS_PER_SLOT_TAG, &(pNfapiMsg->pdsch_param.max_pdsch_tbs_per_slot), &unpack_uint8_tlv_value}, + { NFAPI_NR_PARAM_TLV_MAX_NUMBER_MIMO_LAYERS_PDSCH_TAG, &(pNfapiMsg->pdsch_param.max_number_mimo_layers_pdsch), &unpack_uint8_tlv_value}, + { NFAPI_NR_PARAM_TLV_MAX_MU_MIMO_USERS_DL_TAG, &(pNfapiMsg->pdsch_param.max_mu_mimo_users_dl), &unpack_uint8_tlv_value}, + { NFAPI_NR_PARAM_TLV_PDSCH_DATA_IN_DMRS_SYMBOLS_TAG, &(pNfapiMsg->pdsch_param.pdsch_data_in_dmrs_symbols), &unpack_uint8_tlv_value}, + { NFAPI_NR_PARAM_TLV_PREMPTION_SUPPORT_TAG, &(pNfapiMsg->pdsch_param.premption_support), &unpack_uint8_tlv_value}, + { NFAPI_NR_PARAM_TLV_PDSCH_NON_SLOT_SUPPORT_TAG, &(pNfapiMsg->pdsch_param.pdsch_non_slot_support), &unpack_uint8_tlv_value}, + + { NFAPI_NR_PARAM_TLV_UCI_MUX_ULSCH_IN_PUSCH_TAG, &(pNfapiMsg->pusch_param.uci_mux_ulsch_in_pusch), &unpack_uint8_tlv_value}, + { NFAPI_NR_PARAM_TLV_UCI_ONLY_PUSCH_TAG, &(pNfapiMsg->pusch_param.uci_only_pusch), &unpack_uint8_tlv_value}, + { NFAPI_NR_PARAM_TLV_PUSCH_FREQUENCY_HOPPING_TAG, &(pNfapiMsg->pusch_param.pusch_frequency_hopping), &unpack_uint8_tlv_value}, + { NFAPI_NR_PARAM_TLV_PUSCH_DMRS_CONFIG_TYPES_TAG, &(pNfapiMsg->pusch_param.pusch_dmrs_config_types), &unpack_uint8_tlv_value}, + { NFAPI_NR_PARAM_TLV_PUSCH_DMRS_MAX_LEN_TAG, &(pNfapiMsg->pusch_param.pusch_dmrs_max_len), &unpack_uint8_tlv_value}, + { NFAPI_NR_PARAM_TLV_PUSCH_DMRS_ADDITIONAL_POS_TAG, &(pNfapiMsg->pusch_param.pusch_dmrs_additional_pos), &unpack_uint8_tlv_value}, + { NFAPI_NR_PARAM_TLV_PUSCH_CBG_TAG, &(pNfapiMsg->pusch_param.pusch_cbg), &unpack_uint8_tlv_value}, + { NFAPI_NR_PARAM_TLV_PUSCH_MAPPING_TYPE_TAG, &(pNfapiMsg->pusch_param.pusch_mapping_type), &unpack_uint8_tlv_value}, + { NFAPI_NR_PARAM_TLV_PUSCH_ALLOCATION_TYPES_TAG, &(pNfapiMsg->pusch_param.pusch_allocation_types), &unpack_uint8_tlv_value}, + { NFAPI_NR_PARAM_TLV_PUSCH_VRB_TO_PRB_MAPPING_TAG, &(pNfapiMsg->pusch_param.pusch_vrb_to_prb_mapping), &unpack_uint8_tlv_value}, + { NFAPI_NR_PARAM_TLV_PUSCH_MAX_PTRS_PORTS_TAG, &(pNfapiMsg->pusch_param.pusch_max_ptrs_ports), &unpack_uint8_tlv_value}, + { NFAPI_NR_PARAM_TLV_MAX_PDUSCHS_TBS_PER_SLOT_TAG, &(pNfapiMsg->pusch_param.max_pduschs_tbs_per_slot), &unpack_uint8_tlv_value}, + { NFAPI_NR_PARAM_TLV_MAX_NUMBER_MIMO_LAYERS_NON_CB_PUSCH_TAG, &(pNfapiMsg->pusch_param.max_number_mimo_layers_non_cb_pusch), &unpack_uint8_tlv_value}, + { NFAPI_NR_PARAM_TLV_SUPPORTED_MODULATION_ORDER_UL_TAG, &(pNfapiMsg->pusch_param.supported_modulation_order_ul), &unpack_uint8_tlv_value}, + { NFAPI_NR_PARAM_TLV_MAX_MU_MIMO_USERS_UL_TAG, &(pNfapiMsg->pusch_param.max_mu_mimo_users_ul), &unpack_uint8_tlv_value}, + { NFAPI_NR_PARAM_TLV_DFTS_OFDM_SUPPORT_TAG, &(pNfapiMsg->pusch_param.dfts_ofdm_support), &unpack_uint8_tlv_value}, + { NFAPI_NR_PARAM_TLV_PUSCH_AGGREGATION_FACTOR_TAG, &(pNfapiMsg->pusch_param.pusch_aggregation_factor), &unpack_uint8_tlv_value}, + + { NFAPI_NR_PARAM_TLV_PRACH_LONG_FORMATS_TAG, &(pNfapiMsg->prach_param.prach_long_formats), &unpack_uint8_tlv_value}, + { NFAPI_NR_PARAM_TLV_PRACH_SHORT_FORMATS_TAG, &(pNfapiMsg->prach_param.prach_short_formats), &unpack_uint8_tlv_value}, + { NFAPI_NR_PARAM_TLV_PRACH_RESTRICTED_SETS_TAG, &(pNfapiMsg->prach_param.prach_restricted_sets), &unpack_uint8_tlv_value}, + { NFAPI_NR_PARAM_TLV_MAX_PRACH_FD_OCCASIONS_IN_A_SLOT_TAG, &(pNfapiMsg->prach_param.max_prach_fd_occasions_in_a_slot), &unpack_uint8_tlv_value}, + + { NFAPI_NR_PARAM_TLV_RSSI_MEASUREMENT_SUPPORT_TAG, &(pNfapiMsg->measurement_param.rssi_measurement_support), &unpack_uint8_tlv_value}, + //config + { 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}, + { NFAPI_NR_NFAPI_P7_PNF_ADDRESS_IPV4_TAG, &pNfapiMsg->nfapi_config.p7_pnf_address_ipv4, &unpack_ipv4_address_value}, + { 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}, + { NFAPI_NR_NFAPI_TIMING_WINDOW_TAG, &pNfapiMsg->nfapi_config.timing_window, &unpack_uint8_tlv_value}, + { NFAPI_NR_NFAPI_TIMING_INFO_MODE_TAG, &pNfapiMsg->nfapi_config.timing_info_mode, &unpack_uint8_tlv_value}, + { NFAPI_NR_NFAPI_TIMING_INFO_PERIOD_TAG, &pNfapiMsg->nfapi_config.timing_info_period, &unpack_uint8_tlv_value}, + }; + // print ppReadPackedMsg + uint8_t *ptr = *ppReadPackedMsg; + printf("\n Read message unpack_param_response: "); + + while(ptr < end) { + printf(" %d ", *ptr); + ptr++; + } + + printf("\n"); + return ( pull8(ppReadPackedMsg, &pNfapiMsg->error_code, end) && + pull8(ppReadPackedMsg, &pNfapiMsg->num_tlv, end) && + unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); +} + +static uint8_t unpack_config_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t *config) { + nfapi_config_request_t *pNfapiMsg = (nfapi_config_request_t *)msg; + unpack_tlv_t unpack_fns[] = { + { NFAPI_SUBFRAME_CONFIG_DUPLEX_MODE_TAG, &pNfapiMsg->subframe_config.duplex_mode, &unpack_uint16_tlv_value}, + { NFAPI_SUBFRAME_CONFIG_PCFICH_POWER_OFFSET_TAG, &pNfapiMsg->subframe_config.pcfich_power_offset, &unpack_uint16_tlv_value}, + { NFAPI_SUBFRAME_CONFIG_PB_TAG, &pNfapiMsg->subframe_config.pb, &unpack_uint16_tlv_value}, + { NFAPI_SUBFRAME_CONFIG_DL_CYCLIC_PREFIX_TYPE_TAG, &pNfapiMsg->subframe_config.dl_cyclic_prefix_type, &unpack_uint16_tlv_value}, + { NFAPI_SUBFRAME_CONFIG_UL_CYCLIC_PREFIX_TYPE_TAG, &pNfapiMsg->subframe_config.ul_cyclic_prefix_type, &unpack_uint16_tlv_value}, + + { NFAPI_RF_CONFIG_DL_CHANNEL_BANDWIDTH_TAG, &pNfapiMsg->rf_config.dl_channel_bandwidth, &unpack_uint16_tlv_value}, + { NFAPI_RF_CONFIG_UL_CHANNEL_BANDWIDTH_TAG, &pNfapiMsg->rf_config.ul_channel_bandwidth, &unpack_uint16_tlv_value}, + { NFAPI_RF_CONFIG_REFERENCE_SIGNAL_POWER_TAG, &pNfapiMsg->rf_config.reference_signal_power, &unpack_uint16_tlv_value}, + { NFAPI_RF_CONFIG_TX_ANTENNA_PORTS_TAG, &pNfapiMsg->rf_config.tx_antenna_ports, &unpack_uint16_tlv_value}, + { NFAPI_RF_CONFIG_RX_ANTENNA_PORTS_TAG, &pNfapiMsg->rf_config.rx_antenna_ports, &unpack_uint16_tlv_value}, + + { NFAPI_PHICH_CONFIG_PHICH_RESOURCE_TAG, &pNfapiMsg->phich_config.phich_resource, &unpack_uint16_tlv_value}, + { NFAPI_PHICH_CONFIG_PHICH_DURATION_TAG, &pNfapiMsg->phich_config.phich_duration, &unpack_uint16_tlv_value}, + { NFAPI_PHICH_CONFIG_PHICH_POWER_OFFSET_TAG, &pNfapiMsg->phich_config.phich_power_offset, &unpack_uint16_tlv_value}, + + { NFAPI_SCH_CONFIG_PRIMARY_SYNCHRONIZATION_SIGNAL_EPRE_EPRERS_TAG, &pNfapiMsg->sch_config.primary_synchronization_signal_epre_eprers, &unpack_uint16_tlv_value}, + { NFAPI_SCH_CONFIG_SECONDARY_SYNCHRONIZATION_SIGNAL_EPRE_EPRERS_TAG, &pNfapiMsg->sch_config.secondary_synchronization_signal_epre_eprers, &unpack_uint16_tlv_value}, + { NFAPI_SCH_CONFIG_PHYSICAL_CELL_ID_TAG, &pNfapiMsg->sch_config.physical_cell_id, &unpack_uint16_tlv_value}, + + { NFAPI_PRACH_CONFIG_CONFIGURATION_INDEX_TAG, &pNfapiMsg->prach_config.configuration_index, &unpack_uint16_tlv_value}, + { NFAPI_PRACH_CONFIG_ROOT_SEQUENCE_INDEX_TAG, &pNfapiMsg->prach_config.root_sequence_index, &unpack_uint16_tlv_value}, + { NFAPI_PRACH_CONFIG_ZERO_CORRELATION_ZONE_CONFIGURATION_TAG, &pNfapiMsg->prach_config.zero_correlation_zone_configuration, &unpack_uint16_tlv_value}, + { NFAPI_PRACH_CONFIG_HIGH_SPEED_FLAG_TAG, &pNfapiMsg->prach_config.high_speed_flag, &unpack_uint16_tlv_value}, + { NFAPI_PRACH_CONFIG_FREQUENCY_OFFSET_TAG, &pNfapiMsg->prach_config.frequency_offset, &unpack_uint16_tlv_value}, + + { NFAPI_PUSCH_CONFIG_HOPPING_MODE_TAG, &pNfapiMsg->pusch_config.hopping_mode, &unpack_uint16_tlv_value}, + { NFAPI_PUSCH_CONFIG_HOPPING_OFFSET_TAG, &pNfapiMsg->pusch_config.hopping_offset, &unpack_uint16_tlv_value}, + { NFAPI_PUSCH_CONFIG_NUMBER_OF_SUBBANDS_TAG, &pNfapiMsg->pusch_config.number_of_subbands, &unpack_uint16_tlv_value}, + + { NFAPI_PUCCH_CONFIG_DELTA_PUCCH_SHIFT_TAG, &pNfapiMsg->pucch_config.delta_pucch_shift, &unpack_uint16_tlv_value}, + { NFAPI_PUCCH_CONFIG_N_CQI_RB_TAG, &pNfapiMsg->pucch_config.n_cqi_rb, &unpack_uint16_tlv_value}, + { NFAPI_PUCCH_CONFIG_N_AN_CS_TAG, &pNfapiMsg->pucch_config.n_an_cs, &unpack_uint16_tlv_value}, + { NFAPI_PUCCH_CONFIG_N1_PUCCH_AN_TAG, &pNfapiMsg->pucch_config.n1_pucch_an, &unpack_uint16_tlv_value}, + + { NFAPI_SRS_CONFIG_BANDWIDTH_CONFIGURATION_TAG, &pNfapiMsg->srs_config.bandwidth_configuration, &unpack_uint16_tlv_value}, + { NFAPI_SRS_CONFIG_MAX_UP_PTS_TAG, &pNfapiMsg->srs_config.max_up_pts, &unpack_uint16_tlv_value}, + { NFAPI_SRS_CONFIG_SRS_SUBFRAME_CONFIGURATION_TAG, &pNfapiMsg->srs_config.srs_subframe_configuration, &unpack_uint16_tlv_value}, + { NFAPI_SRS_CONFIG_SRS_ACKNACK_SRS_SIMULTANEOUS_TRANSMISSION_TAG, &pNfapiMsg->srs_config.srs_acknack_srs_simultaneous_transmission, &unpack_uint16_tlv_value}, + + { NFAPI_UPLINK_REFERENCE_SIGNAL_CONFIG_UPLINK_RS_HOPPING_TAG, &pNfapiMsg->uplink_reference_signal_config.uplink_rs_hopping, &unpack_uint16_tlv_value}, + { NFAPI_UPLINK_REFERENCE_SIGNAL_CONFIG_GROUP_ASSIGNMENT_TAG, &pNfapiMsg->uplink_reference_signal_config.group_assignment, &unpack_uint16_tlv_value}, + { NFAPI_UPLINK_REFERENCE_SIGNAL_CONFIG_CYCLIC_SHIFT_1_FOR_DRMS_TAG, &pNfapiMsg->uplink_reference_signal_config.cyclic_shift_1_for_drms, &unpack_uint16_tlv_value}, + + + { NFAPI_LAA_CONFIG_ED_THRESHOLD_FOR_LBT_FOR_PDSCH_TAG, &pNfapiMsg->laa_config.ed_threshold_lbt_pdsch, &unpack_uint16_tlv_value}, + { NFAPI_LAA_CONFIG_ED_THRESHOLD_FOR_LBT_FOR_DRS_TAG, &pNfapiMsg->laa_config.ed_threshold_lbt_drs, &unpack_uint16_tlv_value}, + { NFAPI_LAA_CONFIG_PD_THRESHOLD_TAG, &pNfapiMsg->laa_config.pd_threshold, &unpack_uint16_tlv_value}, + { NFAPI_LAA_CONFIG_MULTI_CARRIER_TYPE_TAG, &pNfapiMsg->laa_config.multi_carrier_type, &unpack_uint16_tlv_value}, + { NFAPI_LAA_CONFIG_MULTI_CARRIER_TX_TAG, &pNfapiMsg->laa_config.multi_carrier_tx, &unpack_uint16_tlv_value}, + { NFAPI_LAA_CONFIG_MULTI_CARRIER_FREEZE_TAG, &pNfapiMsg->laa_config.multi_carrier_freeze, &unpack_uint16_tlv_value}, + { NFAPI_LAA_CONFIG_TX_ANTENNA_PORTS_FOR_DRS_TAG, &pNfapiMsg->laa_config.tx_antenna_ports_drs, &unpack_uint16_tlv_value}, + { NFAPI_LAA_CONFIG_TRANSMISSION_POWER_FOR_DRS_TAG, &pNfapiMsg->laa_config.tx_power_drs, &unpack_uint16_tlv_value}, + + { NFAPI_EMTC_CONFIG_PBCH_REPETITIONS_ENABLE_R13_TAG, &pNfapiMsg->emtc_config.pbch_repetitions_enable_r13, &unpack_uint16_tlv_value}, + { NFAPI_EMTC_CONFIG_PRACH_CATM_ROOT_SEQUENCE_INDEX_TAG, &pNfapiMsg->emtc_config.prach_catm_root_sequence_index, &unpack_uint16_tlv_value}, + { NFAPI_EMTC_CONFIG_PRACH_CATM_ZERO_CORRELATION_ZONE_CONFIGURATION_TAG, &pNfapiMsg->emtc_config.prach_catm_zero_correlation_zone_configuration, &unpack_uint16_tlv_value}, + { NFAPI_EMTC_CONFIG_PRACH_CATM_HIGH_SPEED_FLAG, &pNfapiMsg->emtc_config.prach_catm_high_speed_flag, &unpack_uint16_tlv_value}, + { NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_0_ENABLE_TAG, &pNfapiMsg->emtc_config.prach_ce_level_0_enable, &unpack_uint16_tlv_value}, + { NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_0_CONFIGURATION_INDEX_TAG, &pNfapiMsg->emtc_config.prach_ce_level_0_configuration_index, &unpack_uint16_tlv_value}, + { NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_0_FREQUENCY_OFFSET_TAG, &pNfapiMsg->emtc_config.prach_ce_level_0_frequency_offset, &unpack_uint16_tlv_value}, + { NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_0_NUMBER_OF_REPETITIONS_PER_ATTEMPT_TAG, &pNfapiMsg->emtc_config.prach_ce_level_0_number_of_repetitions_per_attempt, &unpack_uint16_tlv_value}, + { NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_0_STARTING_SUBFRAME_PERIODICITY_TAG, &pNfapiMsg->emtc_config.prach_ce_level_0_starting_subframe_periodicity, &unpack_uint16_tlv_value}, + { NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_0_HOPPING_ENABLE_TAG, &pNfapiMsg->emtc_config.prach_ce_level_0_hopping_enable, &unpack_uint16_tlv_value}, + { NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_0_HOPPING_OFFSET_TAG, &pNfapiMsg->emtc_config.prach_ce_level_0_hopping_offset, &unpack_uint16_tlv_value}, + { NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_1_ENABLE_TAG, &pNfapiMsg->emtc_config.prach_ce_level_1_enable, &unpack_uint16_tlv_value}, + { NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_1_CONFIGURATION_INDEX_TAG, &pNfapiMsg->emtc_config.prach_ce_level_1_configuration_index, &unpack_uint16_tlv_value}, + { NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_1_FREQUENCY_OFFSET_TAG, &pNfapiMsg->emtc_config.prach_ce_level_1_frequency_offset, &unpack_uint16_tlv_value}, + { NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_1_NUMBER_OF_REPETITIONS_PER_ATTEMPT_TAG, &pNfapiMsg->emtc_config.prach_ce_level_1_number_of_repetitions_per_attempt, &unpack_uint16_tlv_value}, + { NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_1_STARTING_SUBFRAME_PERIODICITY_TAG, &pNfapiMsg->emtc_config.prach_ce_level_1_starting_subframe_periodicity, &unpack_uint16_tlv_value}, + { NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_1_HOPPING_ENABLE_TAG, &pNfapiMsg->emtc_config.prach_ce_level_1_hopping_enable, &unpack_uint16_tlv_value}, + { NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_1_HOPPING_OFFSET_TAG, &pNfapiMsg->emtc_config.prach_ce_level_1_hopping_offset, &unpack_uint16_tlv_value}, + { NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_2_ENABLE_TAG, &pNfapiMsg->emtc_config.prach_ce_level_2_enable, &unpack_uint16_tlv_value}, + { NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_2_CONFIGURATION_INDEX_TAG, &pNfapiMsg->emtc_config.prach_ce_level_2_configuration_index, &unpack_uint16_tlv_value}, + { NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_2_FREQUENCY_OFFSET_TAG, &pNfapiMsg->emtc_config.prach_ce_level_2_frequency_offset, &unpack_uint16_tlv_value}, + { NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_2_NUMBER_OF_REPETITIONS_PER_ATTEMPT_TAG, &pNfapiMsg->emtc_config.prach_ce_level_2_number_of_repetitions_per_attempt, &unpack_uint16_tlv_value}, + { NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_2_STARTING_SUBFRAME_PERIODICITY_TAG, &pNfapiMsg->emtc_config.prach_ce_level_2_starting_subframe_periodicity, &unpack_uint16_tlv_value}, + { NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_2_HOPPING_ENABLE_TAG, &pNfapiMsg->emtc_config.prach_ce_level_2_hopping_enable, &unpack_uint16_tlv_value}, + { NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_2_HOPPING_OFFSET_TAG, &pNfapiMsg->emtc_config.prach_ce_level_2_hopping_offset, &unpack_uint16_tlv_value}, + { NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_3_ENABLE_TAG, &pNfapiMsg->emtc_config.prach_ce_level_3_enable, &unpack_uint16_tlv_value}, + { NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_3_CONFIGURATION_INDEX_TAG, &pNfapiMsg->emtc_config.prach_ce_level_3_configuration_index, &unpack_uint16_tlv_value}, + { NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_3_FREQUENCY_OFFSET_TAG, &pNfapiMsg->emtc_config.prach_ce_level_3_frequency_offset, &unpack_uint16_tlv_value}, + { NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_3_NUMBER_OF_REPETITIONS_PER_ATTEMPT_TAG, &pNfapiMsg->emtc_config.prach_ce_level_3_number_of_repetitions_per_attempt, &unpack_uint16_tlv_value}, + { NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_3_STARTING_SUBFRAME_PERIODICITY_TAG, &pNfapiMsg->emtc_config.prach_ce_level_3_starting_subframe_periodicity, &unpack_uint16_tlv_value}, + { NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_3_HOPPING_ENABLE_TAG, &pNfapiMsg->emtc_config.prach_ce_level_3_hopping_enable, &unpack_uint16_tlv_value}, + { NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_3_HOPPING_OFFSET_TAG, &pNfapiMsg->emtc_config.prach_ce_level_3_hopping_offset, &unpack_uint16_tlv_value}, + { NFAPI_EMTC_CONFIG_PUCCH_INTERVAL_ULHOPPINGCONFIGCOMMONMODEA_TAG, &pNfapiMsg->emtc_config.pucch_interval_ulhoppingconfigcommonmodea, &unpack_uint16_tlv_value}, + { NFAPI_EMTC_CONFIG_PUCCH_INTERVAL_ULHOPPINGCONFIGCOMMONMODEB_TAG, &pNfapiMsg->emtc_config.pucch_interval_ulhoppingconfigcommonmodeb, &unpack_uint16_tlv_value}, + + { NFAPI_TDD_FRAME_STRUCTURE_SUBFRAME_ASSIGNMENT_TAG, &pNfapiMsg->tdd_frame_structure_config.subframe_assignment, &unpack_uint16_tlv_value}, + { NFAPI_TDD_FRAME_STRUCTURE_SPECIAL_SUBFRAME_PATTERNS_TAG, &pNfapiMsg->tdd_frame_structure_config.special_subframe_patterns, &unpack_uint16_tlv_value}, + + { NFAPI_L23_CONFIG_DATA_REPORT_MODE_TAG, &pNfapiMsg->l23_config.data_report_mode, &unpack_uint16_tlv_value}, + { NFAPI_L23_CONFIG_SFNSF_TAG, &pNfapiMsg->l23_config.sfnsf, &unpack_uint16_tlv_value}, + + { NFAPI_NFAPI_P7_VNF_ADDRESS_IPV4_TAG, &pNfapiMsg->nfapi_config.p7_vnf_address_ipv4, &unpack_ipv4_address_value}, + { NFAPI_NFAPI_P7_VNF_ADDRESS_IPV6_TAG, &pNfapiMsg->nfapi_config.p7_vnf_address_ipv6, &unpack_ipv6_address_value}, + { NFAPI_NFAPI_P7_VNF_PORT_TAG, &pNfapiMsg->nfapi_config.p7_vnf_port, &unpack_uint16_tlv_value}, + { NFAPI_NFAPI_P7_PNF_ADDRESS_IPV4_TAG, &pNfapiMsg->nfapi_config.p7_pnf_address_ipv4, &unpack_ipv4_address_value}, + { NFAPI_NFAPI_P7_PNF_ADDRESS_IPV6_TAG, &pNfapiMsg->nfapi_config.p7_pnf_address_ipv6, &unpack_ipv6_address_value}, + { NFAPI_NFAPI_P7_PNF_PORT_TAG, &pNfapiMsg->nfapi_config.p7_pnf_port, &unpack_uint16_tlv_value}, + { NFAPI_NFAPI_DOWNLINK_UES_PER_SUBFRAME_TAG, &pNfapiMsg->nfapi_config.dl_ue_per_sf, &unpack_uint8_tlv_value}, + { NFAPI_NFAPI_UPLINK_UES_PER_SUBFRAME_TAG, &pNfapiMsg->nfapi_config.ul_ue_per_sf, &unpack_uint8_tlv_value}, + { NFAPI_NFAPI_RF_BANDS_TAG, &pNfapiMsg->nfapi_config.rf_bands, &unpack_rf_bands_value}, + { NFAPI_NFAPI_TIMING_WINDOW_TAG, &pNfapiMsg->nfapi_config.timing_window, &unpack_uint8_tlv_value}, + { NFAPI_NFAPI_TIMING_INFO_MODE_TAG, &pNfapiMsg->nfapi_config.timing_info_mode, &unpack_uint8_tlv_value}, + { NFAPI_NFAPI_TIMING_INFO_PERIOD_TAG, &pNfapiMsg->nfapi_config.timing_info_period, &unpack_uint8_tlv_value}, + { NFAPI_NFAPI_MAXIMUM_TRANSMIT_POWER_TAG, &pNfapiMsg->nfapi_config.max_transmit_power, &unpack_uint16_tlv_value}, + { NFAPI_NFAPI_EARFCN_TAG, &pNfapiMsg->nfapi_config.earfcn, &unpack_uint16_tlv_value}, + { NFAPI_NFAPI_NMM_GSM_FREQUENCY_BANDS_TAG, &pNfapiMsg->nfapi_config.nmm_gsm_frequency_bands, &unpack_nmm_frequency_bands_value}, + { NFAPI_NFAPI_NMM_UMTS_FREQUENCY_BANDS_TAG, &pNfapiMsg->nfapi_config.nmm_umts_frequency_bands, &unpack_nmm_frequency_bands_value}, + { NFAPI_NFAPI_NMM_LTE_FREQUENCY_BANDS_TAG, &pNfapiMsg->nfapi_config.nmm_lte_frequency_bands, &unpack_nmm_frequency_bands_value}, + { NFAPI_NFAPI_NMM_UPLINK_RSSI_SUPPORTED_TAG, &pNfapiMsg->nfapi_config.nmm_uplink_rssi_supported, &unpack_uint8_tlv_value}, + + }; + return ( pull8(ppReadPackedMsg, &pNfapiMsg->num_tlv, end) && + unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); +} +static uint8_t unpack_nr_config_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t *config) { + nfapi_nr_config_request_scf_t *pNfapiMsg = (nfapi_nr_config_request_scf_t *)msg; + pNfapiMsg->tdd_table.max_tdd_periodicity_list = (nfapi_nr_max_tdd_periodicity_t *) malloc(20*sizeof(nfapi_nr_max_tdd_periodicity_t)); + + for(int i=0; i<40; i++) + pNfapiMsg->tdd_table.max_tdd_periodicity_list[i].max_num_of_symbol_per_slot_list = (nfapi_nr_max_num_of_symbol_per_slot_t *) malloc(14*sizeof(nfapi_nr_max_num_of_symbol_per_slot_t)); + + pNfapiMsg->prach_config.num_prach_fd_occasions_list=(nfapi_nr_num_prach_fd_occasions_t *) malloc(sizeof(nfapi_nr_num_prach_fd_occasions_t)); + unpack_tlv_t unpack_fns[] = { + { NFAPI_NR_CONFIG_DL_BANDWIDTH_TAG, &(pNfapiMsg->carrier_config.dl_bandwidth), &unpack_uint16_tlv_value}, + { NFAPI_NR_CONFIG_DL_FREQUENCY_TAG, &(pNfapiMsg->carrier_config.dl_frequency), &unpack_uint32_tlv_value}, + { NFAPI_NR_CONFIG_DL_GRID_SIZE_TAG, &(pNfapiMsg->carrier_config.dl_grid_size[1]), &unpack_uint16_tlv_value}, + { NFAPI_NR_CONFIG_DL_K0_TAG, &(pNfapiMsg->carrier_config.dl_k0[1]), &unpack_uint16_tlv_value}, + { NFAPI_NR_CONFIG_NUM_RX_ANT_TAG, &(pNfapiMsg->carrier_config.num_rx_ant), &unpack_uint16_tlv_value}, + { NFAPI_NR_CONFIG_NUM_TX_ANT_TAG, &(pNfapiMsg->carrier_config.num_tx_ant), &unpack_uint16_tlv_value}, + { NFAPI_NR_CONFIG_UL_GRID_SIZE_TAG, &(pNfapiMsg->carrier_config.ul_grid_size[1]), &unpack_uint16_tlv_value}, + { NFAPI_NR_CONFIG_UL_K0_TAG, &(pNfapiMsg->carrier_config.ul_k0[1]), &unpack_uint16_tlv_value}, + { NFAPI_NR_CONFIG_UPLINK_BANDWIDTH_TAG, &(pNfapiMsg->carrier_config.uplink_bandwidth), &unpack_uint16_tlv_value}, + { NFAPI_NR_CONFIG_UPLINK_FREQUENCY_TAG, &(pNfapiMsg->carrier_config.uplink_frequency), &unpack_uint32_tlv_value}, + { NFAPI_NR_CONFIG_FRAME_DUPLEX_TYPE_TAG, &(pNfapiMsg->cell_config.frame_duplex_type), &unpack_uint8_tlv_value}, + { NFAPI_NR_CONFIG_PHY_CELL_ID_TAG, &(pNfapiMsg->cell_config.phy_cell_id), &unpack_uint8_tlv_value}, + { NFAPI_NR_CONFIG_NUM_PRACH_FD_OCCASIONS_TAG, &(pNfapiMsg->prach_config.num_prach_fd_occasions), &unpack_uint8_tlv_value}, + { NFAPI_NR_CONFIG_PRACH_SEQUENCE_LENGTH_TAG, &(pNfapiMsg->prach_config.prach_sequence_length), &unpack_uint8_tlv_value}, + { NFAPI_NR_CONFIG_RESTRICTED_SET_CONFIG_TAG, &(pNfapiMsg->prach_config.restricted_set_config), &unpack_uint8_tlv_value}, + { NFAPI_NR_CONFIG_SSB_PER_RACH_TAG, &(pNfapiMsg->prach_config.ssb_per_rach), &unpack_uint8_tlv_value}, + { NFAPI_NR_CONFIG_PRACH_SUB_C_SPACING_TAG, &(pNfapiMsg->prach_config.prach_sub_c_spacing), &unpack_uint8_tlv_value}, + { NFAPI_NR_CONFIG_PRACH_ROOT_SEQUENCE_INDEX_TAG, &(pNfapiMsg->prach_config.num_prach_fd_occasions_list[0].prach_root_sequence_index), &unpack_uint16_tlv_value}, + { NFAPI_NR_CONFIG_K1_TAG, &(pNfapiMsg->prach_config.num_prach_fd_occasions_list[0].k1), &unpack_uint16_tlv_value}, + { NFAPI_NR_CONFIG_PRACH_ZERO_CORR_CONF_TAG, &(pNfapiMsg->prach_config.num_prach_fd_occasions_list[0].prach_zero_corr_conf), &unpack_uint8_tlv_value}, + { NFAPI_NR_CONFIG_NUM_ROOT_SEQUENCES_TAG, &(pNfapiMsg->prach_config.num_prach_fd_occasions_list[0].num_root_sequences), &unpack_uint8_tlv_value}, + + { NFAPI_NR_CONFIG_SCS_COMMON_TAG, &(pNfapiMsg->ssb_config.scs_common), &unpack_uint8_tlv_value}, + { NFAPI_NR_CONFIG_SS_PBCH_POWER_TAG, &(pNfapiMsg->ssb_config.ss_pbch_power), &unpack_uint32_tlv_value}, + { NFAPI_NR_CONFIG_BETA_PSS_TAG, &(pNfapiMsg->ssb_table.beta_pss), &unpack_uint8_tlv_value}, + { NFAPI_NR_CONFIG_MIB_TAG, &(pNfapiMsg->ssb_table.MIB), &unpack_uint32_tlv_value}, + { NFAPI_NR_CONFIG_SSB_MASK_TAG, &(pNfapiMsg->ssb_table.ssb_mask_list[0].ssb_mask), &unpack_uint32_tlv_value}, + { NFAPI_NR_CONFIG_SSB_MASK_TAG, &(pNfapiMsg->ssb_table.ssb_mask_list[1].ssb_mask), &unpack_uint32_tlv_value}, + + { NFAPI_NR_CONFIG_SSB_OFFSET_POINT_A_TAG, &(pNfapiMsg->ssb_table.ssb_offset_point_a), &unpack_uint16_tlv_value}, + { NFAPI_NR_CONFIG_SSB_PERIOD_TAG, &(pNfapiMsg->ssb_table.ssb_period), &unpack_uint8_tlv_value}, + { NFAPI_NR_CONFIG_SSB_SUBCARRIER_OFFSET_TAG, &(pNfapiMsg->ssb_table.ssb_subcarrier_offset), &unpack_uint8_tlv_value}, + { NFAPI_NR_CONFIG_TDD_PERIOD_TAG, &(pNfapiMsg->tdd_table.tdd_period), &unpack_uint8_tlv_value}, + { NFAPI_NR_CONFIG_SLOT_CONFIG_TAG, &(pNfapiMsg->tdd_table.max_tdd_periodicity_list[0].max_num_of_symbol_per_slot_list[0].slot_config), &unpack_uint8_tlv_value}, + { NFAPI_NR_NFAPI_P7_PNF_ADDRESS_IPV4_TAG, &(pNfapiMsg->nfapi_config.p7_pnf_address_ipv4), &unpack_ipv4_address_value}, + { 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}, + { 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}, + { NFAPI_NR_NFAPI_TIMING_INFO_MODE_TAG, &(pNfapiMsg->nfapi_config.timing_info_mode), &unpack_uint8_tlv_value}, + { NFAPI_NR_NFAPI_TIMING_INFO_PERIOD_TAG, &(pNfapiMsg->nfapi_config.timing_info_period), &unpack_uint8_tlv_value}, + { NFAPI_NR_NFAPI_TIMING_WINDOW_TAG, &(pNfapiMsg->nfapi_config.timing_window), &unpack_uint8_tlv_value}, + }; + return ( pull8(ppReadPackedMsg, &pNfapiMsg->num_tlv, end) && + unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); +} + +static uint8_t unpack_config_response(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t *config) { + nfapi_config_response_t *pNfapiMsg = (nfapi_config_response_t *)msg; + return ( pull32(ppReadPackedMsg, &pNfapiMsg->error_code, end) && + unpack_tlv_list(NULL, 0, ppReadPackedMsg, end, config, &(pNfapiMsg->vendor_extension))); +} + +static uint8_t unpack_nr_config_response(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t *config) { + nfapi_nr_config_response_scf_t *pNfapiMsg = (nfapi_nr_config_response_scf_t *)msg; + return ( pull8(ppReadPackedMsg, &pNfapiMsg->error_code, end) && + unpack_tlv_list(NULL, 0, ppReadPackedMsg, end, config, &(pNfapiMsg->vendor_extension))); +} + +static uint8_t unpack_nr_start_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t *config) { + nfapi_nr_start_request_scf_t *pNfapiMsg = ( nfapi_nr_start_request_scf_t *)msg; + return unpack_tlv_list(NULL, 0, ppReadPackedMsg, end, config, &(pNfapiMsg->vendor_extension)); +} + +static uint8_t unpack_start_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t *config) { + nfapi_start_request_t *pNfapiMsg = ( nfapi_start_request_t *)msg; + return unpack_tlv_list(NULL, 0, ppReadPackedMsg, end, config, &(pNfapiMsg->vendor_extension)); +} + +static uint8_t unpack_start_response(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t *config) { + nfapi_start_response_t *pNfapiMsg = (nfapi_start_response_t *)msg; + return ( pull32(ppReadPackedMsg, &pNfapiMsg->error_code, end) && + unpack_tlv_list(NULL, 0, ppReadPackedMsg, end, config, &(pNfapiMsg->vendor_extension))); +} + +static uint8_t unpack_nr_start_response(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t *config) { + nfapi_nr_start_response_scf_t *pNfapiMsg = (nfapi_nr_start_response_scf_t *)msg; + return ( pull32(ppReadPackedMsg, &pNfapiMsg->error_code, end) && + unpack_tlv_list(NULL, 0, ppReadPackedMsg, end, config, &(pNfapiMsg->vendor_extension))); +} + +static uint8_t unpack_stop_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t *config) { + nfapi_stop_request_t *pNfapiMsg = (nfapi_stop_request_t *)msg; + return unpack_tlv_list(NULL, 0, ppReadPackedMsg, end, config, &(pNfapiMsg->vendor_extension)); +} + +static uint8_t unpack_stop_response(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t *config) { + nfapi_stop_response_t *pNfapiMsg = (nfapi_stop_response_t *)msg; + return ( pull32(ppReadPackedMsg, &pNfapiMsg->error_code, end) && + unpack_tlv_list(NULL, 0, ppReadPackedMsg, end, config, &(pNfapiMsg->vendor_extension))); +} +static uint8_t unpack_measurement_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t *config) { + nfapi_measurement_request_t *pNfapiMsg = (nfapi_measurement_request_t *)msg; + unpack_tlv_t unpack_fns[] = { + { NFAPI_MEASUREMENT_REQUEST_DL_RS_XTX_POWER_TAG, &pNfapiMsg->dl_rs_tx_power, &unpack_uint16_tlv_value}, + { NFAPI_MEASUREMENT_REQUEST_RECEIVED_INTERFERENCE_POWER_TAG, &pNfapiMsg->received_interference_power, &unpack_uint16_tlv_value}, + { NFAPI_MEASUREMENT_REQUEST_THERMAL_NOISE_POWER_TAG, &pNfapiMsg->thermal_noise_power, &unpack_uint16_tlv_value}, + }; + return unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &(pNfapiMsg->vendor_extension)); +} + +static uint8_t unpack_received_interference_power_measurement_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_received_interference_power_measurement_t *value = (nfapi_received_interference_power_measurement_t *)tlv; + return ( pull16(ppReadPackedMsg, &value->number_of_resource_blocks, end) && + pullarrays16(ppReadPackedMsg, value->received_interference_power, NFAPI_MAX_RECEIVED_INTERFERENCE_POWER_RESULTS, value->number_of_resource_blocks, end)); +} + + +static uint8_t unpack_measurement_response(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t *config) { + nfapi_measurement_response_t *pNfapiMsg = (nfapi_measurement_response_t *)msg; + unpack_tlv_t unpack_fns[] = { + { NFAPI_MEASUREMENT_RESPONSE_DL_RS_POWER_MEASUREMENT_TAG, &pNfapiMsg->dl_rs_tx_power_measurement, &unpack_int16_tlv_value}, + { NFAPI_MEASUREMENT_RESPONSE_RECEIVED_INTERFERENCE_POWER_MEASUREMENT_TAG, &pNfapiMsg->received_interference_power_measurement, &unpack_received_interference_power_measurement_value}, + { NFAPI_MEASUREMENT_RESPONSE_THERMAL_NOISE_MEASUREMENT_TAG, &pNfapiMsg->thermal_noise_power_measurement, &unpack_int16_tlv_value}, + }; + return ( pull32(ppReadPackedMsg, &pNfapiMsg->error_code, end) && + unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); +} + +// unpack length check + +static int check_nr_unpack_length(nfapi_nr_phy_msg_type_e msgId, uint32_t unpackedBufLen) { + int retLen = 0; + + switch (msgId) { + case NFAPI_NR_PHY_MSG_TYPE_PNF_PARAM_REQUEST: + if (unpackedBufLen >= sizeof(nfapi_pnf_param_request_t)) + retLen = sizeof(nfapi_pnf_param_request_t); + + break; + + case NFAPI_NR_PHY_MSG_TYPE_PNF_PARAM_RESPONSE: + if (unpackedBufLen >= sizeof(nfapi_nr_pnf_param_response_t)) + retLen = sizeof(nfapi_nr_pnf_param_response_t); + + break; + + case NFAPI_NR_PHY_MSG_TYPE_PNF_CONFIG_REQUEST: + if (unpackedBufLen >= sizeof(nfapi_nr_pnf_config_request_t)) + retLen = sizeof(nfapi_nr_pnf_config_request_t); + + break; + + case NFAPI_NR_PHY_MSG_TYPE_PNF_CONFIG_RESPONSE: + if (unpackedBufLen >= sizeof(nfapi_nr_pnf_config_response_t)) + retLen = sizeof(nfapi_nr_pnf_config_response_t); + + break; + + case NFAPI_NR_PHY_MSG_TYPE_PNF_START_REQUEST: + if (unpackedBufLen >= sizeof(nfapi_nr_pnf_start_request_t)) + retLen = sizeof(nfapi_nr_pnf_start_request_t); + + break; + + case NFAPI_NR_PHY_MSG_TYPE_PNF_START_RESPONSE: + if (unpackedBufLen >= sizeof(nfapi_nr_pnf_start_response_t)) + retLen = sizeof(nfapi_nr_pnf_start_response_t); + + break; + + case NFAPI_NR_PHY_MSG_TYPE_PNF_STOP_REQUEST: + if (unpackedBufLen >= sizeof(nfapi_nr_pnf_stop_request_t)) + retLen = sizeof(nfapi_nr_pnf_stop_request_t); + + break; + + case NFAPI_NR_PHY_MSG_TYPE_PNF_STOP_RESPONSE: + if (unpackedBufLen >= sizeof(nfapi_nr_pnf_stop_response_t)) + retLen = sizeof(nfapi_nr_pnf_stop_response_t); + + break; + + case NFAPI_NR_PHY_MSG_TYPE_PARAM_REQUEST: + if (unpackedBufLen >= sizeof(nfapi_nr_param_request_scf_t)) + retLen = sizeof(nfapi_nr_param_request_scf_t); + + break; + + case NFAPI_NR_PHY_MSG_TYPE_PARAM_RESPONSE: + if (unpackedBufLen >= sizeof(nfapi_nr_param_response_scf_t)) + retLen = sizeof(nfapi_nr_param_response_scf_t); + + break; + + case NFAPI_NR_PHY_MSG_TYPE_CONFIG_REQUEST: + if (unpackedBufLen >= sizeof(nfapi_nr_config_request_scf_t)) + retLen = sizeof(nfapi_nr_config_request_scf_t); + + break; + + case NFAPI_NR_PHY_MSG_TYPE_CONFIG_RESPONSE: + if (unpackedBufLen >= sizeof(nfapi_nr_config_response_scf_t)) + retLen = sizeof(nfapi_nr_config_response_scf_t); + + break; + + case NFAPI_NR_PHY_MSG_TYPE_START_REQUEST: + if (unpackedBufLen >= sizeof( nfapi_nr_start_request_scf_t)) + retLen = sizeof( nfapi_nr_start_request_scf_t); + + break; + + case NFAPI_NR_PHY_MSG_TYPE_START_RESPONSE: + if (unpackedBufLen >= sizeof(nfapi_nr_start_response_scf_t)) + retLen = sizeof(nfapi_nr_start_response_scf_t); + + break; + + case NFAPI_NR_PHY_MSG_TYPE_STOP_REQUEST: + if (unpackedBufLen >= sizeof(nfapi_stop_request_t)) + retLen = sizeof(nfapi_stop_request_t); + + break; + + case NFAPI_NR_PHY_MSG_TYPE_STOP_RESPONSE: + if (unpackedBufLen >= sizeof(nfapi_stop_response_t)) + retLen = sizeof(nfapi_stop_response_t); + + break; + + default: + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s Unknown message ID %d\n", __FUNCTION__, msgId); + break; + } + + return retLen; +} + + +static int check_unpack_length(nfapi_message_id_e msgId, uint32_t unpackedBufLen) { + int retLen = 0; + + switch (msgId) { + case NFAPI_PNF_PARAM_REQUEST: + if (unpackedBufLen >= sizeof(nfapi_pnf_param_request_t)) + retLen = sizeof(nfapi_pnf_param_request_t); + + break; + + case NFAPI_PNF_PARAM_RESPONSE: + if (unpackedBufLen >= sizeof(nfapi_pnf_param_response_t)) + retLen = sizeof(nfapi_pnf_param_response_t); + + break; + + case NFAPI_PNF_CONFIG_REQUEST: + if (unpackedBufLen >= sizeof(nfapi_pnf_config_request_t)) + retLen = sizeof(nfapi_pnf_config_request_t); + + break; + + case NFAPI_PNF_CONFIG_RESPONSE: + if (unpackedBufLen >= sizeof(nfapi_pnf_config_response_t)) + retLen = sizeof(nfapi_pnf_config_response_t); + + break; + + case NFAPI_PNF_START_REQUEST: + if (unpackedBufLen >= sizeof(nfapi_pnf_start_request_t)) + retLen = sizeof(nfapi_pnf_start_request_t); + + break; + + case NFAPI_PNF_START_RESPONSE: + if (unpackedBufLen >= sizeof(nfapi_pnf_start_response_t)) + retLen = sizeof(nfapi_pnf_start_response_t); + + break; + + case NFAPI_PNF_STOP_REQUEST: + if (unpackedBufLen >= sizeof(nfapi_pnf_stop_request_t)) + retLen = sizeof(nfapi_pnf_stop_request_t); + + break; + + case NFAPI_PNF_STOP_RESPONSE: + if (unpackedBufLen >= sizeof(nfapi_pnf_stop_response_t)) + retLen = sizeof(nfapi_pnf_stop_response_t); + + break; + + case NFAPI_PARAM_REQUEST: + if (unpackedBufLen >= sizeof(nfapi_param_request_t)) + retLen = sizeof(nfapi_param_request_t); + + break; + + case NFAPI_PARAM_RESPONSE: + if (unpackedBufLen >= sizeof(nfapi_param_response_t)) + retLen = sizeof(nfapi_param_response_t); + + break; + + case NFAPI_CONFIG_REQUEST: + if (unpackedBufLen >= sizeof(nfapi_config_request_t)) + retLen = sizeof(nfapi_config_request_t); + + break; + + case NFAPI_CONFIG_RESPONSE: + if (unpackedBufLen >= sizeof(nfapi_config_response_t)) + retLen = sizeof(nfapi_config_response_t); + + break; + + case NFAPI_START_REQUEST: + if (unpackedBufLen >= sizeof( nfapi_start_request_t)) + retLen = sizeof( nfapi_start_request_t); + + break; + + case NFAPI_START_RESPONSE: + if (unpackedBufLen >= sizeof(nfapi_start_response_t)) + retLen = sizeof(nfapi_start_response_t); + + break; + + case NFAPI_STOP_REQUEST: + if (unpackedBufLen >= sizeof(nfapi_stop_request_t)) + retLen = sizeof(nfapi_stop_request_t); + + break; + + case NFAPI_STOP_RESPONSE: + if (unpackedBufLen >= sizeof(nfapi_stop_response_t)) + retLen = sizeof(nfapi_stop_response_t); + + break; + + case NFAPI_MEASUREMENT_REQUEST: + if (unpackedBufLen >= sizeof(nfapi_measurement_request_t)) + retLen = sizeof(nfapi_measurement_request_t); + + break; + + case NFAPI_MEASUREMENT_RESPONSE: + if (unpackedBufLen >= sizeof(nfapi_measurement_response_t)) + retLen = sizeof(nfapi_measurement_response_t); + + break; + + default: + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s Unknown message ID %d\n", __FUNCTION__, msgId); + break; + } + + return retLen; +} + + +// Main unpack functions - public + +int nfapi_p5_message_header_unpack(void *pMessageBuf, uint32_t messageBufLen, void *pUnpackedBuf, uint32_t unpackedBufLen, nfapi_p4_p5_codec_config_t *config) { + nfapi_p4_p5_message_header_t *pMessageHeader = pUnpackedBuf; + uint8_t *pReadPackedMessage = pMessageBuf; + uint8_t *end = pMessageBuf + messageBufLen; + + if (pMessageBuf == NULL || pUnpackedBuf == NULL) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "P5 header unpack supplied pointers are null\n"); + return -1; + } + + if (messageBufLen < NFAPI_HEADER_LENGTH || unpackedBufLen < sizeof(nfapi_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; + } + + // process the header + return ( pull16(&pReadPackedMessage, &pMessageHeader->phy_id, end) && + pull16(&pReadPackedMessage, &pMessageHeader->message_id, end) && + pull16(&pReadPackedMessage, &pMessageHeader->message_length, end) && + pull16(&pReadPackedMessage, &pMessageHeader->spare, end) ); +} + +int nfapi_nr_p5_message_unpack(void *pMessageBuf, uint32_t messageBufLen, void *pUnpackedBuf, uint32_t unpackedBufLen, nfapi_p4_p5_codec_config_t *config) { + nfapi_p4_p5_message_header_t *pMessageHeader = pUnpackedBuf; + uint8_t *pReadPackedMessage = pMessageBuf; + uint8_t *end = pMessageBuf + messageBufLen; + + if (pMessageBuf == NULL || pUnpackedBuf == NULL) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "P5 unpack supplied pointers are null\n"); + return -1; + } + + if (messageBufLen < NFAPI_HEADER_LENGTH || unpackedBufLen < sizeof(nfapi_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; + } + + uint8_t *ptr = pReadPackedMessage; + printf("\n Read message unpack: "); + + while(ptr < end) { + printf(" %d ", *ptr); + ptr++; + } + + printf("\n"); + // clean the supplied buffer for - tag value blanking + (void)memset(pUnpackedBuf, 0, unpackedBufLen); + + // process the header + if( !(pull16(&pReadPackedMessage, &pMessageHeader->phy_id, end ) && + pull16(&pReadPackedMessage, &pMessageHeader->message_id, end) && + pull16(&pReadPackedMessage, &pMessageHeader->message_length, end) && + pull16(&pReadPackedMessage, &pMessageHeader->spare, end))) { + // failed to read the header + return -1; + } + + int result = -1; + + if(check_nr_unpack_length(pMessageHeader->message_id, unpackedBufLen) == 0) { + // the unpack buffer is not big enough for the struct + return -1; + } + + // look for the specific message + switch (pMessageHeader->message_id) { + case NFAPI_NR_PHY_MSG_TYPE_PNF_PARAM_REQUEST: + result = unpack_nr_pnf_param_request(&pReadPackedMessage, end, pMessageHeader, config); + break; + + case NFAPI_NR_PHY_MSG_TYPE_PNF_PARAM_RESPONSE: + result = unpack_nr_pnf_param_response(&pReadPackedMessage, end, pMessageHeader, config); + break; + + case NFAPI_NR_PHY_MSG_TYPE_PNF_CONFIG_REQUEST: + result = unpack_nr_pnf_config_request(&pReadPackedMessage, end, pMessageHeader, config); + break; + + case NFAPI_NR_PHY_MSG_TYPE_PNF_CONFIG_RESPONSE: + result = unpack_nr_pnf_config_response(&pReadPackedMessage, end, pMessageHeader, config); + break; + + case NFAPI_NR_PHY_MSG_TYPE_PNF_START_REQUEST: + result = unpack_nr_pnf_start_request(&pReadPackedMessage, end, pMessageHeader, config); + break; + + case NFAPI_NR_PHY_MSG_TYPE_PNF_START_RESPONSE: + result = unpack_nr_pnf_start_response(&pReadPackedMessage, end, pMessageHeader, config); + break; + + case NFAPI_NR_PHY_MSG_TYPE_PNF_STOP_REQUEST: + result = unpack_pnf_stop_request(&pReadPackedMessage, end, pMessageHeader, config); + break; + + case NFAPI_NR_PHY_MSG_TYPE_PNF_STOP_RESPONSE: + result = unpack_pnf_stop_response(&pReadPackedMessage, end, pMessageHeader, config); + break; + + case NFAPI_NR_PHY_MSG_TYPE_PARAM_REQUEST: + result = unpack_nr_param_request(&pReadPackedMessage, end, pMessageHeader, config); + break; + + case NFAPI_NR_PHY_MSG_TYPE_PARAM_RESPONSE: + result = unpack_nr_param_response(&pReadPackedMessage, end, pMessageHeader, config); + break; + + case NFAPI_NR_PHY_MSG_TYPE_CONFIG_REQUEST: + result = unpack_nr_config_request(&pReadPackedMessage, end, pMessageHeader, config); + break; + + case NFAPI_NR_PHY_MSG_TYPE_CONFIG_RESPONSE: + result = unpack_nr_config_response(&pReadPackedMessage, end, pMessageHeader, config); + break; + + case NFAPI_NR_PHY_MSG_TYPE_START_REQUEST: + result = unpack_nr_start_request(&pReadPackedMessage, end, pMessageHeader, config); + break; + + case NFAPI_NR_PHY_MSG_TYPE_START_RESPONSE: + result = unpack_nr_start_response(&pReadPackedMessage, end, pMessageHeader, config); + break; + + case NFAPI_NR_PHY_MSG_TYPE_STOP_REQUEST: + result = unpack_stop_request(&pReadPackedMessage, end, pMessageHeader, config); + break; + + case NFAPI_NR_PHY_MSG_TYPE_STOP_RESPONSE: + result = unpack_stop_response(&pReadPackedMessage, end, pMessageHeader, config); + break; + + case NFAPI_MEASUREMENT_REQUEST: + result = unpack_measurement_request(&pReadPackedMessage, end, pMessageHeader, config); + break; + + case NFAPI_MEASUREMENT_RESPONSE: + result = unpack_measurement_response(&pReadPackedMessage, end, pMessageHeader, config); + break; + + default: + if(pMessageHeader->message_id >= NFAPI_VENDOR_EXT_MSG_MIN && + pMessageHeader->message_id <= NFAPI_VENDOR_EXT_MSG_MAX) { + if(config && config->unpack_p4_p5_vendor_extension) { + result = (config->unpack_p4_p5_vendor_extension)(pMessageHeader, &pReadPackedMessage, end, config); + } else { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s VE NFAPI message ID %d. No ve decoder provided\n", __FUNCTION__, pMessageHeader->message_id); + } + } else { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s NFAPI Unknown P5 message ID %d\n", __FUNCTION__, pMessageHeader->message_id); + } + + break; + } + + return result; +} + +int nfapi_p5_message_unpack(void *pMessageBuf, uint32_t messageBufLen, void *pUnpackedBuf, uint32_t unpackedBufLen, nfapi_p4_p5_codec_config_t *config) { + nfapi_p4_p5_message_header_t *pMessageHeader = pUnpackedBuf; + uint8_t *pReadPackedMessage = pMessageBuf; + uint8_t *end = pMessageBuf + messageBufLen; + + if (pMessageBuf == NULL || pUnpackedBuf == NULL) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "P5 unpack supplied pointers are null\n"); + return -1; + } + + if (messageBufLen < NFAPI_HEADER_LENGTH || unpackedBufLen < sizeof(nfapi_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; + } + + uint8_t *ptr = pReadPackedMessage; + printf("\n Read message unpack: "); + + while(ptr < end) { + printf(" %d ", *ptr); + ptr++; + } + + printf("\n"); + // clean the supplied buffer for - tag value blanking + (void)memset(pUnpackedBuf, 0, unpackedBufLen); + + // process the header + if( !(pull16(&pReadPackedMessage, &pMessageHeader->phy_id, end ) && + pull16(&pReadPackedMessage, &pMessageHeader->message_id, end) && + pull16(&pReadPackedMessage, &pMessageHeader->message_length, end) && + pull16(&pReadPackedMessage, &pMessageHeader->spare, end))) { + // failed to read the header + return -1; + } + + int result = -1; + + if(check_unpack_length(pMessageHeader->message_id, unpackedBufLen) == 0) { + // the unpack buffer is not big enough for the struct + return -1; + } + + // look for the specific message + switch (pMessageHeader->message_id) { + case NFAPI_PNF_PARAM_REQUEST: + result = unpack_pnf_param_request(&pReadPackedMessage, end, pMessageHeader, config); + break; + + case NFAPI_PNF_PARAM_RESPONSE: + result = unpack_pnf_param_response(&pReadPackedMessage, end, pMessageHeader, config); + break; + + case NFAPI_PNF_CONFIG_REQUEST: + result = unpack_pnf_config_request(&pReadPackedMessage, end, pMessageHeader, config); + break; + + case NFAPI_PNF_CONFIG_RESPONSE: + result = unpack_pnf_config_response(&pReadPackedMessage, end, pMessageHeader, config); + break; + + case NFAPI_PNF_START_REQUEST: + result = unpack_pnf_start_request(&pReadPackedMessage, end, pMessageHeader, config); + break; + + case NFAPI_PNF_START_RESPONSE: + result = unpack_pnf_start_response(&pReadPackedMessage, end, pMessageHeader, config); + break; + + case NFAPI_PNF_STOP_REQUEST: + result = unpack_pnf_stop_request(&pReadPackedMessage, end, pMessageHeader, config); + break; + + case NFAPI_PNF_STOP_RESPONSE: + result = unpack_pnf_stop_response(&pReadPackedMessage, end, pMessageHeader, config); + break; + + case NFAPI_PARAM_REQUEST: + result = unpack_param_request(&pReadPackedMessage, end, pMessageHeader, config); + break; + + case NFAPI_PARAM_RESPONSE: + result = unpack_param_response(&pReadPackedMessage, end, pMessageHeader, config); + break; + + case NFAPI_CONFIG_REQUEST: + result = unpack_config_request(&pReadPackedMessage, end, pMessageHeader, config); + break; + + case NFAPI_CONFIG_RESPONSE: + result = unpack_config_response(&pReadPackedMessage, end, pMessageHeader, config); + break; + + case NFAPI_START_REQUEST: + result = unpack_start_request(&pReadPackedMessage, end, pMessageHeader, config); + break; + + case NFAPI_START_RESPONSE: + result = unpack_start_response(&pReadPackedMessage, end, pMessageHeader, config); + break; + + case NFAPI_STOP_REQUEST: + result = unpack_stop_request(&pReadPackedMessage, end, pMessageHeader, config); + break; + + case NFAPI_STOP_RESPONSE: + result = unpack_stop_response(&pReadPackedMessage, end, pMessageHeader, config); + break; + + case NFAPI_MEASUREMENT_REQUEST: + result = unpack_measurement_request(&pReadPackedMessage, end, pMessageHeader, config); + break; + + case NFAPI_MEASUREMENT_RESPONSE: + result = unpack_measurement_response(&pReadPackedMessage, end, pMessageHeader, config); + break; + + default: + if(pMessageHeader->message_id >= NFAPI_VENDOR_EXT_MSG_MIN && + pMessageHeader->message_id <= NFAPI_VENDOR_EXT_MSG_MAX) { + if(config && config->unpack_p4_p5_vendor_extension) { + result = (config->unpack_p4_p5_vendor_extension)(pMessageHeader, &pReadPackedMessage, end, config); + } else { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s VE NFAPI message ID %d. No ve decoder provided\n", __FUNCTION__, pMessageHeader->message_id); + } + } else { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s NFAPI Unknown P5 message ID %d\n", __FUNCTION__, pMessageHeader->message_id); + } + + break; + } + + return result; +} + diff --git a/nfapi/open-nFAPI/nfapi/src/nfapi_p7.c b/nfapi/open-nFAPI/nfapi/src/nfapi_p7.c old mode 100755 new mode 100644 index ec59ba39b2..bfc9d6cae6 --- a/nfapi/open-nFAPI/nfapi/src/nfapi_p7.c +++ b/nfapi/open-nFAPI/nfapi/src/nfapi_p7.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. @@ -38,8232 +38,7323 @@ #include #include "nfapi_nr_interface_scf.h" -extern int nfapi_unpack_p7_vendor_extension(nfapi_p7_message_header_t* header, uint8_t **ppReadPackedMsg, void* user_data); -extern int nfapi_pack_p7_vendor_extension(nfapi_p7_message_header_t* header, uint8_t **ppWritePackedMsg, void* user_data); +extern int nfapi_unpack_p7_vendor_extension(nfapi_p7_message_header_t *header, uint8_t **ppReadPackedMsg, void *user_data); +extern int nfapi_pack_p7_vendor_extension(nfapi_p7_message_header_t *header, uint8_t **ppWritePackedMsg, void *user_data); -uint32_t nfapi_calculate_checksum(uint8_t* buffer, uint16_t len) -{ - uint32_t chksum = 0; - // calcaulte upto the checksum - chksum = crc32(chksum, buffer, 8); - - // skip the checksum - uint8_t zeros[4] = {0, 0, 0, 0}; - chksum = crc32(chksum, zeros, 4); - - // continu with the rest of the mesage - chksum = crc32(chksum, &buffer[NFAPI_P7_HEADER_LENGTH], len - NFAPI_P7_HEADER_LENGTH); - - // return the inverse - return ~(chksum); +uint32_t nfapi_calculate_checksum(uint8_t *buffer, uint16_t len) { + uint32_t chksum = 0; + // calcaulte upto the checksum + chksum = crc32(chksum, buffer, 8); + // skip the checksum + uint8_t zeros[4] = {0, 0, 0, 0}; + chksum = crc32(chksum, zeros, 4); + // continu with the rest of the mesage + chksum = crc32(chksum, &buffer[NFAPI_P7_HEADER_LENGTH], len - NFAPI_P7_HEADER_LENGTH); + // return the inverse + return ~(chksum); } -int nfapi_p7_update_checksum(uint8_t* buffer, uint32_t len) -{ - uint32_t checksum = nfapi_calculate_checksum(buffer, len); - - uint8_t* p_write = &buffer[8]; - return (push32(checksum, &p_write, buffer + len) > 0 ? 0 : -1); +int nfapi_p7_update_checksum(uint8_t *buffer, uint32_t len) { + uint32_t checksum = nfapi_calculate_checksum(buffer, len); + uint8_t *p_write = &buffer[8]; + return (push32(checksum, &p_write, buffer + len) > 0 ? 0 : -1); } -int nfapi_p7_update_transmit_timestamp(uint8_t* buffer, uint32_t timestamp) -{ - uint8_t* p_write = &buffer[12]; - return (push32(timestamp, &p_write, buffer + 16) > 0 ? 0 : -1); +int nfapi_p7_update_transmit_timestamp(uint8_t *buffer, uint32_t timestamp) { + uint8_t *p_write = &buffer[12]; + return (push32(timestamp, &p_write, buffer + 16) > 0 ? 0 : -1); } -uint32_t nfapi_p7_calculate_checksum(uint8_t* buffer, uint32_t len) -{ - return nfapi_calculate_checksum(buffer, len); +uint32_t nfapi_p7_calculate_checksum(uint8_t *buffer, uint32_t len) { + return nfapi_calculate_checksum(buffer, len); } -void* nfapi_p7_allocate(size_t size, nfapi_p7_codec_config_t* config) -{ - if(size == 0) - return 0; +void *nfapi_p7_allocate(size_t size, nfapi_p7_codec_config_t *config) { + if(size == 0) + return 0; - void* buffer_p = NULL; - if(config && config->allocate) - { - buffer_p = (config->allocate)(size); - if(buffer_p != NULL){ - memset(buffer_p,0,size); - } - return buffer_p; - } - else - { - buffer_p = calloc(1, size); - return buffer_p; - } + void *buffer_p = NULL; + + if(config && config->allocate) { + buffer_p = (config->allocate)(size); + + if(buffer_p != NULL) { + memset(buffer_p,0,size); + } + + return buffer_p; + } else { + buffer_p = calloc(1, size); + return buffer_p; + } } -void nfapi_p7_deallocate(void* ptr, nfapi_p7_codec_config_t* config) -{ - if(ptr == NULL) - return; +void nfapi_p7_deallocate(void *ptr, nfapi_p7_codec_config_t *config) { + if(ptr == NULL) + return; - if(config && config->deallocate) - { - return (config->deallocate)(ptr); - } - else - { - return free(ptr); - } + if(config && config->deallocate) { + return (config->deallocate)(ptr); + } else { + return free(ptr); + } } // Pack routines -static uint8_t pack_dl_config_dci_dl_pdu_rel8_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_dl_config_dci_dl_pdu_rel8_t* value = (nfapi_dl_config_dci_dl_pdu_rel8_t*)tlv; - - //NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s() dci_format:%u\n", __FUNCTION__, value->dci_format); - - return ( push8(value->dci_format, ppWritePackedMsg, end) && - push8(value->cce_idx, ppWritePackedMsg, end) && - push8(value->aggregation_level, ppWritePackedMsg, end) && - push16(value->rnti, ppWritePackedMsg, end) && - push8(value->resource_allocation_type, ppWritePackedMsg, end) && - push8(value->virtual_resource_block_assignment_flag, ppWritePackedMsg, end) && - push32(value->resource_block_coding, ppWritePackedMsg, end) && - push8(value->mcs_1, ppWritePackedMsg, end) && - push8(value->redundancy_version_1, ppWritePackedMsg, end) && - push8(value->new_data_indicator_1, ppWritePackedMsg, end) && - push8(value->transport_block_to_codeword_swap_flag, ppWritePackedMsg, end) && - push8(value->mcs_2, ppWritePackedMsg, end) && - push8(value->redundancy_version_2, ppWritePackedMsg, end) && - push8(value->new_data_indicator_2, ppWritePackedMsg, end) && - push8(value->harq_process, ppWritePackedMsg, end) && - push8(value->tpmi, ppWritePackedMsg, end) && - push8(value->pmi, ppWritePackedMsg, end) && - push8(value->precoding_information, ppWritePackedMsg, end) && - push8(value->tpc, ppWritePackedMsg, end) && - push8(value->downlink_assignment_index, ppWritePackedMsg, end) && - push8(value->ngap, ppWritePackedMsg, end) && - push8(value->transport_block_size_index, ppWritePackedMsg, end) && - push8(value->downlink_power_offset, ppWritePackedMsg, end) && - push8(value->allocate_prach_flag, ppWritePackedMsg, end) && - push8(value->preamble_index, ppWritePackedMsg, end) && - push8(value->prach_mask_index, ppWritePackedMsg, end) && - push8(value->rnti_type, ppWritePackedMsg, end) && - push16(value->transmission_power, ppWritePackedMsg, end)); +static uint8_t pack_dl_config_dci_dl_pdu_rel8_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_dl_config_dci_dl_pdu_rel8_t *value = (nfapi_dl_config_dci_dl_pdu_rel8_t *)tlv; + //NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s() dci_format:%u\n", __FUNCTION__, value->dci_format); + return ( push8(value->dci_format, ppWritePackedMsg, end) && + push8(value->cce_idx, ppWritePackedMsg, end) && + push8(value->aggregation_level, ppWritePackedMsg, end) && + push16(value->rnti, ppWritePackedMsg, end) && + push8(value->resource_allocation_type, ppWritePackedMsg, end) && + push8(value->virtual_resource_block_assignment_flag, ppWritePackedMsg, end) && + push32(value->resource_block_coding, ppWritePackedMsg, end) && + push8(value->mcs_1, ppWritePackedMsg, end) && + push8(value->redundancy_version_1, ppWritePackedMsg, end) && + push8(value->new_data_indicator_1, ppWritePackedMsg, end) && + push8(value->transport_block_to_codeword_swap_flag, ppWritePackedMsg, end) && + push8(value->mcs_2, ppWritePackedMsg, end) && + push8(value->redundancy_version_2, ppWritePackedMsg, end) && + push8(value->new_data_indicator_2, ppWritePackedMsg, end) && + push8(value->harq_process, ppWritePackedMsg, end) && + push8(value->tpmi, ppWritePackedMsg, end) && + push8(value->pmi, ppWritePackedMsg, end) && + push8(value->precoding_information, ppWritePackedMsg, end) && + push8(value->tpc, ppWritePackedMsg, end) && + push8(value->downlink_assignment_index, ppWritePackedMsg, end) && + push8(value->ngap, ppWritePackedMsg, end) && + push8(value->transport_block_size_index, ppWritePackedMsg, end) && + push8(value->downlink_power_offset, ppWritePackedMsg, end) && + push8(value->allocate_prach_flag, ppWritePackedMsg, end) && + push8(value->preamble_index, ppWritePackedMsg, end) && + push8(value->prach_mask_index, ppWritePackedMsg, end) && + push8(value->rnti_type, ppWritePackedMsg, end) && + push16(value->transmission_power, ppWritePackedMsg, end)); } -static uint8_t pack_dl_config_dci_dl_pdu_rel9_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_dl_config_dci_dl_pdu_rel9_t* value = (nfapi_dl_config_dci_dl_pdu_rel9_t*)tlv; - - return( push8(value->mcch_flag, ppWritePackedMsg, end) && - push8(value->mcch_change_notification, ppWritePackedMsg, end) && - push8(value->scrambling_identity, ppWritePackedMsg, end)); +static uint8_t pack_dl_config_dci_dl_pdu_rel9_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_dl_config_dci_dl_pdu_rel9_t *value = (nfapi_dl_config_dci_dl_pdu_rel9_t *)tlv; + return( push8(value->mcch_flag, ppWritePackedMsg, end) && + push8(value->mcch_change_notification, ppWritePackedMsg, end) && + push8(value->scrambling_identity, ppWritePackedMsg, end)); } -static uint8_t pack_dl_config_dci_dl_pdu_rel10_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_dl_config_dci_dl_pdu_rel10_t* value = (nfapi_dl_config_dci_dl_pdu_rel10_t*)tlv; - - return ( push8(value->cross_carrier_scheduling_flag, ppWritePackedMsg, end) && - push8(value->carrier_indicator, ppWritePackedMsg, end) && - push8(value->srs_flag, ppWritePackedMsg, end) && - push8(value->srs_request, ppWritePackedMsg, end) && - push8(value->antenna_ports_scrambling_and_layers, ppWritePackedMsg, end) && - push8(value->total_dci_length_including_padding, ppWritePackedMsg, end) && - push8(value->n_dl_rb, ppWritePackedMsg, end)); +static uint8_t pack_dl_config_dci_dl_pdu_rel10_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_dl_config_dci_dl_pdu_rel10_t *value = (nfapi_dl_config_dci_dl_pdu_rel10_t *)tlv; + return ( push8(value->cross_carrier_scheduling_flag, ppWritePackedMsg, end) && + push8(value->carrier_indicator, ppWritePackedMsg, end) && + push8(value->srs_flag, ppWritePackedMsg, end) && + push8(value->srs_request, ppWritePackedMsg, end) && + push8(value->antenna_ports_scrambling_and_layers, ppWritePackedMsg, end) && + push8(value->total_dci_length_including_padding, ppWritePackedMsg, end) && + push8(value->n_dl_rb, ppWritePackedMsg, end)); } -static uint8_t pack_dl_config_dci_dl_pdu_rel11_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_dl_config_dci_dl_pdu_rel11_t* value = (nfapi_dl_config_dci_dl_pdu_rel11_t*)tlv; - - return ( push8(value->harq_ack_resource_offset, ppWritePackedMsg, end) && - push8(value->pdsch_re_mapping_quasi_co_location_indicator, ppWritePackedMsg, end)); +static uint8_t pack_dl_config_dci_dl_pdu_rel11_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_dl_config_dci_dl_pdu_rel11_t *value = (nfapi_dl_config_dci_dl_pdu_rel11_t *)tlv; + return ( push8(value->harq_ack_resource_offset, ppWritePackedMsg, end) && + push8(value->pdsch_re_mapping_quasi_co_location_indicator, ppWritePackedMsg, end)); } -static uint8_t pack_dl_config_dci_dl_pdu_rel12_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_dl_config_dci_dl_pdu_rel12_t* value = (nfapi_dl_config_dci_dl_pdu_rel12_t*)tlv; - - return ( push8(value->primary_cell_type, ppWritePackedMsg, end) && - push8(value->ul_dl_configuration_flag, ppWritePackedMsg, end) && - push8(value->number_ul_dl_configurations, ppWritePackedMsg, end) && - pusharray8(value->ul_dl_configuration_indication, NFAPI_MAX_UL_DL_CONFIGURATIONS, value->number_ul_dl_configurations, ppWritePackedMsg, end)); +static uint8_t pack_dl_config_dci_dl_pdu_rel12_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_dl_config_dci_dl_pdu_rel12_t *value = (nfapi_dl_config_dci_dl_pdu_rel12_t *)tlv; + return ( push8(value->primary_cell_type, ppWritePackedMsg, end) && + push8(value->ul_dl_configuration_flag, ppWritePackedMsg, end) && + push8(value->number_ul_dl_configurations, ppWritePackedMsg, end) && + pusharray8(value->ul_dl_configuration_indication, NFAPI_MAX_UL_DL_CONFIGURATIONS, value->number_ul_dl_configurations, ppWritePackedMsg, end)); } -static uint8_t pack_tpm_value(nfapi_dl_config_dci_dl_tpm_t* value, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - if (!( push8(value->num_prb_per_subband, ppWritePackedMsg, end) && - push8(value->number_of_subbands, ppWritePackedMsg, end) && - push8(value->num_antennas, ppWritePackedMsg, end))) - return 0; - - uint8_t idx = 0; - for(idx = 0; idx < value->number_of_subbands; ++idx) - { - nfapi_dl_config_dci_dl_tpm_subband_info_t* subband_info = &(value->subband_info[idx]); - - if(!(push8(subband_info->subband_index, ppWritePackedMsg, end) && - push8(subband_info->scheduled_ues, ppWritePackedMsg, end))) - return 0; - +static uint8_t pack_tpm_value(nfapi_dl_config_dci_dl_tpm_t *value, uint8_t **ppWritePackedMsg, uint8_t *end) { + if (!( push8(value->num_prb_per_subband, ppWritePackedMsg, end) && + push8(value->number_of_subbands, ppWritePackedMsg, end) && + push8(value->num_antennas, ppWritePackedMsg, end))) + return 0; - uint8_t antenna_idx = 0; - uint8_t scheduled_ue_idx = 0; - - for(antenna_idx = 0; antenna_idx < value->num_antennas; ++antenna_idx) - { - for(scheduled_ue_idx = 0; scheduled_ue_idx < subband_info->scheduled_ues; ++scheduled_ue_idx) - { - if(!push16(subband_info->precoding_value[antenna_idx][scheduled_ue_idx], ppWritePackedMsg, end)) - return 0; - } - } + uint8_t idx = 0; - } - - - return 1; - + for(idx = 0; idx < value->number_of_subbands; ++idx) { + nfapi_dl_config_dci_dl_tpm_subband_info_t *subband_info = &(value->subband_info[idx]); + + if(!(push8(subband_info->subband_index, ppWritePackedMsg, end) && + push8(subband_info->scheduled_ues, ppWritePackedMsg, end))) + return 0; + + uint8_t antenna_idx = 0; + uint8_t scheduled_ue_idx = 0; + + for(antenna_idx = 0; antenna_idx < value->num_antennas; ++antenna_idx) { + for(scheduled_ue_idx = 0; scheduled_ue_idx < subband_info->scheduled_ues; ++scheduled_ue_idx) { + if(!push16(subband_info->precoding_value[antenna_idx][scheduled_ue_idx], ppWritePackedMsg, end)) + return 0; + } + } + } + + return 1; } -static uint8_t pack_dl_tti_csi_rs_pdu_rel15_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_nr_dl_tti_csi_rs_pdu_rel15_t* value = (nfapi_nr_dl_tti_csi_rs_pdu_rel15_t*)tlv; - - return( - push16(value->bwp_size, ppWritePackedMsg, end) && - push16(value->bwp_start, ppWritePackedMsg, end) && - - push8(value->subcarrier_spacing, ppWritePackedMsg, end) && - push8(value->cyclic_prefix, ppWritePackedMsg, end) && - - push16(value->start_rb, ppWritePackedMsg, end) && - push16(value->nr_of_rbs, ppWritePackedMsg, end) && - - push8(value->csi_type, ppWritePackedMsg, end) && - push8(value->row, ppWritePackedMsg, end) && - - push16(value->freq_domain, ppWritePackedMsg, end) && - push8(value->symb_l0, ppWritePackedMsg, end) && - - push8(value->symb_l1, ppWritePackedMsg, end) && - push8(value->cdm_type, ppWritePackedMsg, end) && - - push8(value->freq_density, ppWritePackedMsg, end) && - push16(value->scramb_id, ppWritePackedMsg, end) && - - push8(value->power_control_offset, ppWritePackedMsg, end) && - push8(value->power_control_offset_ss, ppWritePackedMsg, end) - ); - +static uint8_t pack_dl_tti_csi_rs_pdu_rel15_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_nr_dl_tti_csi_rs_pdu_rel15_t *value = (nfapi_nr_dl_tti_csi_rs_pdu_rel15_t *)tlv; + return( + push16(value->bwp_size, ppWritePackedMsg, end) && + push16(value->bwp_start, ppWritePackedMsg, end) && + push8(value->subcarrier_spacing, ppWritePackedMsg, end) && + push8(value->cyclic_prefix, ppWritePackedMsg, end) && + push16(value->start_rb, ppWritePackedMsg, end) && + push16(value->nr_of_rbs, ppWritePackedMsg, end) && + push8(value->csi_type, ppWritePackedMsg, end) && + push8(value->row, ppWritePackedMsg, end) && + push16(value->freq_domain, ppWritePackedMsg, end) && + push8(value->symb_l0, ppWritePackedMsg, end) && + push8(value->symb_l1, ppWritePackedMsg, end) && + push8(value->cdm_type, ppWritePackedMsg, end) && + push8(value->freq_density, ppWritePackedMsg, end) && + push16(value->scramb_id, ppWritePackedMsg, end) && + push8(value->power_control_offset, ppWritePackedMsg, end) && + push8(value->power_control_offset_ss, ppWritePackedMsg, end) + ); } -static uint8_t pack_dl_tti_pdcch_pdu_rel15_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_nr_dl_tti_pdcch_pdu_rel15_t* value = (nfapi_nr_dl_tti_pdcch_pdu_rel15_t*)tlv; - - for(uint8_t i = 0; i < MAX_DCI_CORESET; ++i) - { - if(!push16(value->dci_pdu[i].RNTI, ppWritePackedMsg, end) && - push16(value->dci_pdu[i].ScramblingId, ppWritePackedMsg, end) && +static uint8_t pack_dl_tti_pdcch_pdu_rel15_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_nr_dl_tti_pdcch_pdu_rel15_t *value = (nfapi_nr_dl_tti_pdcch_pdu_rel15_t *)tlv; - push16(value->dci_pdu[i].ScramblingRNTI, ppWritePackedMsg, end) && - push8(value->dci_pdu[i].CceIndex, ppWritePackedMsg, end) && - push8(value->dci_pdu[i].AggregationLevel, ppWritePackedMsg, end) && - push8(value->dci_pdu[i].beta_PDCCH_1_0, ppWritePackedMsg, end) && + for(uint8_t i = 0; i < MAX_DCI_CORESET; ++i) { + if(!push16(value->dci_pdu[i].RNTI, ppWritePackedMsg, end) && + push16(value->dci_pdu[i].ScramblingId, ppWritePackedMsg, end) && + push16(value->dci_pdu[i].ScramblingRNTI, ppWritePackedMsg, end) && + push8(value->dci_pdu[i].CceIndex, ppWritePackedMsg, end) && + push8(value->dci_pdu[i].AggregationLevel, ppWritePackedMsg, end) && + push8(value->dci_pdu[i].beta_PDCCH_1_0, ppWritePackedMsg, end) && + push8(value->dci_pdu[i].powerControlOffsetSS, ppWritePackedMsg, end) && + push16(value->dci_pdu[i].PayloadSizeBits, ppWritePackedMsg, end) && + pusharray8(value->dci_pdu[i].Payload, DCI_PAYLOAD_BYTE_LEN, value->dci_pdu[i].PayloadSizeBits, ppWritePackedMsg, end)); - push8(value->dci_pdu[i].powerControlOffsetSS, ppWritePackedMsg, end) && - push16(value->dci_pdu[i].PayloadSizeBits, ppWritePackedMsg, end) && - pusharray8(value->dci_pdu[i].Payload, DCI_PAYLOAD_BYTE_LEN, value->dci_pdu[i].PayloadSizeBits, ppWritePackedMsg, end)); - - return 0; - } - - // TODO: resolve the packaging of array (currently sending a single element) - return( - push16(value->BWPSize, ppWritePackedMsg, end) && - push16(value->BWPStart, ppWritePackedMsg, end) && - push8(value->SubcarrierSpacing, ppWritePackedMsg, end) && - push8(value->CyclicPrefix, ppWritePackedMsg, end) && - - push8(value->StartSymbolIndex, ppWritePackedMsg, end) && - push8(value->DurationSymbols, ppWritePackedMsg, end) && - pusharray8(value->FreqDomainResource, 6, 6, ppWritePackedMsg, end) && - push8(value->CceRegMappingType, ppWritePackedMsg, end) && - - push8(value->RegBundleSize, ppWritePackedMsg, end) && - push8(value->InterleaverSize, ppWritePackedMsg, end) && - push8(value->CoreSetType, ppWritePackedMsg, end) && - push16(value->ShiftIndex, ppWritePackedMsg, end) && - - push8(value->precoderGranularity, ppWritePackedMsg, end) && - push16(value->numDlDci, ppWritePackedMsg, end)); + return 0; + } + // TODO: resolve the packaging of array (currently sending a single element) + return( + push16(value->BWPSize, ppWritePackedMsg, end) && + push16(value->BWPStart, ppWritePackedMsg, end) && + push8(value->SubcarrierSpacing, ppWritePackedMsg, end) && + push8(value->CyclicPrefix, ppWritePackedMsg, end) && + push8(value->StartSymbolIndex, ppWritePackedMsg, end) && + push8(value->DurationSymbols, ppWritePackedMsg, end) && + pusharray8(value->FreqDomainResource, 6, 6, ppWritePackedMsg, end) && + push8(value->CceRegMappingType, ppWritePackedMsg, end) && + push8(value->RegBundleSize, ppWritePackedMsg, end) && + push8(value->InterleaverSize, ppWritePackedMsg, end) && + push8(value->CoreSetType, ppWritePackedMsg, end) && + push16(value->ShiftIndex, ppWritePackedMsg, end) && + push8(value->precoderGranularity, ppWritePackedMsg, end) && + push16(value->numDlDci, ppWritePackedMsg, end)); } -static uint8_t pack_dl_tti_pdsch_pdu_rel15_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_nr_dl_tti_pdsch_pdu_rel15_t* value = (nfapi_nr_dl_tti_pdsch_pdu_rel15_t*)tlv; - - // TODO: resolve the packaging of array (currently sending a single element) - return( - push16(value->pduBitmap, ppWritePackedMsg, end) && - push16(value->rnti, ppWritePackedMsg, end) && - push16(value->pduIndex, ppWritePackedMsg, end) && - push16(value->BWPSize, ppWritePackedMsg, end) && - - push16(value->BWPStart, ppWritePackedMsg, end) && - push8(value->SubcarrierSpacing, ppWritePackedMsg, end) && - push8(value->CyclicPrefix, ppWritePackedMsg, end) && - push8(value->NrOfCodewords, ppWritePackedMsg, end) && - - pusharray16(value->targetCodeRate, 2, 1, ppWritePackedMsg, end) && - pusharray8(value->qamModOrder, 2, 1, ppWritePackedMsg, end) && - pusharray8(value->mcsIndex, 2, 1, ppWritePackedMsg, end) && - pusharray8(value->mcsTable, 2, 1, ppWritePackedMsg, end) && - - pusharray8(value->rvIndex, 2, 1, ppWritePackedMsg, end) && - pusharray32(value->TBSize, 2, 1, ppWritePackedMsg, end) && - push16(value->dataScramblingId, ppWritePackedMsg, end) && - push8(value->nrOfLayers, ppWritePackedMsg, end) && - - push8(value->transmissionScheme, ppWritePackedMsg, end) && - push8(value->refPoint, ppWritePackedMsg, end) && - push16(value->dlDmrsSymbPos, ppWritePackedMsg, end) && - push8(value->dmrsConfigType, ppWritePackedMsg, end) && - - push16(value->dlDmrsScramblingId, ppWritePackedMsg, end) && - push8(value->SCID, ppWritePackedMsg, end) && - push8(value->numDmrsCdmGrpsNoData, ppWritePackedMsg, end) && - push16(value->dmrsPorts, ppWritePackedMsg, end) && - - push8(value->resourceAlloc, ppWritePackedMsg, end) && - push16(value->rbStart, ppWritePackedMsg, end) && - push16(value->rbSize, ppWritePackedMsg, end) && - - push8(value->VRBtoPRBMapping, ppWritePackedMsg, end) && - push8(value->StartSymbolIndex, ppWritePackedMsg, end) && - push8(value->NrOfSymbols, ppWritePackedMsg, end) && - push8(value->PTRSPortIndex, ppWritePackedMsg, end) && - - push8(value->PTRSTimeDensity, ppWritePackedMsg, end) && - push8(value->PTRSFreqDensity, ppWritePackedMsg, end) && - push8(value->PTRSReOffset, ppWritePackedMsg, end) - ); - +static uint8_t pack_dl_tti_pdsch_pdu_rel15_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_nr_dl_tti_pdsch_pdu_rel15_t *value = (nfapi_nr_dl_tti_pdsch_pdu_rel15_t *)tlv; + // TODO: resolve the packaging of array (currently sending a single element) + return( + push16(value->pduBitmap, ppWritePackedMsg, end) && + push16(value->rnti, ppWritePackedMsg, end) && + push16(value->pduIndex, ppWritePackedMsg, end) && + push16(value->BWPSize, ppWritePackedMsg, end) && + push16(value->BWPStart, ppWritePackedMsg, end) && + push8(value->SubcarrierSpacing, ppWritePackedMsg, end) && + push8(value->CyclicPrefix, ppWritePackedMsg, end) && + push8(value->NrOfCodewords, ppWritePackedMsg, end) && + pusharray16(value->targetCodeRate, 2, 1, ppWritePackedMsg, end) && + pusharray8(value->qamModOrder, 2, 1, ppWritePackedMsg, end) && + pusharray8(value->mcsIndex, 2, 1, ppWritePackedMsg, end) && + pusharray8(value->mcsTable, 2, 1, ppWritePackedMsg, end) && + pusharray8(value->rvIndex, 2, 1, ppWritePackedMsg, end) && + pusharray32(value->TBSize, 2, 1, ppWritePackedMsg, end) && + push16(value->dataScramblingId, ppWritePackedMsg, end) && + push8(value->nrOfLayers, ppWritePackedMsg, end) && + push8(value->transmissionScheme, ppWritePackedMsg, end) && + push8(value->refPoint, ppWritePackedMsg, end) && + push16(value->dlDmrsSymbPos, ppWritePackedMsg, end) && + push8(value->dmrsConfigType, ppWritePackedMsg, end) && + push16(value->dlDmrsScramblingId, ppWritePackedMsg, end) && + push8(value->SCID, ppWritePackedMsg, end) && + push8(value->numDmrsCdmGrpsNoData, ppWritePackedMsg, end) && + push16(value->dmrsPorts, ppWritePackedMsg, end) && + push8(value->resourceAlloc, ppWritePackedMsg, end) && + push16(value->rbStart, ppWritePackedMsg, end) && + push16(value->rbSize, ppWritePackedMsg, end) && + push8(value->VRBtoPRBMapping, ppWritePackedMsg, end) && + push8(value->StartSymbolIndex, ppWritePackedMsg, end) && + push8(value->NrOfSymbols, ppWritePackedMsg, end) && + push8(value->PTRSPortIndex, ppWritePackedMsg, end) && + push8(value->PTRSTimeDensity, ppWritePackedMsg, end) && + push8(value->PTRSFreqDensity, ppWritePackedMsg, end) && + push8(value->PTRSReOffset, ppWritePackedMsg, end) + ); } -static uint8_t pack_dl_tti_ssb_pdu_rel15_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_nr_dl_tti_ssb_pdu_rel15_t* value = (nfapi_nr_dl_tti_ssb_pdu_rel15_t*)tlv; - - return( - push16(value->PhysCellId, ppWritePackedMsg, end) && - push8(value->BetaPss, ppWritePackedMsg, end) && - push8(value->SsbBlockIndex, ppWritePackedMsg, end) && - push8(value->SsbSubcarrierOffset, ppWritePackedMsg, end) && - push16(value->ssbOffsetPointA, ppWritePackedMsg, end) && - push8(value->bchPayloadFlag, ppWritePackedMsg, end) && - push32(value->bchPayload, ppWritePackedMsg, end) - // TODO: pack precoding_and_beamforming too - ); - +static uint8_t pack_dl_tti_ssb_pdu_rel15_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_nr_dl_tti_ssb_pdu_rel15_t *value = (nfapi_nr_dl_tti_ssb_pdu_rel15_t *)tlv; + return( + push16(value->PhysCellId, ppWritePackedMsg, end) && + push8(value->BetaPss, ppWritePackedMsg, end) && + push8(value->SsbBlockIndex, ppWritePackedMsg, end) && + push8(value->SsbSubcarrierOffset, ppWritePackedMsg, end) && + push16(value->ssbOffsetPointA, ppWritePackedMsg, end) && + push8(value->bchPayloadFlag, ppWritePackedMsg, end) && + push32(value->bchPayload, ppWritePackedMsg, end) + // TODO: pack precoding_and_beamforming too + ); } -static uint8_t pack_dl_config_dci_dl_pdu_rel13_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_dl_config_dci_dl_pdu_rel13_t* value = (nfapi_dl_config_dci_dl_pdu_rel13_t*)tlv; - - return( push8(value->laa_end_partial_sf_flag, ppWritePackedMsg, end) && - push8(value->laa_end_partial_sf_configuration, ppWritePackedMsg, end) && - push8(value->initial_lbt_sf, ppWritePackedMsg, end) && - push8(value->codebook_size_determination, ppWritePackedMsg, end) && - push8(value->drms_table_flag, ppWritePackedMsg, end) && - push8(value->tpm_struct_flag, ppWritePackedMsg, end) && - (value->tpm_struct_flag == 1 ? pack_tpm_value(&(value->tpm), ppWritePackedMsg, end) : 1)); +static uint8_t pack_dl_config_dci_dl_pdu_rel13_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_dl_config_dci_dl_pdu_rel13_t *value = (nfapi_dl_config_dci_dl_pdu_rel13_t *)tlv; + return( push8(value->laa_end_partial_sf_flag, ppWritePackedMsg, end) && + push8(value->laa_end_partial_sf_configuration, ppWritePackedMsg, end) && + push8(value->initial_lbt_sf, ppWritePackedMsg, end) && + push8(value->codebook_size_determination, ppWritePackedMsg, end) && + push8(value->drms_table_flag, ppWritePackedMsg, end) && + push8(value->tpm_struct_flag, ppWritePackedMsg, end) && + (value->tpm_struct_flag == 1 ? pack_tpm_value(&(value->tpm), ppWritePackedMsg, end) : 1)); } -static uint8_t pack_dl_config_bch_pdu_rel8_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_dl_config_bch_pdu_rel8_t* value = (nfapi_dl_config_bch_pdu_rel8_t*)tlv; - - //NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s()\n", __FUNCTION__); - - return( push16(value->length, ppWritePackedMsg, end) && - push16(value->pdu_index, ppWritePackedMsg, end) && - push16(value->transmission_power, ppWritePackedMsg, end)); +static uint8_t pack_dl_config_bch_pdu_rel8_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_dl_config_bch_pdu_rel8_t *value = (nfapi_dl_config_bch_pdu_rel8_t *)tlv; + //NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s()\n", __FUNCTION__); + return( push16(value->length, ppWritePackedMsg, end) && + push16(value->pdu_index, ppWritePackedMsg, end) && + push16(value->transmission_power, ppWritePackedMsg, end)); } -static uint8_t pack_dl_config_mch_pdu_rel8_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_dl_config_mch_pdu_rel8_t* value = (nfapi_dl_config_mch_pdu_rel8_t*)tlv; - - return ( push16(value->length, ppWritePackedMsg, end) && - push16(value->pdu_index, ppWritePackedMsg, end) && - push16(value->rnti, ppWritePackedMsg, end) && - push8(value->resource_allocation_type, ppWritePackedMsg, end) && - push32(value->resource_block_coding, ppWritePackedMsg, end) && - push8(value->modulation, ppWritePackedMsg, end) && - push16(value->transmission_power, ppWritePackedMsg, end) && - push16(value->mbsfn_area_id, ppWritePackedMsg, end)); +static uint8_t pack_dl_config_mch_pdu_rel8_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_dl_config_mch_pdu_rel8_t *value = (nfapi_dl_config_mch_pdu_rel8_t *)tlv; + return ( push16(value->length, ppWritePackedMsg, end) && + push16(value->pdu_index, ppWritePackedMsg, end) && + push16(value->rnti, ppWritePackedMsg, end) && + push8(value->resource_allocation_type, ppWritePackedMsg, end) && + push32(value->resource_block_coding, ppWritePackedMsg, end) && + push8(value->modulation, ppWritePackedMsg, end) && + push16(value->transmission_power, ppWritePackedMsg, end) && + push16(value->mbsfn_area_id, ppWritePackedMsg, end)); } -static uint8_t pack_bf_vector_info(void* elem, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_bf_vector_t* bf = (nfapi_bf_vector_t*)elem; +static uint8_t pack_bf_vector_info(void *elem, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_bf_vector_t *bf = (nfapi_bf_vector_t *)elem; + return ( push8(bf->subband_index, ppWritePackedMsg, end) && + push8(bf->num_antennas, ppWritePackedMsg, end) && + pusharray16(bf->bf_value, NFAPI_MAX_NUM_ANTENNAS, bf->num_antennas, ppWritePackedMsg, end)); +} +static uint8_t pack_dl_config_dlsch_pdu_rel8_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_dl_config_dlsch_pdu_rel8_t *value = (nfapi_dl_config_dlsch_pdu_rel8_t *)tlv; + return ( push16(value->length, ppWritePackedMsg, end) && + push16(value->pdu_index, ppWritePackedMsg, end) && + push16(value->rnti, ppWritePackedMsg, end) && + push8(value->resource_allocation_type, ppWritePackedMsg, end) && + push8(value->virtual_resource_block_assignment_flag, ppWritePackedMsg, end) && + push32(value->resource_block_coding, ppWritePackedMsg, end) && + push8(value->modulation, ppWritePackedMsg, end) && + push8(value->redundancy_version, ppWritePackedMsg, end) && + push8(value->transport_blocks, ppWritePackedMsg, end) && + push8(value->transport_block_to_codeword_swap_flag, ppWritePackedMsg, end) && + push8(value->transmission_scheme, ppWritePackedMsg, end) && + push8(value->number_of_layers, ppWritePackedMsg, end) && + push8(value->number_of_subbands, ppWritePackedMsg, end) && + pusharray8(value->codebook_index, NFAPI_MAX_NUM_SUBBANDS, value->number_of_subbands, ppWritePackedMsg, end) && + push8(value->ue_category_capacity, ppWritePackedMsg, end) && + push8(value->pa, ppWritePackedMsg, end) && + push8(value->delta_power_offset_index, ppWritePackedMsg, end) && + push8(value->ngap, ppWritePackedMsg, end) && + push8(value->nprb, ppWritePackedMsg, end) && + push8(value->transmission_mode, ppWritePackedMsg, end) && + push8(value->num_bf_prb_per_subband, ppWritePackedMsg, end) && + push8(value->num_bf_vector, ppWritePackedMsg, end) && + packarray(value->bf_vector, sizeof(nfapi_bf_vector_t), NFAPI_MAX_BF_VECTORS, value->num_bf_vector, ppWritePackedMsg, end, &pack_bf_vector_info)); +} +static uint8_t pack_dl_config_dlsch_pdu_rel9_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_dl_config_dlsch_pdu_rel9_t *value = (nfapi_dl_config_dlsch_pdu_rel9_t *)tlv; + return ( push8(value->nscid, ppWritePackedMsg, end) ); +} +static uint8_t pack_dl_config_dlsch_pdu_rel10_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_dl_config_dlsch_pdu_rel10_t *value = (nfapi_dl_config_dlsch_pdu_rel10_t *)tlv; + return ( push8(value->csi_rs_flag, ppWritePackedMsg, end) && + push8(value->csi_rs_resource_config_r10, ppWritePackedMsg, end) && + push16(value->csi_rs_zero_tx_power_resource_config_bitmap_r10, ppWritePackedMsg, end) && + push8(value->csi_rs_number_nzp_configuration, ppWritePackedMsg, end) && + pusharray8(value->csi_rs_resource_config, NFAPI_MAX_CSI_RS_RESOURCE_CONFIG, value->csi_rs_number_nzp_configuration, ppWritePackedMsg, end) && + push8(value->pdsch_start, ppWritePackedMsg, end)); +} +static uint8_t pack_dl_config_dlsch_pdu_rel11_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_dl_config_dlsch_pdu_rel11_t *value = (nfapi_dl_config_dlsch_pdu_rel11_t *)tlv; + return( push8(value->drms_config_flag, ppWritePackedMsg, end) && + push16(value->drms_scrambling, ppWritePackedMsg, end) && + push8(value->csi_config_flag, ppWritePackedMsg, end) && + push16(value->csi_scrambling, ppWritePackedMsg, end) && + push8(value->pdsch_re_mapping_flag, ppWritePackedMsg, end) && + push8(value->pdsch_re_mapping_atenna_ports, ppWritePackedMsg, end) && + push8(value->pdsch_re_mapping_freq_shift, ppWritePackedMsg, end)); +} +static uint8_t pack_dl_config_dlsch_pdu_rel12_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_dl_config_dlsch_pdu_rel12_t *value = (nfapi_dl_config_dlsch_pdu_rel12_t *)tlv; + return( push8(value->altcqi_table_r12, ppWritePackedMsg, end) && + push8(value->maxlayers, ppWritePackedMsg, end) && + push8(value->n_dl_harq, ppWritePackedMsg, end)); +} +static uint8_t pack_dl_config_dlsch_pdu_rel13_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_dl_config_dlsch_pdu_rel13_t *value = (nfapi_dl_config_dlsch_pdu_rel13_t *)tlv; + return( push8(value->dwpts_symbols, ppWritePackedMsg, end) && + push8(value->initial_lbt_sf, ppWritePackedMsg, end) && + push8(value->ue_type, ppWritePackedMsg, end) && + push8(value->pdsch_payload_type, ppWritePackedMsg, end) && + push16(value->initial_transmission_sf_io, ppWritePackedMsg, end) && + push8(value->drms_table_flag, ppWritePackedMsg, end)); +} +static uint8_t pack_dl_config_pch_pdu_rel8_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_dl_config_pch_pdu_rel8_t *value = (nfapi_dl_config_pch_pdu_rel8_t *)tlv; + return( push16(value->length, ppWritePackedMsg, end) && + push16(value->pdu_index, ppWritePackedMsg, end) && + push16(value->p_rnti, ppWritePackedMsg, end) && + push8(value->resource_allocation_type, ppWritePackedMsg, end) && + push8(value->virtual_resource_block_assignment_flag, ppWritePackedMsg, end) && + push32(value->resource_block_coding, ppWritePackedMsg, end) && + push8(value->mcs, ppWritePackedMsg, end) && + push8(value->redundancy_version, ppWritePackedMsg, end) && + push8(value->number_of_transport_blocks, ppWritePackedMsg, end) && + push8(value->transport_block_to_codeword_swap_flag, ppWritePackedMsg, end) && + push8(value->transmission_scheme, ppWritePackedMsg, end) && + push8(value->number_of_layers, ppWritePackedMsg, end) && + push8(value->codebook_index, ppWritePackedMsg, end) && + push8(value->ue_category_capacity, ppWritePackedMsg, end) && + push8(value->pa, ppWritePackedMsg, end) && + push16(value->transmission_power, ppWritePackedMsg, end) && + push8(value->nprb, ppWritePackedMsg, end) && + push8(value->ngap, ppWritePackedMsg, end)); +} +static uint8_t pack_dl_config_pch_pdu_rel13_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_dl_config_pch_pdu_rel13_t *value = (nfapi_dl_config_pch_pdu_rel13_t *)tlv; + return ( push8(value->ue_mode, ppWritePackedMsg, end) && + push16(value->initial_transmission_sf_io, ppWritePackedMsg, end)); +} +static uint8_t pack_dl_config_prs_pdu_rel9_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_dl_config_prs_pdu_rel9_t *value = (nfapi_dl_config_prs_pdu_rel9_t *)tlv; + return( push16(value->transmission_power, ppWritePackedMsg, end) && + push8(value->prs_bandwidth, ppWritePackedMsg, end) && + push8(value->prs_cyclic_prefix_type, ppWritePackedMsg, end) && + push8(value->prs_muting, ppWritePackedMsg, end)); +} +static uint8_t pack_dl_config_csi_rs_pdu_rel10_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_dl_config_csi_rs_pdu_rel10_t *value = (nfapi_dl_config_csi_rs_pdu_rel10_t *)tlv; + return( push8(value->csi_rs_antenna_port_count_r10, ppWritePackedMsg, end) && + push8(value->csi_rs_resource_config_r10, ppWritePackedMsg, end) && + push16(value->transmission_power, ppWritePackedMsg, end) && + push16(value->csi_rs_zero_tx_power_resource_config_bitmap_r10, ppWritePackedMsg, end) && + push8(value->csi_rs_number_of_nzp_configuration, ppWritePackedMsg, end) && + pusharray8(value->csi_rs_resource_config, NFAPI_MAX_CSI_RS_RESOURCE_CONFIG, value->csi_rs_number_of_nzp_configuration, ppWritePackedMsg, end)); +} +static uint8_t pack_dl_config_csi_rs_pdu_rel13_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_dl_config_csi_rs_pdu_rel13_t *value = (nfapi_dl_config_csi_rs_pdu_rel13_t *)tlv; - return ( push8(bf->subband_index, ppWritePackedMsg, end) && - push8(bf->num_antennas, ppWritePackedMsg, end) && - pusharray16(bf->bf_value, NFAPI_MAX_NUM_ANTENNAS, bf->num_antennas, ppWritePackedMsg, end)); + if(!(push8(value->csi_rs_class, ppWritePackedMsg, end) && + push8(value->cdm_type, ppWritePackedMsg, end) && + push8(value->num_bf_vector, ppWritePackedMsg, end))) { + return 0; + } - -} -static uint8_t pack_dl_config_dlsch_pdu_rel8_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_dl_config_dlsch_pdu_rel8_t* value = (nfapi_dl_config_dlsch_pdu_rel8_t*)tlv; + uint16_t i; - return ( push16(value->length, ppWritePackedMsg, end) && - push16(value->pdu_index, ppWritePackedMsg, end) && - push16(value->rnti, ppWritePackedMsg, end) && - push8(value->resource_allocation_type, ppWritePackedMsg, end) && - push8(value->virtual_resource_block_assignment_flag, ppWritePackedMsg, end) && - push32(value->resource_block_coding, ppWritePackedMsg, end) && - push8(value->modulation, ppWritePackedMsg, end) && - push8(value->redundancy_version, ppWritePackedMsg, end) && - push8(value->transport_blocks, ppWritePackedMsg, end) && - push8(value->transport_block_to_codeword_swap_flag, ppWritePackedMsg, end) && - push8(value->transmission_scheme, ppWritePackedMsg, end) && - push8(value->number_of_layers, ppWritePackedMsg, end) && - push8(value->number_of_subbands, ppWritePackedMsg, end) && - pusharray8(value->codebook_index, NFAPI_MAX_NUM_SUBBANDS, value->number_of_subbands, ppWritePackedMsg, end) && - push8(value->ue_category_capacity, ppWritePackedMsg, end) && - push8(value->pa, ppWritePackedMsg, end) && - push8(value->delta_power_offset_index, ppWritePackedMsg, end) && - push8(value->ngap, ppWritePackedMsg, end) && - push8(value->nprb, ppWritePackedMsg, end) && - push8(value->transmission_mode, ppWritePackedMsg, end) && - push8(value->num_bf_prb_per_subband, ppWritePackedMsg, end) && - push8(value->num_bf_vector, ppWritePackedMsg, end) && - packarray(value->bf_vector, sizeof(nfapi_bf_vector_t), NFAPI_MAX_BF_VECTORS, value->num_bf_vector, ppWritePackedMsg, end, &pack_bf_vector_info)); + for(i = 0; i < value->num_bf_vector; ++i) { + if(!(push8(value->bf_vector[i].csi_rs_resource_index, ppWritePackedMsg, end) && + pusharray16(value->bf_vector[i].bf_value, NFAPI_MAX_ANTENNA_PORT_COUNT, NFAPI_MAX_ANTENNA_PORT_COUNT, ppWritePackedMsg, end))) + return 0; + } + return 1; } -static uint8_t pack_dl_config_dlsch_pdu_rel9_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_dl_config_dlsch_pdu_rel9_t* value = (nfapi_dl_config_dlsch_pdu_rel9_t*)tlv; - return ( push8(value->nscid, ppWritePackedMsg, end) ); -} -static uint8_t pack_dl_config_dlsch_pdu_rel10_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_dl_config_dlsch_pdu_rel10_t* value = (nfapi_dl_config_dlsch_pdu_rel10_t*)tlv; - - return ( push8(value->csi_rs_flag, ppWritePackedMsg, end) && - push8(value->csi_rs_resource_config_r10, ppWritePackedMsg, end) && - push16(value->csi_rs_zero_tx_power_resource_config_bitmap_r10, ppWritePackedMsg, end) && - push8(value->csi_rs_number_nzp_configuration, ppWritePackedMsg, end) && - pusharray8(value->csi_rs_resource_config, NFAPI_MAX_CSI_RS_RESOURCE_CONFIG, value->csi_rs_number_nzp_configuration, ppWritePackedMsg, end) && - push8(value->pdsch_start, ppWritePackedMsg, end)); -} -static uint8_t pack_dl_config_dlsch_pdu_rel11_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_dl_config_dlsch_pdu_rel11_t* value = (nfapi_dl_config_dlsch_pdu_rel11_t*)tlv; - - return( push8(value->drms_config_flag, ppWritePackedMsg, end) && - push16(value->drms_scrambling, ppWritePackedMsg, end) && - push8(value->csi_config_flag, ppWritePackedMsg, end) && - push16(value->csi_scrambling, ppWritePackedMsg, end) && - push8(value->pdsch_re_mapping_flag, ppWritePackedMsg, end) && - push8(value->pdsch_re_mapping_atenna_ports, ppWritePackedMsg, end) && - push8(value->pdsch_re_mapping_freq_shift, ppWritePackedMsg, end)); -} -static uint8_t pack_dl_config_dlsch_pdu_rel12_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_dl_config_dlsch_pdu_rel12_t* value = (nfapi_dl_config_dlsch_pdu_rel12_t*)tlv; - - return( push8(value->altcqi_table_r12, ppWritePackedMsg, end) && - push8(value->maxlayers, ppWritePackedMsg, end) && - push8(value->n_dl_harq, ppWritePackedMsg, end)); -} -static uint8_t pack_dl_config_dlsch_pdu_rel13_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_dl_config_dlsch_pdu_rel13_t* value = (nfapi_dl_config_dlsch_pdu_rel13_t*)tlv; - - return( push8(value->dwpts_symbols, ppWritePackedMsg, end) && - push8(value->initial_lbt_sf, ppWritePackedMsg, end) && - push8(value->ue_type, ppWritePackedMsg, end) && - push8(value->pdsch_payload_type, ppWritePackedMsg, end) && - push16(value->initial_transmission_sf_io, ppWritePackedMsg, end) && - push8(value->drms_table_flag, ppWritePackedMsg, end)); -} -static uint8_t pack_dl_config_pch_pdu_rel8_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_dl_config_pch_pdu_rel8_t* value = (nfapi_dl_config_pch_pdu_rel8_t*)tlv; - - return( push16(value->length, ppWritePackedMsg, end) && - push16(value->pdu_index, ppWritePackedMsg, end) && - push16(value->p_rnti, ppWritePackedMsg, end) && - push8(value->resource_allocation_type, ppWritePackedMsg, end) && - push8(value->virtual_resource_block_assignment_flag, ppWritePackedMsg, end) && - push32(value->resource_block_coding, ppWritePackedMsg, end) && - push8(value->mcs, ppWritePackedMsg, end) && - push8(value->redundancy_version, ppWritePackedMsg, end) && - push8(value->number_of_transport_blocks, ppWritePackedMsg, end) && - push8(value->transport_block_to_codeword_swap_flag, ppWritePackedMsg, end) && - push8(value->transmission_scheme, ppWritePackedMsg, end) && - push8(value->number_of_layers, ppWritePackedMsg, end) && - push8(value->codebook_index, ppWritePackedMsg, end) && - push8(value->ue_category_capacity, ppWritePackedMsg, end) && - push8(value->pa, ppWritePackedMsg, end) && - push16(value->transmission_power, ppWritePackedMsg, end) && - push8(value->nprb, ppWritePackedMsg, end) && - push8(value->ngap, ppWritePackedMsg, end)); -} -static uint8_t pack_dl_config_pch_pdu_rel13_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_dl_config_pch_pdu_rel13_t* value = (nfapi_dl_config_pch_pdu_rel13_t*)tlv; - - return ( push8(value->ue_mode, ppWritePackedMsg, end) && - push16(value->initial_transmission_sf_io, ppWritePackedMsg, end)); -} -static uint8_t pack_dl_config_prs_pdu_rel9_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_dl_config_prs_pdu_rel9_t* value = (nfapi_dl_config_prs_pdu_rel9_t*)tlv; - - return( push16(value->transmission_power, ppWritePackedMsg, end) && - push8(value->prs_bandwidth, ppWritePackedMsg, end) && - push8(value->prs_cyclic_prefix_type, ppWritePackedMsg, end) && - push8(value->prs_muting, ppWritePackedMsg, end)); -} -static uint8_t pack_dl_config_csi_rs_pdu_rel10_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_dl_config_csi_rs_pdu_rel10_t* value = (nfapi_dl_config_csi_rs_pdu_rel10_t*)tlv; - - return( push8(value->csi_rs_antenna_port_count_r10, ppWritePackedMsg, end) && - push8(value->csi_rs_resource_config_r10, ppWritePackedMsg, end) && - push16(value->transmission_power, ppWritePackedMsg, end) && - push16(value->csi_rs_zero_tx_power_resource_config_bitmap_r10, ppWritePackedMsg, end) && - push8(value->csi_rs_number_of_nzp_configuration, ppWritePackedMsg, end) && - pusharray8(value->csi_rs_resource_config, NFAPI_MAX_CSI_RS_RESOURCE_CONFIG, value->csi_rs_number_of_nzp_configuration, ppWritePackedMsg, end)); -} -static uint8_t pack_dl_config_csi_rs_pdu_rel13_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_dl_config_csi_rs_pdu_rel13_t* value = (nfapi_dl_config_csi_rs_pdu_rel13_t*)tlv; - - if(!(push8(value->csi_rs_class, ppWritePackedMsg, end) && - push8(value->cdm_type, ppWritePackedMsg, end) && - push8(value->num_bf_vector, ppWritePackedMsg, end))) - { - return 0; - } - - uint16_t i; - for(i = 0; i < value->num_bf_vector; ++i) - { - if(!(push8(value->bf_vector[i].csi_rs_resource_index, ppWritePackedMsg, end) && - pusharray16(value->bf_vector[i].bf_value, NFAPI_MAX_ANTENNA_PORT_COUNT, NFAPI_MAX_ANTENNA_PORT_COUNT, ppWritePackedMsg, end))) - return 0; - } - - return 1; -} -static uint8_t pack_bf_vector(nfapi_bf_vector_t* vector, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - return ( push8(vector->subband_index, ppWritePackedMsg, end) && - push8(vector->num_antennas, ppWritePackedMsg, end) && - pusharray16(vector->bf_value, NFAPI_MAX_NUM_ANTENNAS, vector->num_antennas, ppWritePackedMsg, end)); +static uint8_t pack_bf_vector(nfapi_bf_vector_t *vector, uint8_t **ppWritePackedMsg, uint8_t *end) { + return ( push8(vector->subband_index, ppWritePackedMsg, end) && + push8(vector->num_antennas, ppWritePackedMsg, end) && + pusharray16(vector->bf_value, NFAPI_MAX_NUM_ANTENNAS, vector->num_antennas, ppWritePackedMsg, end)); } -static uint8_t pack_dl_config_epdcch_parameters_rel11_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_dl_config_epdcch_parameters_rel11_t* value = (nfapi_dl_config_epdcch_parameters_rel11_t*)tlv; - - return ( push8(value->epdcch_resource_assignment_flag, ppWritePackedMsg, end) && - push16(value->epdcch_id, ppWritePackedMsg, end) && - push8(value->epdcch_start_symbol, ppWritePackedMsg, end) && - push8(value->epdcch_num_prb, ppWritePackedMsg, end) && - pusharray8(value->epdcch_prb_index, NFAPI_MAX_EPDCCH_PRB, value->epdcch_num_prb, ppWritePackedMsg, end) && - pack_bf_vector(&value->bf_vector, ppWritePackedMsg, end)); +static uint8_t pack_dl_config_epdcch_parameters_rel11_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_dl_config_epdcch_parameters_rel11_t *value = (nfapi_dl_config_epdcch_parameters_rel11_t *)tlv; + return ( push8(value->epdcch_resource_assignment_flag, ppWritePackedMsg, end) && + push16(value->epdcch_id, ppWritePackedMsg, end) && + push8(value->epdcch_start_symbol, ppWritePackedMsg, end) && + push8(value->epdcch_num_prb, ppWritePackedMsg, end) && + pusharray8(value->epdcch_prb_index, NFAPI_MAX_EPDCCH_PRB, value->epdcch_num_prb, ppWritePackedMsg, end) && + pack_bf_vector(&value->bf_vector, ppWritePackedMsg, end)); } -static uint8_t pack_dl_config_epdcch_parameters_rel13_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_dl_config_epdcch_parameters_rel13_t* value = (nfapi_dl_config_epdcch_parameters_rel13_t*)tlv; - - return (push8(value->dwpts_symbols, ppWritePackedMsg, end) && - push8(value->initial_lbt_sf, ppWritePackedMsg, end)); +static uint8_t pack_dl_config_epdcch_parameters_rel13_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_dl_config_epdcch_parameters_rel13_t *value = (nfapi_dl_config_epdcch_parameters_rel13_t *)tlv; + return (push8(value->dwpts_symbols, ppWritePackedMsg, end) && + push8(value->initial_lbt_sf, ppWritePackedMsg, end)); } -static uint8_t pack_dl_config_mpdcch_pdu_rel13_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_dl_config_mpdcch_pdu_rel13_t* value = (nfapi_dl_config_mpdcch_pdu_rel13_t*)tlv; - - return ( push8(value->mpdcch_narrow_band, ppWritePackedMsg, end) && - push8(value->number_of_prb_pairs, ppWritePackedMsg, end) && - push8(value->resource_block_assignment, ppWritePackedMsg, end) && - push8(value->mpdcch_tansmission_type, ppWritePackedMsg, end) && - push8(value->start_symbol, ppWritePackedMsg, end) && - push8(value->ecce_index, ppWritePackedMsg, end) && - push8(value->aggregation_level, ppWritePackedMsg, end) && - push8(value->rnti_type, ppWritePackedMsg, end) && - push16(value->rnti, ppWritePackedMsg, end) && - push8(value->ce_mode, ppWritePackedMsg, end) && - push16(value->drms_scrambling_init, ppWritePackedMsg, end) && - push16(value->initial_transmission_sf_io, ppWritePackedMsg, end) && - push16(value->transmission_power, ppWritePackedMsg, end) && - push8(value->dci_format, ppWritePackedMsg, end) && - push16(value->resource_block_coding, ppWritePackedMsg, end) && - push8(value->mcs, ppWritePackedMsg, end) && - push8(value->pdsch_reptition_levels, ppWritePackedMsg, end) && - push8(value->redundancy_version, ppWritePackedMsg, end) && - push8(value->new_data_indicator, ppWritePackedMsg, end) && - push8(value->harq_process, ppWritePackedMsg, end) && - push8(value->tpmi_length, ppWritePackedMsg, end) && - push8(value->tpmi, ppWritePackedMsg, end) && - push8(value->pmi_flag, ppWritePackedMsg, end) && - push8(value->pmi, ppWritePackedMsg, end) && - push8(value->harq_resource_offset, ppWritePackedMsg, end) && - push8(value->dci_subframe_repetition_number, ppWritePackedMsg, end) && - push8(value->tpc, ppWritePackedMsg, end) && - push8(value->downlink_assignment_index_length, ppWritePackedMsg, end) && - push8(value->downlink_assignment_index, ppWritePackedMsg, end) && - push8(value->allocate_prach_flag, ppWritePackedMsg, end) && - push8(value->preamble_index, ppWritePackedMsg, end) && - push8(value->prach_mask_index, ppWritePackedMsg, end) && - push8(value->starting_ce_level, ppWritePackedMsg, end) && - push8(value->srs_request, ppWritePackedMsg, end) && - push8(value->antenna_ports_and_scrambling_identity_flag, ppWritePackedMsg, end) && - push8(value->antenna_ports_and_scrambling_identity, ppWritePackedMsg, end) && - push8(value->frequency_hopping_enabled_flag, ppWritePackedMsg, end) && - push8(value->paging_direct_indication_differentiation_flag, ppWritePackedMsg, end) && - push8(value->direct_indication, ppWritePackedMsg, end) && - push8(value->total_dci_length_including_padding, ppWritePackedMsg, end) && - push8(value->number_of_tx_antenna_ports, ppWritePackedMsg, end) && - pusharray16(value->precoding_value, NFAPI_MAX_TX_PHYSICAL_ANTENNA_PORTS, value->number_of_tx_antenna_ports, ppWritePackedMsg, end)); +static uint8_t pack_dl_config_mpdcch_pdu_rel13_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_dl_config_mpdcch_pdu_rel13_t *value = (nfapi_dl_config_mpdcch_pdu_rel13_t *)tlv; + return ( push8(value->mpdcch_narrow_band, ppWritePackedMsg, end) && + push8(value->number_of_prb_pairs, ppWritePackedMsg, end) && + push8(value->resource_block_assignment, ppWritePackedMsg, end) && + push8(value->mpdcch_tansmission_type, ppWritePackedMsg, end) && + push8(value->start_symbol, ppWritePackedMsg, end) && + push8(value->ecce_index, ppWritePackedMsg, end) && + push8(value->aggregation_level, ppWritePackedMsg, end) && + push8(value->rnti_type, ppWritePackedMsg, end) && + push16(value->rnti, ppWritePackedMsg, end) && + push8(value->ce_mode, ppWritePackedMsg, end) && + push16(value->drms_scrambling_init, ppWritePackedMsg, end) && + push16(value->initial_transmission_sf_io, ppWritePackedMsg, end) && + push16(value->transmission_power, ppWritePackedMsg, end) && + push8(value->dci_format, ppWritePackedMsg, end) && + push16(value->resource_block_coding, ppWritePackedMsg, end) && + push8(value->mcs, ppWritePackedMsg, end) && + push8(value->pdsch_reptition_levels, ppWritePackedMsg, end) && + push8(value->redundancy_version, ppWritePackedMsg, end) && + push8(value->new_data_indicator, ppWritePackedMsg, end) && + push8(value->harq_process, ppWritePackedMsg, end) && + push8(value->tpmi_length, ppWritePackedMsg, end) && + push8(value->tpmi, ppWritePackedMsg, end) && + push8(value->pmi_flag, ppWritePackedMsg, end) && + push8(value->pmi, ppWritePackedMsg, end) && + push8(value->harq_resource_offset, ppWritePackedMsg, end) && + push8(value->dci_subframe_repetition_number, ppWritePackedMsg, end) && + push8(value->tpc, ppWritePackedMsg, end) && + push8(value->downlink_assignment_index_length, ppWritePackedMsg, end) && + push8(value->downlink_assignment_index, ppWritePackedMsg, end) && + push8(value->allocate_prach_flag, ppWritePackedMsg, end) && + push8(value->preamble_index, ppWritePackedMsg, end) && + push8(value->prach_mask_index, ppWritePackedMsg, end) && + push8(value->starting_ce_level, ppWritePackedMsg, end) && + push8(value->srs_request, ppWritePackedMsg, end) && + push8(value->antenna_ports_and_scrambling_identity_flag, ppWritePackedMsg, end) && + push8(value->antenna_ports_and_scrambling_identity, ppWritePackedMsg, end) && + push8(value->frequency_hopping_enabled_flag, ppWritePackedMsg, end) && + push8(value->paging_direct_indication_differentiation_flag, ppWritePackedMsg, end) && + push8(value->direct_indication, ppWritePackedMsg, end) && + push8(value->total_dci_length_including_padding, ppWritePackedMsg, end) && + push8(value->number_of_tx_antenna_ports, ppWritePackedMsg, end) && + pusharray16(value->precoding_value, NFAPI_MAX_TX_PHYSICAL_ANTENNA_PORTS, value->number_of_tx_antenna_ports, ppWritePackedMsg, end)); } -static uint8_t pack_dl_config_nbch_pdu_rel13_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_dl_config_nbch_pdu_rel13_t* value = (nfapi_dl_config_nbch_pdu_rel13_t*)tlv; - - return (push16(value->length, ppWritePackedMsg, end) && - push16(value->pdu_index, ppWritePackedMsg, end) && - push16(value->transmission_power, ppWritePackedMsg, end) && - push16(value->hyper_sfn_2_lsbs, ppWritePackedMsg, end)); +static uint8_t pack_dl_config_nbch_pdu_rel13_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_dl_config_nbch_pdu_rel13_t *value = (nfapi_dl_config_nbch_pdu_rel13_t *)tlv; + return (push16(value->length, ppWritePackedMsg, end) && + push16(value->pdu_index, ppWritePackedMsg, end) && + push16(value->transmission_power, ppWritePackedMsg, end) && + push16(value->hyper_sfn_2_lsbs, ppWritePackedMsg, end)); } -static uint8_t pack_dl_config_npdcch_pdu_rel13_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_dl_config_npdcch_pdu_rel13_t* value = (nfapi_dl_config_npdcch_pdu_rel13_t*)tlv; - - return (push16(value->length, ppWritePackedMsg, end) && - push16(value->pdu_index, ppWritePackedMsg, end) && - push8(value->ncce_index, ppWritePackedMsg, end) && - push8(value->aggregation_level, ppWritePackedMsg, end) && - push8(value->start_symbol, ppWritePackedMsg, end) && - push8(value->rnti_type, ppWritePackedMsg, end) && - push16(value->rnti, ppWritePackedMsg, end) && - push8(value->scrambling_reinitialization_batch_index, ppWritePackedMsg, end) && - push8(value->nrs_antenna_ports_assumed_by_the_ue, ppWritePackedMsg, end) && - push8(value->dci_format, ppWritePackedMsg, end) && - push8(value->scheduling_delay, ppWritePackedMsg, end) && - push8(value->resource_assignment, ppWritePackedMsg, end) && - push8(value->repetition_number, ppWritePackedMsg, end) && - push8(value->mcs, ppWritePackedMsg, end) && - push8(value->new_data_indicator, ppWritePackedMsg, end) && - push8(value->harq_ack_resource, ppWritePackedMsg, end) && - push8(value->npdcch_order_indication, ppWritePackedMsg, end) && - push8(value->starting_number_of_nprach_repetitions, ppWritePackedMsg, end) && - push8(value->subcarrier_indication_of_nprach, ppWritePackedMsg, end) && - push8(value->paging_direct_indication_differentation_flag, ppWritePackedMsg, end) && - push8(value->direct_indication, ppWritePackedMsg, end) && - push8(value->dci_subframe_repetition_number, ppWritePackedMsg, end) && - push8(value->total_dci_length_including_padding, ppWritePackedMsg, end)); +static uint8_t pack_dl_config_npdcch_pdu_rel13_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_dl_config_npdcch_pdu_rel13_t *value = (nfapi_dl_config_npdcch_pdu_rel13_t *)tlv; + return (push16(value->length, ppWritePackedMsg, end) && + push16(value->pdu_index, ppWritePackedMsg, end) && + push8(value->ncce_index, ppWritePackedMsg, end) && + push8(value->aggregation_level, ppWritePackedMsg, end) && + push8(value->start_symbol, ppWritePackedMsg, end) && + push8(value->rnti_type, ppWritePackedMsg, end) && + push16(value->rnti, ppWritePackedMsg, end) && + push8(value->scrambling_reinitialization_batch_index, ppWritePackedMsg, end) && + push8(value->nrs_antenna_ports_assumed_by_the_ue, ppWritePackedMsg, end) && + push8(value->dci_format, ppWritePackedMsg, end) && + push8(value->scheduling_delay, ppWritePackedMsg, end) && + push8(value->resource_assignment, ppWritePackedMsg, end) && + push8(value->repetition_number, ppWritePackedMsg, end) && + push8(value->mcs, ppWritePackedMsg, end) && + push8(value->new_data_indicator, ppWritePackedMsg, end) && + push8(value->harq_ack_resource, ppWritePackedMsg, end) && + push8(value->npdcch_order_indication, ppWritePackedMsg, end) && + push8(value->starting_number_of_nprach_repetitions, ppWritePackedMsg, end) && + push8(value->subcarrier_indication_of_nprach, ppWritePackedMsg, end) && + push8(value->paging_direct_indication_differentation_flag, ppWritePackedMsg, end) && + push8(value->direct_indication, ppWritePackedMsg, end) && + push8(value->dci_subframe_repetition_number, ppWritePackedMsg, end) && + push8(value->total_dci_length_including_padding, ppWritePackedMsg, end)); } -static uint8_t pack_dl_config_ndlsch_pdu_rel13_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_dl_config_ndlsch_pdu_rel13_t* value = (nfapi_dl_config_ndlsch_pdu_rel13_t*)tlv; - - return (push16(value->length, ppWritePackedMsg, end) && - push16(value->pdu_index, ppWritePackedMsg, end) && - push8(value->start_symbol, ppWritePackedMsg, end) && - push8(value->rnti_type, ppWritePackedMsg, end) && - push16(value->rnti, ppWritePackedMsg, end) && - push16(value->resource_assignment, ppWritePackedMsg, end) && - push16(value->repetition_number, ppWritePackedMsg, end) && - push8(value->modulation, ppWritePackedMsg, end) && - push8(value->number_of_subframes_for_resource_assignment, ppWritePackedMsg, end) && - push8(value->scrambling_sequence_initialization_cinit, ppWritePackedMsg, end) && - push16(value->sf_idx, ppWritePackedMsg, end) && - push8(value->nrs_antenna_ports_assumed_by_the_ue, ppWritePackedMsg, end)); +static uint8_t pack_dl_config_ndlsch_pdu_rel13_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_dl_config_ndlsch_pdu_rel13_t *value = (nfapi_dl_config_ndlsch_pdu_rel13_t *)tlv; + return (push16(value->length, ppWritePackedMsg, end) && + push16(value->pdu_index, ppWritePackedMsg, end) && + push8(value->start_symbol, ppWritePackedMsg, end) && + push8(value->rnti_type, ppWritePackedMsg, end) && + push16(value->rnti, ppWritePackedMsg, end) && + push16(value->resource_assignment, ppWritePackedMsg, end) && + push16(value->repetition_number, ppWritePackedMsg, end) && + push8(value->modulation, ppWritePackedMsg, end) && + push8(value->number_of_subframes_for_resource_assignment, ppWritePackedMsg, end) && + push8(value->scrambling_sequence_initialization_cinit, ppWritePackedMsg, end) && + push16(value->sf_idx, ppWritePackedMsg, end) && + push8(value->nrs_antenna_ports_assumed_by_the_ue, ppWritePackedMsg, end)); } -static uint8_t pack_dl_tti_request_body_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_nr_dl_tti_request_pdu_t* value = (nfapi_nr_dl_tti_request_pdu_t*)tlv; +static uint8_t pack_dl_tti_request_body_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_nr_dl_tti_request_pdu_t *value = (nfapi_nr_dl_tti_request_pdu_t *)tlv; - if(!(push16(value->PDUSize, ppWritePackedMsg, end) && - push16(value->PDUType, ppWritePackedMsg, end) )) - return 0; + if(!(push16(value->PDUSize, ppWritePackedMsg, end) && + push16(value->PDUType, ppWritePackedMsg, end) )) + return 0; + // first match the pdu type, then call the respective function + switch(value->PDUType) { + case NFAPI_NR_DL_TTI_CSI_RS_PDU_TYPE: { + if(!(pack_dl_tti_csi_rs_pdu_rel15_value(&value->csi_rs_pdu.csi_rs_pdu_rel15,ppWritePackedMsg,end))) + return 0; + } + break; - // first match the pdu type, then call the respective function - switch(value->PDUType) - { - case NFAPI_NR_DL_TTI_CSI_RS_PDU_TYPE: - { - if(!(pack_dl_tti_csi_rs_pdu_rel15_value(&value->csi_rs_pdu.csi_rs_pdu_rel15,ppWritePackedMsg,end))) - return 0; - } - break; + case NFAPI_NR_DL_TTI_PDCCH_PDU_TYPE: { + if(!(pack_dl_tti_pdcch_pdu_rel15_value(&value->pdcch_pdu.pdcch_pdu_rel15,ppWritePackedMsg,end))) + return 0; + } + break; - case NFAPI_NR_DL_TTI_PDCCH_PDU_TYPE: - { - if(!(pack_dl_tti_pdcch_pdu_rel15_value(&value->pdcch_pdu.pdcch_pdu_rel15,ppWritePackedMsg,end))) - return 0; - } - break; - case NFAPI_NR_DL_TTI_PDSCH_PDU_TYPE: - { - if(!(pack_dl_tti_pdsch_pdu_rel15_value(&value->pdsch_pdu.pdsch_pdu_rel15,ppWritePackedMsg,end))) - return 0; - } - break; - case NFAPI_NR_DL_TTI_SSB_PDU_TYPE: - { - if(!(pack_dl_tti_ssb_pdu_rel15_value(&value->ssb_pdu.ssb_pdu_rel15,ppWritePackedMsg,end))) - return 0; - } - break; + case NFAPI_NR_DL_TTI_PDSCH_PDU_TYPE: { + if(!(pack_dl_tti_pdsch_pdu_rel15_value(&value->pdsch_pdu.pdsch_pdu_rel15,ppWritePackedMsg,end))) + return 0; + } + break; - default: - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "FIXME : Invalid DL_TTI pdu type %d \n", value->PDUType ); - } - break; - } + case NFAPI_NR_DL_TTI_SSB_PDU_TYPE: { + if(!(pack_dl_tti_ssb_pdu_rel15_value(&value->ssb_pdu.ssb_pdu_rel15,ppWritePackedMsg,end))) + return 0; + } + break; - return 1; + default: { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "FIXME : Invalid DL_TTI pdu type %d \n", value->PDUType ); + } + break; + } + + return 1; } -static uint8_t pack_dl_config_request_body_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_dl_config_request_body_t* value = (nfapi_dl_config_request_body_t*)tlv; +static uint8_t pack_dl_config_request_body_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_dl_config_request_body_t *value = (nfapi_dl_config_request_body_t *)tlv; - //NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s() dci:%u pdu:%u pdsch:%u rnti:%u pcfich:%u\n", __FUNCTION__, value->number_dci, value->number_pdu, value->number_pdsch_rnti, value->transmission_power_pcfich); + //NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s() dci:%u pdu:%u pdsch:%u rnti:%u pcfich:%u\n", __FUNCTION__, value->number_dci, value->number_pdu, value->number_pdsch_rnti, value->transmission_power_pcfich); - if(!(push8(value->number_pdcch_ofdm_symbols, ppWritePackedMsg, end) && - push8(value->number_dci, ppWritePackedMsg, end) && - push16(value->number_pdu, ppWritePackedMsg, end) && - push8(value->number_pdsch_rnti, ppWritePackedMsg, end) && - push16(value->transmission_power_pcfich, ppWritePackedMsg, end))) - { - return 0; - } + if(!(push8(value->number_pdcch_ofdm_symbols, ppWritePackedMsg, end) && + push8(value->number_dci, ppWritePackedMsg, end) && + push16(value->number_pdu, ppWritePackedMsg, end) && + push8(value->number_pdsch_rnti, ppWritePackedMsg, end) && + push16(value->transmission_power_pcfich, ppWritePackedMsg, end))) { + return 0; + } - uint16_t i = 0; - uint16_t total_number_of_pdus = value->number_pdu; - for(; i < total_number_of_pdus; ++i) - { - nfapi_dl_config_request_pdu_t* pdu = &(value->dl_config_pdu_list[i]); + uint16_t i = 0; + uint16_t total_number_of_pdus = value->number_pdu; - if(push8(pdu->pdu_type, ppWritePackedMsg, end) == 0) - return 0; + for(; i < total_number_of_pdus; ++i) { + nfapi_dl_config_request_pdu_t *pdu = &(value->dl_config_pdu_list[i]); - // Put a 0 size in and then determine the size after the pdu - // has been writen and write the calculated size - uint8_t* pWritePackedMsgPduSize = *ppWritePackedMsg; - pdu->pdu_size = 0; - if(push8(pdu->pdu_size, ppWritePackedMsg, end) == 0) - return 0; + if(push8(pdu->pdu_type, ppWritePackedMsg, end) == 0) + return 0; - switch(pdu->pdu_type) - { - case NFAPI_DL_CONFIG_DCI_DL_PDU_TYPE: - { - //NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s() NFAPI_DL_CONFIG_DCI_DL_PDU_TYPE\n", __FUNCTION__); + // Put a 0 size in and then determine the size after the pdu + // has been writen and write the calculated size + uint8_t *pWritePackedMsgPduSize = *ppWritePackedMsg; + pdu->pdu_size = 0; - if(!(pack_tlv(NFAPI_DL_CONFIG_REQUEST_DCI_DL_PDU_REL8_TAG, &pdu->dci_dl_pdu.dci_dl_pdu_rel8, ppWritePackedMsg, end, &pack_dl_config_dci_dl_pdu_rel8_value) && - pack_tlv(NFAPI_DL_CONFIG_REQUEST_DCI_DL_PDU_REL9_TAG, &pdu->dci_dl_pdu.dci_dl_pdu_rel9, ppWritePackedMsg, end, &pack_dl_config_dci_dl_pdu_rel9_value) && - pack_tlv(NFAPI_DL_CONFIG_REQUEST_DCI_DL_PDU_REL10_TAG, &pdu->dci_dl_pdu.dci_dl_pdu_rel10, ppWritePackedMsg, end, &pack_dl_config_dci_dl_pdu_rel10_value) && - pack_tlv(NFAPI_DL_CONFIG_REQUEST_DCI_DL_PDU_REL11_TAG, &pdu->dci_dl_pdu.dci_dl_pdu_rel11, ppWritePackedMsg, end, &pack_dl_config_dci_dl_pdu_rel11_value) && - pack_tlv(NFAPI_DL_CONFIG_REQUEST_DCI_DL_PDU_REL12_TAG, &pdu->dci_dl_pdu.dci_dl_pdu_rel12, ppWritePackedMsg, end, &pack_dl_config_dci_dl_pdu_rel12_value) && - pack_tlv(NFAPI_DL_CONFIG_REQUEST_DCI_DL_PDU_REL13_TAG, &pdu->dci_dl_pdu.dci_dl_pdu_rel13, ppWritePackedMsg, end, &pack_dl_config_dci_dl_pdu_rel13_value))) - { - return 0; - } - } - break; - case NFAPI_DL_CONFIG_BCH_PDU_TYPE: - { - //NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s() NFAPI_DL_CONFIG_BCH_PDU_TYPE\n", __FUNCTION__); + if(push8(pdu->pdu_size, ppWritePackedMsg, end) == 0) + return 0; - if(!(pack_tlv(NFAPI_DL_CONFIG_REQUEST_BCH_PDU_REL8_TAG, &pdu->bch_pdu.bch_pdu_rel8, ppWritePackedMsg, end, &pack_dl_config_bch_pdu_rel8_value))) - return 0; - } - break; - case NFAPI_DL_CONFIG_MCH_PDU_TYPE: - { - if(!(pack_tlv(NFAPI_DL_CONFIG_REQUEST_MCH_PDU_REL8_TAG, &pdu->mch_pdu.mch_pdu_rel8, ppWritePackedMsg, end, &pack_dl_config_mch_pdu_rel8_value))) - return 0; - } - break; - case NFAPI_DL_CONFIG_DLSCH_PDU_TYPE: - { - if(!(pack_tlv(NFAPI_DL_CONFIG_REQUEST_DLSCH_PDU_REL8_TAG, &pdu->dlsch_pdu.dlsch_pdu_rel8, ppWritePackedMsg, end, &pack_dl_config_dlsch_pdu_rel8_value) && - pack_tlv(NFAPI_DL_CONFIG_REQUEST_DLSCH_PDU_REL9_TAG, &pdu->dlsch_pdu.dlsch_pdu_rel9, ppWritePackedMsg, end, &pack_dl_config_dlsch_pdu_rel9_value) && - pack_tlv(NFAPI_DL_CONFIG_REQUEST_DLSCH_PDU_REL10_TAG, &pdu->dlsch_pdu.dlsch_pdu_rel10, ppWritePackedMsg, end, &pack_dl_config_dlsch_pdu_rel10_value) && - pack_tlv(NFAPI_DL_CONFIG_REQUEST_DLSCH_PDU_REL11_TAG, &pdu->dlsch_pdu.dlsch_pdu_rel11, ppWritePackedMsg, end, &pack_dl_config_dlsch_pdu_rel11_value) && - pack_tlv(NFAPI_DL_CONFIG_REQUEST_DLSCH_PDU_REL12_TAG, &pdu->dlsch_pdu.dlsch_pdu_rel12, ppWritePackedMsg, end, &pack_dl_config_dlsch_pdu_rel12_value) && - pack_tlv(NFAPI_DL_CONFIG_REQUEST_DLSCH_PDU_REL13_TAG, &pdu->dlsch_pdu.dlsch_pdu_rel13, ppWritePackedMsg, end, &pack_dl_config_dlsch_pdu_rel13_value))) - return 0; - } - break; - case NFAPI_DL_CONFIG_PCH_PDU_TYPE: - { - if(!(pack_tlv(NFAPI_DL_CONFIG_REQUEST_PCH_PDU_REL8_TAG, &pdu->pch_pdu.pch_pdu_rel8, ppWritePackedMsg, end, &pack_dl_config_pch_pdu_rel8_value) && - pack_tlv(NFAPI_DL_CONFIG_REQUEST_PCH_PDU_REL13_TAG, &pdu->pch_pdu.pch_pdu_rel13, ppWritePackedMsg, end, &pack_dl_config_pch_pdu_rel13_value))) - return 0; - } - break; - case NFAPI_DL_CONFIG_PRS_PDU_TYPE: - { - if(!(pack_tlv(NFAPI_DL_CONFIG_REQUEST_PRS_PDU_REL9_TAG, &pdu->prs_pdu.prs_pdu_rel9, ppWritePackedMsg, end, &pack_dl_config_prs_pdu_rel9_value))) - return 0; - } - break; - case NFAPI_DL_CONFIG_CSI_RS_PDU_TYPE: - { - if(!(pack_tlv(NFAPI_DL_CONFIG_REQUEST_CSI_RS_PDU_REL10_TAG, &pdu->csi_rs_pdu.csi_rs_pdu_rel10, ppWritePackedMsg, end, &pack_dl_config_csi_rs_pdu_rel10_value) && - pack_tlv(NFAPI_DL_CONFIG_REQUEST_CSI_RS_PDU_REL13_TAG, &pdu->csi_rs_pdu.csi_rs_pdu_rel13, ppWritePackedMsg, end, &pack_dl_config_csi_rs_pdu_rel13_value))) - return 0; - } - break; - case NFAPI_DL_CONFIG_EPDCCH_DL_PDU_TYPE: - { - if(!(pack_tlv(NFAPI_DL_CONFIG_REQUEST_EPDCCH_PDU_REL8_TAG, &pdu->epdcch_pdu.epdcch_pdu_rel8, ppWritePackedMsg, end, &pack_dl_config_dci_dl_pdu_rel8_value) && - pack_tlv(NFAPI_DL_CONFIG_REQUEST_EPDCCH_PDU_REL9_TAG, &pdu->epdcch_pdu.epdcch_pdu_rel9, ppWritePackedMsg, end, &pack_dl_config_dci_dl_pdu_rel9_value) && - pack_tlv(NFAPI_DL_CONFIG_REQUEST_EPDCCH_PDU_REL10_TAG, &pdu->epdcch_pdu.epdcch_pdu_rel10, ppWritePackedMsg, end, &pack_dl_config_dci_dl_pdu_rel10_value) && - pack_tlv(NFAPI_DL_CONFIG_REQUEST_EPDCCH_PDU_REL11_TAG, &pdu->epdcch_pdu.epdcch_pdu_rel11, ppWritePackedMsg, end, &pack_dl_config_dci_dl_pdu_rel11_value) && - pack_tlv(NFAPI_DL_CONFIG_REQUEST_EPDCCH_PDU_REL12_TAG, &pdu->epdcch_pdu.epdcch_pdu_rel12, ppWritePackedMsg, end, &pack_dl_config_dci_dl_pdu_rel12_value) && - pack_tlv(NFAPI_DL_CONFIG_REQUEST_EPDCCH_PDU_REL13_TAG, &pdu->epdcch_pdu.epdcch_pdu_rel13, ppWritePackedMsg, end, &pack_dl_config_dci_dl_pdu_rel13_value) && - pack_tlv(NFAPI_DL_CONFIG_REQUEST_EPDCCH_PARAM_REL11_TAG, &pdu->epdcch_pdu.epdcch_params_rel11, ppWritePackedMsg, end, &pack_dl_config_epdcch_parameters_rel11_value) & - pack_tlv(NFAPI_DL_CONFIG_REQUEST_EPDCCH_PARAM_REL13_TAG, &pdu->epdcch_pdu.epdcch_params_rel13, ppWritePackedMsg, end, &pack_dl_config_epdcch_parameters_rel13_value))) - return 0; - } - break; - case NFAPI_DL_CONFIG_MPDCCH_PDU_TYPE: - { - if(!(pack_tlv(NFAPI_DL_CONFIG_REQUEST_MPDCCH_PDU_REL13_TAG, &pdu->mpdcch_pdu.mpdcch_pdu_rel13, ppWritePackedMsg, end, &pack_dl_config_mpdcch_pdu_rel13_value))) - return 0; - } - break; - case NFAPI_DL_CONFIG_NBCH_PDU_TYPE: - { - if(!(pack_tlv(NFAPI_DL_CONFIG_REQUEST_NBCH_PDU_REL13_TAG, &pdu->nbch_pdu.nbch_pdu_rel13, ppWritePackedMsg, end, &pack_dl_config_nbch_pdu_rel13_value))) - return 0; - } - break; - case NFAPI_DL_CONFIG_NPDCCH_PDU_TYPE: - { - if(!(pack_tlv(NFAPI_DL_CONFIG_REQUEST_NPDCCH_PDU_REL13_TAG, &pdu->npdcch_pdu.npdcch_pdu_rel13, ppWritePackedMsg, end, &pack_dl_config_npdcch_pdu_rel13_value))) - return 0; - } - break; - case NFAPI_DL_CONFIG_NDLSCH_PDU_TYPE: - { - if(!(pack_tlv(NFAPI_DL_CONFIG_REQUEST_NDLSCH_PDU_REL13_TAG, &pdu->ndlsch_pdu.ndlsch_pdu_rel13, ppWritePackedMsg, end, &pack_dl_config_ndlsch_pdu_rel13_value))) - return 0; - } - break; - default: - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "FIXME : Invalid pdu type %d \n", pdu->pdu_type ); - } - break; - }; - - // add 1 for the pdu_type. The delta will include the pdu_size - pdu->pdu_size = 1 + (*ppWritePackedMsg - pWritePackedMsgPduSize); - push8(pdu->pdu_size, &pWritePackedMsgPduSize, end); - } - - return 1; -} - - -static uint8_t pack_dl_tti_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) -{ - nfapi_nr_dl_tti_request_t *pNfapiMsg = (nfapi_nr_dl_tti_request_t*)msg; - - if (!(push16(pNfapiMsg->SFN , ppWritePackedMsg, end) && - push16(pNfapiMsg->Slot , ppWritePackedMsg, end) && - push8(pNfapiMsg->dl_tti_request_body.nGroup , ppWritePackedMsg, end) && - push8(pNfapiMsg->dl_tti_request_body.nPDUs , ppWritePackedMsg, end) && - pusharray8(pNfapiMsg->dl_tti_request_body.nUe ,256,pNfapiMsg->dl_tti_request_body.nGroup, ppWritePackedMsg, end) - //pusharray8(pNfapiMsg->PduIdx[0] ,256,256, ppWritePackedMsg, end) - )) - return 0; - - int arr[12]; - for(int i=0;idl_tti_request_body.nGroup;i++) - { - for(int j=0;jdl_tti_request_body.nUe[i];j++) - { - arr[j] = pNfapiMsg->dl_tti_request_body.PduIdx[i][j]; - } - if(!(pusharrays32(arr,12,pNfapiMsg->dl_tti_request_body.nUe[i],ppWritePackedMsg, end))) - return 0; - } - - for(int i=0;idl_tti_request_body.nPDUs;i++) - { - if(!pack_dl_tti_request_body_value(&pNfapiMsg->dl_tti_request_body.dl_tti_pdu_list[i],ppWritePackedMsg,end)) - return 0; - } - -return 1; -} - - -static uint8_t pack_dl_config_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) -{ - nfapi_dl_config_request_t *pNfapiMsg = (nfapi_dl_config_request_t*)msg; - - //return ( push16(pNfapiMsg->sfn_sf, ppWritePackedMsg, end) && - //pack_tlv(NFAPI_DL_CONFIG_REQUEST_BODY_TAG, &pNfapiMsg->dl_config_request_body, ppWritePackedMsg, end, &pack_dl_config_request_body_value) && - //pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); - { - uint8_t x = push16(pNfapiMsg->sfn_sf, ppWritePackedMsg, end); - uint8_t y = pack_tlv(NFAPI_DL_CONFIG_REQUEST_BODY_TAG, &pNfapiMsg->dl_config_request_body, ppWritePackedMsg, end, &pack_dl_config_request_body_value); - uint8_t z = pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config); - - if (!x || !y || !z) - { - NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() NFAPI_DL_CONFIG_REQUEST x:%u y:%u z:%u \n", __FUNCTION__,x,y,z); - } - - return x && y && z; + switch(pdu->pdu_type) { + case NFAPI_DL_CONFIG_DCI_DL_PDU_TYPE: { + //NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s() NFAPI_DL_CONFIG_DCI_DL_PDU_TYPE\n", __FUNCTION__); + if(!(pack_tlv(NFAPI_DL_CONFIG_REQUEST_DCI_DL_PDU_REL8_TAG, &pdu->dci_dl_pdu.dci_dl_pdu_rel8, ppWritePackedMsg, end, &pack_dl_config_dci_dl_pdu_rel8_value) && + pack_tlv(NFAPI_DL_CONFIG_REQUEST_DCI_DL_PDU_REL9_TAG, &pdu->dci_dl_pdu.dci_dl_pdu_rel9, ppWritePackedMsg, end, &pack_dl_config_dci_dl_pdu_rel9_value) && + pack_tlv(NFAPI_DL_CONFIG_REQUEST_DCI_DL_PDU_REL10_TAG, &pdu->dci_dl_pdu.dci_dl_pdu_rel10, ppWritePackedMsg, end, &pack_dl_config_dci_dl_pdu_rel10_value) && + pack_tlv(NFAPI_DL_CONFIG_REQUEST_DCI_DL_PDU_REL11_TAG, &pdu->dci_dl_pdu.dci_dl_pdu_rel11, ppWritePackedMsg, end, &pack_dl_config_dci_dl_pdu_rel11_value) && + pack_tlv(NFAPI_DL_CONFIG_REQUEST_DCI_DL_PDU_REL12_TAG, &pdu->dci_dl_pdu.dci_dl_pdu_rel12, ppWritePackedMsg, end, &pack_dl_config_dci_dl_pdu_rel12_value) && + pack_tlv(NFAPI_DL_CONFIG_REQUEST_DCI_DL_PDU_REL13_TAG, &pdu->dci_dl_pdu.dci_dl_pdu_rel13, ppWritePackedMsg, end, &pack_dl_config_dci_dl_pdu_rel13_value))) { + return 0; } + } + break; + + case NFAPI_DL_CONFIG_BCH_PDU_TYPE: { + //NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s() NFAPI_DL_CONFIG_BCH_PDU_TYPE\n", __FUNCTION__); + if(!(pack_tlv(NFAPI_DL_CONFIG_REQUEST_BCH_PDU_REL8_TAG, &pdu->bch_pdu.bch_pdu_rel8, ppWritePackedMsg, end, &pack_dl_config_bch_pdu_rel8_value))) + return 0; + } + break; + + case NFAPI_DL_CONFIG_MCH_PDU_TYPE: { + if(!(pack_tlv(NFAPI_DL_CONFIG_REQUEST_MCH_PDU_REL8_TAG, &pdu->mch_pdu.mch_pdu_rel8, ppWritePackedMsg, end, &pack_dl_config_mch_pdu_rel8_value))) + return 0; + } + break; + + case NFAPI_DL_CONFIG_DLSCH_PDU_TYPE: { + if(!(pack_tlv(NFAPI_DL_CONFIG_REQUEST_DLSCH_PDU_REL8_TAG, &pdu->dlsch_pdu.dlsch_pdu_rel8, ppWritePackedMsg, end, &pack_dl_config_dlsch_pdu_rel8_value) && + pack_tlv(NFAPI_DL_CONFIG_REQUEST_DLSCH_PDU_REL9_TAG, &pdu->dlsch_pdu.dlsch_pdu_rel9, ppWritePackedMsg, end, &pack_dl_config_dlsch_pdu_rel9_value) && + pack_tlv(NFAPI_DL_CONFIG_REQUEST_DLSCH_PDU_REL10_TAG, &pdu->dlsch_pdu.dlsch_pdu_rel10, ppWritePackedMsg, end, &pack_dl_config_dlsch_pdu_rel10_value) && + pack_tlv(NFAPI_DL_CONFIG_REQUEST_DLSCH_PDU_REL11_TAG, &pdu->dlsch_pdu.dlsch_pdu_rel11, ppWritePackedMsg, end, &pack_dl_config_dlsch_pdu_rel11_value) && + pack_tlv(NFAPI_DL_CONFIG_REQUEST_DLSCH_PDU_REL12_TAG, &pdu->dlsch_pdu.dlsch_pdu_rel12, ppWritePackedMsg, end, &pack_dl_config_dlsch_pdu_rel12_value) && + pack_tlv(NFAPI_DL_CONFIG_REQUEST_DLSCH_PDU_REL13_TAG, &pdu->dlsch_pdu.dlsch_pdu_rel13, ppWritePackedMsg, end, &pack_dl_config_dlsch_pdu_rel13_value))) + return 0; + } + break; + + case NFAPI_DL_CONFIG_PCH_PDU_TYPE: { + if(!(pack_tlv(NFAPI_DL_CONFIG_REQUEST_PCH_PDU_REL8_TAG, &pdu->pch_pdu.pch_pdu_rel8, ppWritePackedMsg, end, &pack_dl_config_pch_pdu_rel8_value) && + pack_tlv(NFAPI_DL_CONFIG_REQUEST_PCH_PDU_REL13_TAG, &pdu->pch_pdu.pch_pdu_rel13, ppWritePackedMsg, end, &pack_dl_config_pch_pdu_rel13_value))) + return 0; + } + break; + + case NFAPI_DL_CONFIG_PRS_PDU_TYPE: { + if(!(pack_tlv(NFAPI_DL_CONFIG_REQUEST_PRS_PDU_REL9_TAG, &pdu->prs_pdu.prs_pdu_rel9, ppWritePackedMsg, end, &pack_dl_config_prs_pdu_rel9_value))) + return 0; + } + break; + + case NFAPI_DL_CONFIG_CSI_RS_PDU_TYPE: { + if(!(pack_tlv(NFAPI_DL_CONFIG_REQUEST_CSI_RS_PDU_REL10_TAG, &pdu->csi_rs_pdu.csi_rs_pdu_rel10, ppWritePackedMsg, end, &pack_dl_config_csi_rs_pdu_rel10_value) && + pack_tlv(NFAPI_DL_CONFIG_REQUEST_CSI_RS_PDU_REL13_TAG, &pdu->csi_rs_pdu.csi_rs_pdu_rel13, ppWritePackedMsg, end, &pack_dl_config_csi_rs_pdu_rel13_value))) + return 0; + } + break; + + case NFAPI_DL_CONFIG_EPDCCH_DL_PDU_TYPE: { + if(!(pack_tlv(NFAPI_DL_CONFIG_REQUEST_EPDCCH_PDU_REL8_TAG, &pdu->epdcch_pdu.epdcch_pdu_rel8, ppWritePackedMsg, end, &pack_dl_config_dci_dl_pdu_rel8_value) && + pack_tlv(NFAPI_DL_CONFIG_REQUEST_EPDCCH_PDU_REL9_TAG, &pdu->epdcch_pdu.epdcch_pdu_rel9, ppWritePackedMsg, end, &pack_dl_config_dci_dl_pdu_rel9_value) && + pack_tlv(NFAPI_DL_CONFIG_REQUEST_EPDCCH_PDU_REL10_TAG, &pdu->epdcch_pdu.epdcch_pdu_rel10, ppWritePackedMsg, end, &pack_dl_config_dci_dl_pdu_rel10_value) && + pack_tlv(NFAPI_DL_CONFIG_REQUEST_EPDCCH_PDU_REL11_TAG, &pdu->epdcch_pdu.epdcch_pdu_rel11, ppWritePackedMsg, end, &pack_dl_config_dci_dl_pdu_rel11_value) && + pack_tlv(NFAPI_DL_CONFIG_REQUEST_EPDCCH_PDU_REL12_TAG, &pdu->epdcch_pdu.epdcch_pdu_rel12, ppWritePackedMsg, end, &pack_dl_config_dci_dl_pdu_rel12_value) && + pack_tlv(NFAPI_DL_CONFIG_REQUEST_EPDCCH_PDU_REL13_TAG, &pdu->epdcch_pdu.epdcch_pdu_rel13, ppWritePackedMsg, end, &pack_dl_config_dci_dl_pdu_rel13_value) && + pack_tlv(NFAPI_DL_CONFIG_REQUEST_EPDCCH_PARAM_REL11_TAG, &pdu->epdcch_pdu.epdcch_params_rel11, ppWritePackedMsg, end, &pack_dl_config_epdcch_parameters_rel11_value) & + pack_tlv(NFAPI_DL_CONFIG_REQUEST_EPDCCH_PARAM_REL13_TAG, &pdu->epdcch_pdu.epdcch_params_rel13, ppWritePackedMsg, end, &pack_dl_config_epdcch_parameters_rel13_value))) + return 0; + } + break; + + case NFAPI_DL_CONFIG_MPDCCH_PDU_TYPE: { + if(!(pack_tlv(NFAPI_DL_CONFIG_REQUEST_MPDCCH_PDU_REL13_TAG, &pdu->mpdcch_pdu.mpdcch_pdu_rel13, ppWritePackedMsg, end, &pack_dl_config_mpdcch_pdu_rel13_value))) + return 0; + } + break; + + case NFAPI_DL_CONFIG_NBCH_PDU_TYPE: { + if(!(pack_tlv(NFAPI_DL_CONFIG_REQUEST_NBCH_PDU_REL13_TAG, &pdu->nbch_pdu.nbch_pdu_rel13, ppWritePackedMsg, end, &pack_dl_config_nbch_pdu_rel13_value))) + return 0; + } + break; + + case NFAPI_DL_CONFIG_NPDCCH_PDU_TYPE: { + if(!(pack_tlv(NFAPI_DL_CONFIG_REQUEST_NPDCCH_PDU_REL13_TAG, &pdu->npdcch_pdu.npdcch_pdu_rel13, ppWritePackedMsg, end, &pack_dl_config_npdcch_pdu_rel13_value))) + return 0; + } + break; + + case NFAPI_DL_CONFIG_NDLSCH_PDU_TYPE: { + if(!(pack_tlv(NFAPI_DL_CONFIG_REQUEST_NDLSCH_PDU_REL13_TAG, &pdu->ndlsch_pdu.ndlsch_pdu_rel13, ppWritePackedMsg, end, &pack_dl_config_ndlsch_pdu_rel13_value))) + return 0; + } + break; + + default: { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "FIXME : Invalid pdu type %d \n", pdu->pdu_type ); + } + break; + }; + + // add 1 for the pdu_type. The delta will include the pdu_size + pdu->pdu_size = 1 + (*ppWritePackedMsg - pWritePackedMsgPduSize); + + push8(pdu->pdu_size, &pWritePackedMsgPduSize, end); + } + + return 1; +} + + +static uint8_t pack_dl_tti_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t *config) { + nfapi_nr_dl_tti_request_t *pNfapiMsg = (nfapi_nr_dl_tti_request_t *)msg; + + if (!(push16(pNfapiMsg->SFN, ppWritePackedMsg, end) && + push16(pNfapiMsg->Slot, ppWritePackedMsg, end) && + push8(pNfapiMsg->dl_tti_request_body.nGroup, ppWritePackedMsg, end) && + push8(pNfapiMsg->dl_tti_request_body.nPDUs, ppWritePackedMsg, end) && + pusharray8(pNfapiMsg->dl_tti_request_body.nUe,256,pNfapiMsg->dl_tti_request_body.nGroup, ppWritePackedMsg, end) + //pusharray8(pNfapiMsg->PduIdx[0] ,256,256, ppWritePackedMsg, end) + )) + return 0; + + int arr[12]; + + for(int i=0; idl_tti_request_body.nGroup; i++) { + for(int j=0; jdl_tti_request_body.nUe[i]; j++) { + arr[j] = pNfapiMsg->dl_tti_request_body.PduIdx[i][j]; + } + + if(!(pusharrays32(arr,12,pNfapiMsg->dl_tti_request_body.nUe[i],ppWritePackedMsg, end))) + return 0; + } + + for(int i=0; idl_tti_request_body.nPDUs; i++) { + if(!pack_dl_tti_request_body_value(&pNfapiMsg->dl_tti_request_body.dl_tti_pdu_list[i],ppWritePackedMsg,end)) + return 0; + } + + return 1; +} + + +static uint8_t pack_dl_config_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t *config) { + nfapi_dl_config_request_t *pNfapiMsg = (nfapi_dl_config_request_t *)msg; + //return ( push16(pNfapiMsg->sfn_sf, ppWritePackedMsg, end) && + //pack_tlv(NFAPI_DL_CONFIG_REQUEST_BODY_TAG, &pNfapiMsg->dl_config_request_body, ppWritePackedMsg, end, &pack_dl_config_request_body_value) && + //pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); + { + uint8_t x = push16(pNfapiMsg->sfn_sf, ppWritePackedMsg, end); + uint8_t y = pack_tlv(NFAPI_DL_CONFIG_REQUEST_BODY_TAG, &pNfapiMsg->dl_config_request_body, ppWritePackedMsg, end, &pack_dl_config_request_body_value); + uint8_t z = pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config); + + if (!x || !y || !z) { + NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() NFAPI_DL_CONFIG_REQUEST x:%u y:%u z:%u \n", __FUNCTION__,x,y,z); + } + + return x && y && z; + } } -static uint8_t pack_ul_config_request_ulsch_rel8_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t * end) -{ - nfapi_ul_config_ulsch_pdu_rel8_t* ulsch_pdu_rel8 = (nfapi_ul_config_ulsch_pdu_rel8_t*)tlv; - - return( push32(ulsch_pdu_rel8->handle, ppWritePackedMsg, end) && - push16(ulsch_pdu_rel8->size, ppWritePackedMsg, end) && - push16(ulsch_pdu_rel8->rnti, ppWritePackedMsg, end) && - push8(ulsch_pdu_rel8->resource_block_start, ppWritePackedMsg, end) && - push8(ulsch_pdu_rel8->number_of_resource_blocks, ppWritePackedMsg, end) && - push8(ulsch_pdu_rel8->modulation_type, ppWritePackedMsg, end) && - push8(ulsch_pdu_rel8->cyclic_shift_2_for_drms, ppWritePackedMsg, end) && - push8(ulsch_pdu_rel8->frequency_hopping_enabled_flag, ppWritePackedMsg, end) && - push8(ulsch_pdu_rel8->frequency_hopping_bits, ppWritePackedMsg, end) && - push8(ulsch_pdu_rel8->new_data_indication, ppWritePackedMsg, end) && - push8(ulsch_pdu_rel8->redundancy_version, ppWritePackedMsg, end) && - push8(ulsch_pdu_rel8->harq_process_number, ppWritePackedMsg, end) && - push8(ulsch_pdu_rel8->ul_tx_mode, ppWritePackedMsg, end) && - push8(ulsch_pdu_rel8->current_tx_nb, ppWritePackedMsg, end) && - push8(ulsch_pdu_rel8->n_srs, ppWritePackedMsg, end)); +static uint8_t pack_ul_config_request_ulsch_rel8_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_ul_config_ulsch_pdu_rel8_t *ulsch_pdu_rel8 = (nfapi_ul_config_ulsch_pdu_rel8_t *)tlv; + return( push32(ulsch_pdu_rel8->handle, ppWritePackedMsg, end) && + push16(ulsch_pdu_rel8->size, ppWritePackedMsg, end) && + push16(ulsch_pdu_rel8->rnti, ppWritePackedMsg, end) && + push8(ulsch_pdu_rel8->resource_block_start, ppWritePackedMsg, end) && + push8(ulsch_pdu_rel8->number_of_resource_blocks, ppWritePackedMsg, end) && + push8(ulsch_pdu_rel8->modulation_type, ppWritePackedMsg, end) && + push8(ulsch_pdu_rel8->cyclic_shift_2_for_drms, ppWritePackedMsg, end) && + push8(ulsch_pdu_rel8->frequency_hopping_enabled_flag, ppWritePackedMsg, end) && + push8(ulsch_pdu_rel8->frequency_hopping_bits, ppWritePackedMsg, end) && + push8(ulsch_pdu_rel8->new_data_indication, ppWritePackedMsg, end) && + push8(ulsch_pdu_rel8->redundancy_version, ppWritePackedMsg, end) && + push8(ulsch_pdu_rel8->harq_process_number, ppWritePackedMsg, end) && + push8(ulsch_pdu_rel8->ul_tx_mode, ppWritePackedMsg, end) && + push8(ulsch_pdu_rel8->current_tx_nb, ppWritePackedMsg, end) && + push8(ulsch_pdu_rel8->n_srs, ppWritePackedMsg, end)); } -static uint8_t pack_ul_config_request_ulsch_rel10_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_ul_config_ulsch_pdu_rel10_t* ulsch_pdu_rel10 = (nfapi_ul_config_ulsch_pdu_rel10_t*)tlv; - - return (push8(ulsch_pdu_rel10->resource_allocation_type, ppWritePackedMsg, end) && - push32(ulsch_pdu_rel10->resource_block_coding, ppWritePackedMsg, end) && - push8(ulsch_pdu_rel10->transport_blocks, ppWritePackedMsg, end) && - push8(ulsch_pdu_rel10->transmission_scheme, ppWritePackedMsg, end) && - push8(ulsch_pdu_rel10->number_of_layers, ppWritePackedMsg, end) && - push8(ulsch_pdu_rel10->codebook_index, ppWritePackedMsg, end) && - push8(ulsch_pdu_rel10->disable_sequence_hopping_flag, ppWritePackedMsg, end)); +static uint8_t pack_ul_config_request_ulsch_rel10_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_ul_config_ulsch_pdu_rel10_t *ulsch_pdu_rel10 = (nfapi_ul_config_ulsch_pdu_rel10_t *)tlv; + return (push8(ulsch_pdu_rel10->resource_allocation_type, ppWritePackedMsg, end) && + push32(ulsch_pdu_rel10->resource_block_coding, ppWritePackedMsg, end) && + push8(ulsch_pdu_rel10->transport_blocks, ppWritePackedMsg, end) && + push8(ulsch_pdu_rel10->transmission_scheme, ppWritePackedMsg, end) && + push8(ulsch_pdu_rel10->number_of_layers, ppWritePackedMsg, end) && + push8(ulsch_pdu_rel10->codebook_index, ppWritePackedMsg, end) && + push8(ulsch_pdu_rel10->disable_sequence_hopping_flag, ppWritePackedMsg, end)); } -static uint8_t pack_ul_config_request_ulsch_rel11_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_ul_config_ulsch_pdu_rel11_t* ulsch_pdu_rel11 = (nfapi_ul_config_ulsch_pdu_rel11_t*)tlv; - - return (push8(ulsch_pdu_rel11->virtual_cell_id_enabled_flag, ppWritePackedMsg, end) && - push16(ulsch_pdu_rel11->npusch_identity, ppWritePackedMsg, end) && - push8(ulsch_pdu_rel11->dmrs_config_flag, ppWritePackedMsg, end) && - push16(ulsch_pdu_rel11->ndmrs_csh_identity, ppWritePackedMsg, end)); +static uint8_t pack_ul_config_request_ulsch_rel11_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_ul_config_ulsch_pdu_rel11_t *ulsch_pdu_rel11 = (nfapi_ul_config_ulsch_pdu_rel11_t *)tlv; + return (push8(ulsch_pdu_rel11->virtual_cell_id_enabled_flag, ppWritePackedMsg, end) && + push16(ulsch_pdu_rel11->npusch_identity, ppWritePackedMsg, end) && + push8(ulsch_pdu_rel11->dmrs_config_flag, ppWritePackedMsg, end) && + push16(ulsch_pdu_rel11->ndmrs_csh_identity, ppWritePackedMsg, end)); } -static uint8_t pack_ul_config_request_ulsch_rel13_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_ul_config_ulsch_pdu_rel13_t* ulsch_pdu_rel13 = (nfapi_ul_config_ulsch_pdu_rel13_t*)tlv; - - return (push8(ulsch_pdu_rel13->ue_type, ppWritePackedMsg, end) && - push16(ulsch_pdu_rel13->total_number_of_repetitions, ppWritePackedMsg, end) && - push16(ulsch_pdu_rel13->repetition_number, ppWritePackedMsg, end) && - push16(ulsch_pdu_rel13->initial_transmission_sf_io, ppWritePackedMsg, end) && - push8(ulsch_pdu_rel13->empty_symbols_due_to_re_tunning, ppWritePackedMsg, end)); +static uint8_t pack_ul_config_request_ulsch_rel13_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_ul_config_ulsch_pdu_rel13_t *ulsch_pdu_rel13 = (nfapi_ul_config_ulsch_pdu_rel13_t *)tlv; + return (push8(ulsch_pdu_rel13->ue_type, ppWritePackedMsg, end) && + push16(ulsch_pdu_rel13->total_number_of_repetitions, ppWritePackedMsg, end) && + push16(ulsch_pdu_rel13->repetition_number, ppWritePackedMsg, end) && + push16(ulsch_pdu_rel13->initial_transmission_sf_io, ppWritePackedMsg, end) && + push8(ulsch_pdu_rel13->empty_symbols_due_to_re_tunning, ppWritePackedMsg, end)); } //Pack fns for ul_tti PDUS -static uint8_t pack_ul_tti_request_prach_pdu(nfapi_nr_prach_pdu_t* prach_pdu, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - return( - push16(prach_pdu->phys_cell_id, ppWritePackedMsg, end) && - push8(prach_pdu->num_prach_ocas, ppWritePackedMsg, end) && - push8(prach_pdu->prach_format, ppWritePackedMsg, end) && - push8(prach_pdu->num_ra, ppWritePackedMsg, end) && - push8(prach_pdu->prach_start_symbol, ppWritePackedMsg, end) && - push16(prach_pdu->num_cs, ppWritePackedMsg, end) - // TODO: ignoring beamforming tlv for now - ); - +static uint8_t pack_ul_tti_request_prach_pdu(nfapi_nr_prach_pdu_t *prach_pdu, uint8_t **ppWritePackedMsg, uint8_t *end) { + return( + push16(prach_pdu->phys_cell_id, ppWritePackedMsg, end) && + push8(prach_pdu->num_prach_ocas, ppWritePackedMsg, end) && + push8(prach_pdu->prach_format, ppWritePackedMsg, end) && + push8(prach_pdu->num_ra, ppWritePackedMsg, end) && + push8(prach_pdu->prach_start_symbol, ppWritePackedMsg, end) && + push16(prach_pdu->num_cs, ppWritePackedMsg, end) + // TODO: ignoring beamforming tlv for now + ); } -static uint8_t pack_ul_tti_request_pucch_pdu(nfapi_nr_pucch_pdu_t* pucch_pdu, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - return( - push16(pucch_pdu->rnti, ppWritePackedMsg, end) && - push32(pucch_pdu->handle, ppWritePackedMsg, end) && - push16(pucch_pdu->bwp_size, ppWritePackedMsg, end) && - push16(pucch_pdu->bwp_start, ppWritePackedMsg, end) && - push8(pucch_pdu->subcarrier_spacing, ppWritePackedMsg, end) && - push8(pucch_pdu->cyclic_prefix, ppWritePackedMsg, end) && - push8(pucch_pdu->format_type, ppWritePackedMsg, end) && - push8(pucch_pdu->multi_slot_tx_indicator, ppWritePackedMsg, end) && - push16(pucch_pdu->prb_start, ppWritePackedMsg, end) && - push16(pucch_pdu->prb_size, ppWritePackedMsg, end) && - push8(pucch_pdu->start_symbol_index, ppWritePackedMsg, end) && - push8(pucch_pdu->nr_of_symbols, ppWritePackedMsg, end) && - push8(pucch_pdu->freq_hop_flag, ppWritePackedMsg, end) && - push16(pucch_pdu->second_hop_prb, ppWritePackedMsg, end) && - push8(pucch_pdu->group_hop_flag, ppWritePackedMsg, end) && - push8(pucch_pdu->sequence_hop_flag, ppWritePackedMsg, end) && - push16(pucch_pdu->hopping_id, ppWritePackedMsg, end) && - push16(pucch_pdu->initial_cyclic_shift, ppWritePackedMsg, end) && - push16(pucch_pdu->data_scrambling_id, ppWritePackedMsg, end) && - push8(pucch_pdu->time_domain_occ_idx, ppWritePackedMsg, end) && - push8(pucch_pdu->pre_dft_occ_idx, ppWritePackedMsg, end) && - push8(pucch_pdu->pre_dft_occ_len, ppWritePackedMsg, end) && - push8(pucch_pdu->add_dmrs_flag, ppWritePackedMsg, end) && - push16(pucch_pdu->dmrs_scrambling_id, ppWritePackedMsg, end) && - push8(pucch_pdu->dmrs_cyclic_shift, ppWritePackedMsg, end) && - push8(pucch_pdu->sr_flag, ppWritePackedMsg, end) && - push8(pucch_pdu->bit_len_harq, ppWritePackedMsg, end) && - push16(pucch_pdu->bit_len_csi_part1, ppWritePackedMsg, end) && - push16(pucch_pdu->bit_len_csi_part2, ppWritePackedMsg, end) - // TODO: ignoring beamforming tlv for now - ); - +static uint8_t pack_ul_tti_request_pucch_pdu(nfapi_nr_pucch_pdu_t *pucch_pdu, uint8_t **ppWritePackedMsg, uint8_t *end) { + return( + push16(pucch_pdu->rnti, ppWritePackedMsg, end) && + push32(pucch_pdu->handle, ppWritePackedMsg, end) && + push16(pucch_pdu->bwp_size, ppWritePackedMsg, end) && + push16(pucch_pdu->bwp_start, ppWritePackedMsg, end) && + push8(pucch_pdu->subcarrier_spacing, ppWritePackedMsg, end) && + push8(pucch_pdu->cyclic_prefix, ppWritePackedMsg, end) && + push8(pucch_pdu->format_type, ppWritePackedMsg, end) && + push8(pucch_pdu->multi_slot_tx_indicator, ppWritePackedMsg, end) && + push16(pucch_pdu->prb_start, ppWritePackedMsg, end) && + push16(pucch_pdu->prb_size, ppWritePackedMsg, end) && + push8(pucch_pdu->start_symbol_index, ppWritePackedMsg, end) && + push8(pucch_pdu->nr_of_symbols, ppWritePackedMsg, end) && + push8(pucch_pdu->freq_hop_flag, ppWritePackedMsg, end) && + push16(pucch_pdu->second_hop_prb, ppWritePackedMsg, end) && + push8(pucch_pdu->group_hop_flag, ppWritePackedMsg, end) && + push8(pucch_pdu->sequence_hop_flag, ppWritePackedMsg, end) && + push16(pucch_pdu->hopping_id, ppWritePackedMsg, end) && + push16(pucch_pdu->initial_cyclic_shift, ppWritePackedMsg, end) && + push16(pucch_pdu->data_scrambling_id, ppWritePackedMsg, end) && + push8(pucch_pdu->time_domain_occ_idx, ppWritePackedMsg, end) && + push8(pucch_pdu->pre_dft_occ_idx, ppWritePackedMsg, end) && + push8(pucch_pdu->pre_dft_occ_len, ppWritePackedMsg, end) && + push8(pucch_pdu->add_dmrs_flag, ppWritePackedMsg, end) && + push16(pucch_pdu->dmrs_scrambling_id, ppWritePackedMsg, end) && + push8(pucch_pdu->dmrs_cyclic_shift, ppWritePackedMsg, end) && + push8(pucch_pdu->sr_flag, ppWritePackedMsg, end) && + push8(pucch_pdu->bit_len_harq, ppWritePackedMsg, end) && + push16(pucch_pdu->bit_len_csi_part1, ppWritePackedMsg, end) && + push16(pucch_pdu->bit_len_csi_part2, ppWritePackedMsg, end) + // TODO: ignoring beamforming tlv for now + ); } -static uint8_t pack_ul_tti_request_pusch_pdu(nfapi_nr_pusch_pdu_t* pusch_pdu, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - - if (!( - push16(pusch_pdu->pdu_bit_map, ppWritePackedMsg, end) && - push16(pusch_pdu->rnti, ppWritePackedMsg, end) && - push32(pusch_pdu->handle, ppWritePackedMsg, end) && - push16(pusch_pdu->bwp_size, ppWritePackedMsg, end) && - push16(pusch_pdu->bwp_start, ppWritePackedMsg, end) && - push8(pusch_pdu->subcarrier_spacing, ppWritePackedMsg, end) && - push8(pusch_pdu->cyclic_prefix, ppWritePackedMsg, end) && - push16(pusch_pdu->target_code_rate, ppWritePackedMsg, end) && - push8(pusch_pdu->qam_mod_order, ppWritePackedMsg, end) && - push8(pusch_pdu->mcs_index, ppWritePackedMsg, end) && - push8(pusch_pdu->mcs_table, ppWritePackedMsg, end) && - push8(pusch_pdu->transform_precoding, ppWritePackedMsg, end) && - push16(pusch_pdu->data_scrambling_id, ppWritePackedMsg, end) && - push8(pusch_pdu->nrOfLayers, ppWritePackedMsg, end) && - push16(pusch_pdu->ul_dmrs_symb_pos, ppWritePackedMsg, end) && - push8(pusch_pdu->dmrs_config_type, ppWritePackedMsg, end) && - push16(pusch_pdu->ul_dmrs_scrambling_id, ppWritePackedMsg, end) && - push8(pusch_pdu->scid, ppWritePackedMsg, end) && - push8(pusch_pdu->num_dmrs_cdm_grps_no_data, ppWritePackedMsg, end) && - push16(pusch_pdu->dmrs_ports, ppWritePackedMsg, end) && - push8(pusch_pdu->resource_alloc, ppWritePackedMsg, end) && - push8(pusch_pdu->resource_alloc,ppWritePackedMsg, end) && - push16(pusch_pdu->dmrs_ports, ppWritePackedMsg, end) && - push16(pusch_pdu->rb_start, ppWritePackedMsg, end) && - push16(pusch_pdu->rb_size, ppWritePackedMsg, end) && - push8(pusch_pdu->vrb_to_prb_mapping, ppWritePackedMsg, end) && - push8(pusch_pdu->frequency_hopping, ppWritePackedMsg, end) && - push16(pusch_pdu->tx_direct_current_location, ppWritePackedMsg, end) && - push8(pusch_pdu->uplink_frequency_shift_7p5khz, ppWritePackedMsg, end) && - push8(pusch_pdu->start_symbol_index, ppWritePackedMsg, end) && - push8(pusch_pdu->nr_of_symbols, ppWritePackedMsg, end) - // TODO: ignoring beamforming tlv for now - )) - return 0; +static uint8_t pack_ul_tti_request_pusch_pdu(nfapi_nr_pusch_pdu_t *pusch_pdu, uint8_t **ppWritePackedMsg, uint8_t *end) { + if (!( + push16(pusch_pdu->pdu_bit_map, ppWritePackedMsg, end) && + push16(pusch_pdu->rnti, ppWritePackedMsg, end) && + push32(pusch_pdu->handle, ppWritePackedMsg, end) && + push16(pusch_pdu->bwp_size, ppWritePackedMsg, end) && + push16(pusch_pdu->bwp_start, ppWritePackedMsg, end) && + push8(pusch_pdu->subcarrier_spacing, ppWritePackedMsg, end) && + push8(pusch_pdu->cyclic_prefix, ppWritePackedMsg, end) && + push16(pusch_pdu->target_code_rate, ppWritePackedMsg, end) && + push8(pusch_pdu->qam_mod_order, ppWritePackedMsg, end) && + push8(pusch_pdu->mcs_index, ppWritePackedMsg, end) && + push8(pusch_pdu->mcs_table, ppWritePackedMsg, end) && + push8(pusch_pdu->transform_precoding, ppWritePackedMsg, end) && + push16(pusch_pdu->data_scrambling_id, ppWritePackedMsg, end) && + push8(pusch_pdu->nrOfLayers, ppWritePackedMsg, end) && + push16(pusch_pdu->ul_dmrs_symb_pos, ppWritePackedMsg, end) && + push8(pusch_pdu->dmrs_config_type, ppWritePackedMsg, end) && + push16(pusch_pdu->ul_dmrs_scrambling_id, ppWritePackedMsg, end) && + push8(pusch_pdu->scid, ppWritePackedMsg, end) && + push8(pusch_pdu->num_dmrs_cdm_grps_no_data, ppWritePackedMsg, end) && + push16(pusch_pdu->dmrs_ports, ppWritePackedMsg, end) && + push8(pusch_pdu->resource_alloc, ppWritePackedMsg, end) && + push8(pusch_pdu->resource_alloc,ppWritePackedMsg, end) && + push16(pusch_pdu->dmrs_ports, ppWritePackedMsg, end) && + push16(pusch_pdu->rb_start, ppWritePackedMsg, end) && + push16(pusch_pdu->rb_size, ppWritePackedMsg, end) && + push8(pusch_pdu->vrb_to_prb_mapping, ppWritePackedMsg, end) && + push8(pusch_pdu->frequency_hopping, ppWritePackedMsg, end) && + push16(pusch_pdu->tx_direct_current_location, ppWritePackedMsg, end) && + push8(pusch_pdu->uplink_frequency_shift_7p5khz, ppWritePackedMsg, end) && + push8(pusch_pdu->start_symbol_index, ppWritePackedMsg, end) && + push8(pusch_pdu->nr_of_symbols, ppWritePackedMsg, end) + // TODO: ignoring beamforming tlv for now + )) + return 0; + //Pack Optional Data only included if indicated in pduBitmap + switch(pusch_pdu->pdu_bit_map) { + case PUSCH_PDU_BITMAP_PUSCH_DATA: { + // pack optional TLVs + return( + push8(pusch_pdu->pusch_data.rv_index, ppWritePackedMsg, end) && + push8(pusch_pdu->pusch_data.harq_process_id, ppWritePackedMsg, end) && + push32(pusch_pdu->pusch_data.tb_size, ppWritePackedMsg, end) && + push16(pusch_pdu->pusch_data.num_cb, ppWritePackedMsg, end) && + pusharray8(pusch_pdu->pusch_data.cb_present_and_position,1,1,ppWritePackedMsg, end) + ); + } + break; - //Pack Optional Data only included if indicated in pduBitmap - switch(pusch_pdu->pdu_bit_map){ - case PUSCH_PDU_BITMAP_PUSCH_DATA: - { - // pack optional TLVs - return( - push8(pusch_pdu->pusch_data.rv_index, ppWritePackedMsg, end) && - push8(pusch_pdu->pusch_data.harq_process_id, ppWritePackedMsg, end) && - push32(pusch_pdu->pusch_data.tb_size, ppWritePackedMsg, end) && - push16(pusch_pdu->pusch_data.num_cb, ppWritePackedMsg, end) && - pusharray8(pusch_pdu->pusch_data.cb_present_and_position,1,1,ppWritePackedMsg, end) - ); - } - break; + case PUSCH_PDU_BITMAP_PUSCH_UCI: { + return( + push16(pusch_pdu->pusch_uci.harq_ack_bit_length, ppWritePackedMsg, end) && + push16(pusch_pdu->pusch_uci.csi_part1_bit_length, ppWritePackedMsg, end) && + push16(pusch_pdu->pusch_uci.csi_part2_bit_length, ppWritePackedMsg, end) && + push8(pusch_pdu->pusch_uci.alpha_scaling, ppWritePackedMsg, end) && + push8(pusch_pdu->pusch_uci.beta_offset_harq_ack, ppWritePackedMsg, end) && + push8(pusch_pdu->pusch_uci.beta_offset_csi1, ppWritePackedMsg, end) && + push8(pusch_pdu->pusch_uci.beta_offset_csi2, ppWritePackedMsg, end) + ); + } + break; - case PUSCH_PDU_BITMAP_PUSCH_UCI: - { - return( - push16(pusch_pdu->pusch_uci.harq_ack_bit_length, ppWritePackedMsg, end) && - push16(pusch_pdu->pusch_uci.csi_part1_bit_length, ppWritePackedMsg, end) && - push16(pusch_pdu->pusch_uci.csi_part2_bit_length, ppWritePackedMsg, end) && - push8(pusch_pdu->pusch_uci.alpha_scaling, ppWritePackedMsg, end) && - push8(pusch_pdu->pusch_uci.beta_offset_harq_ack, ppWritePackedMsg, end) && - push8(pusch_pdu->pusch_uci.beta_offset_csi1, ppWritePackedMsg, end) && - push8(pusch_pdu->pusch_uci.beta_offset_csi2, ppWritePackedMsg, end) - ); - } - break; + case PUSCH_PDU_BITMAP_PUSCH_PTRS: { + return( + push8(pusch_pdu->pusch_ptrs.num_ptrs_ports, ppWritePackedMsg, end) && + push8(pusch_pdu->pusch_ptrs.ptrs_ports_list->ptrs_dmrs_port, ppWritePackedMsg, end) && + push16(pusch_pdu->pusch_ptrs.ptrs_ports_list->ptrs_port_index, ppWritePackedMsg, end) && + push8(pusch_pdu->pusch_ptrs.ptrs_ports_list->ptrs_re_offset, ppWritePackedMsg, end) && + push8(pusch_pdu->pusch_ptrs.ptrs_time_density, ppWritePackedMsg, end) && + push8(pusch_pdu->pusch_ptrs.ptrs_freq_density, ppWritePackedMsg, end) && + push8(pusch_pdu->pusch_ptrs.ul_ptrs_power, ppWritePackedMsg, end) + ); + } + break; - case PUSCH_PDU_BITMAP_PUSCH_PTRS: - { - return( - push8(pusch_pdu->pusch_ptrs.num_ptrs_ports, ppWritePackedMsg, end) && - push8(pusch_pdu->pusch_ptrs.ptrs_ports_list->ptrs_dmrs_port, ppWritePackedMsg, end) && - push16(pusch_pdu->pusch_ptrs.ptrs_ports_list->ptrs_port_index, ppWritePackedMsg, end) && - push8(pusch_pdu->pusch_ptrs.ptrs_ports_list->ptrs_re_offset, ppWritePackedMsg, end) && - push8(pusch_pdu->pusch_ptrs.ptrs_time_density, ppWritePackedMsg, end) && - push8(pusch_pdu->pusch_ptrs.ptrs_freq_density, ppWritePackedMsg, end) && - push8(pusch_pdu->pusch_ptrs.ul_ptrs_power, ppWritePackedMsg, end) - ); - } - break; + case PUSCH_PDU_BITMAP_DFTS_OFDM: { + return( + push8(pusch_pdu->dfts_ofdm.low_papr_group_number, ppWritePackedMsg, end) && + push16(pusch_pdu->dfts_ofdm.low_papr_sequence_number, ppWritePackedMsg, end) && + push8(pusch_pdu->dfts_ofdm.ul_ptrs_sample_density, ppWritePackedMsg, end) && + push8(pusch_pdu->dfts_ofdm.ul_ptrs_time_density_transform_precoding, ppWritePackedMsg, end) + ); + } + break; - case PUSCH_PDU_BITMAP_DFTS_OFDM: - { - return( - push8(pusch_pdu->dfts_ofdm.low_papr_group_number, ppWritePackedMsg, end) && - push16(pusch_pdu->dfts_ofdm.low_papr_sequence_number, ppWritePackedMsg, end) && - push8(pusch_pdu->dfts_ofdm.ul_ptrs_sample_density, ppWritePackedMsg, end) && - push8(pusch_pdu->dfts_ofdm.ul_ptrs_time_density_transform_precoding, ppWritePackedMsg, end) - ); - } - break; + default: { + NFAPI_TRACE(NFAPI_TRACE_INFO, "Invalid pdu bitmap %d \n", pusch_pdu->pdu_bit_map ); + } + } - default: - { - NFAPI_TRACE(NFAPI_TRACE_INFO, "Invalid pdu bitmap %d \n", pusch_pdu->pdu_bit_map ); - } - } - - return 1; + return 1; } -static uint8_t pack_ul_tti_request_srs_pdu(nfapi_nr_srs_pdu_t* srs_pdu, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - return( - push16(srs_pdu->rnti, ppWritePackedMsg, end) && - push32(srs_pdu->handle, ppWritePackedMsg, end) && - push16(srs_pdu->bwp_size, ppWritePackedMsg, end) && - push16(srs_pdu->bwp_start, ppWritePackedMsg, end) && - push8(srs_pdu->subcarrier_spacing, ppWritePackedMsg, end) && - push8(srs_pdu->cyclic_prefix, ppWritePackedMsg, end) && - push8(srs_pdu->num_ant_ports, ppWritePackedMsg, end) && - push8(srs_pdu->num_symbols, ppWritePackedMsg, end) && - push8(srs_pdu->num_repetitions, ppWritePackedMsg, end) && - push8(srs_pdu->time_start_position, ppWritePackedMsg, end) && - push8(srs_pdu->config_index, ppWritePackedMsg, end) && - push16(srs_pdu->sequence_id, ppWritePackedMsg, end) && - push8(srs_pdu->bandwidth_index, ppWritePackedMsg, end) && - push8(srs_pdu->comb_size, ppWritePackedMsg, end) && - push8(srs_pdu->comb_offset, ppWritePackedMsg, end) && - push8(srs_pdu->cyclic_shift, ppWritePackedMsg, end) && - push8(srs_pdu->frequency_position, ppWritePackedMsg, end) && - push8(srs_pdu->frequency_shift, ppWritePackedMsg, end) && - push8(srs_pdu->frequency_hopping, ppWritePackedMsg, end) && - push8(srs_pdu->group_or_sequence_hopping, ppWritePackedMsg, end) && - push8(srs_pdu->resource_type, ppWritePackedMsg, end) && - push16(srs_pdu->t_srs, ppWritePackedMsg, end) && - push16(srs_pdu->t_offset, ppWritePackedMsg, end) - - // TODO: ignoring beamforming tlv for now - ); - +static uint8_t pack_ul_tti_request_srs_pdu(nfapi_nr_srs_pdu_t *srs_pdu, uint8_t **ppWritePackedMsg, uint8_t *end) { + return( + push16(srs_pdu->rnti, ppWritePackedMsg, end) && + push32(srs_pdu->handle, ppWritePackedMsg, end) && + push16(srs_pdu->bwp_size, ppWritePackedMsg, end) && + push16(srs_pdu->bwp_start, ppWritePackedMsg, end) && + push8(srs_pdu->subcarrier_spacing, ppWritePackedMsg, end) && + push8(srs_pdu->cyclic_prefix, ppWritePackedMsg, end) && + push8(srs_pdu->num_ant_ports, ppWritePackedMsg, end) && + push8(srs_pdu->num_symbols, ppWritePackedMsg, end) && + push8(srs_pdu->num_repetitions, ppWritePackedMsg, end) && + push8(srs_pdu->time_start_position, ppWritePackedMsg, end) && + push8(srs_pdu->config_index, ppWritePackedMsg, end) && + push16(srs_pdu->sequence_id, ppWritePackedMsg, end) && + push8(srs_pdu->bandwidth_index, ppWritePackedMsg, end) && + push8(srs_pdu->comb_size, ppWritePackedMsg, end) && + push8(srs_pdu->comb_offset, ppWritePackedMsg, end) && + push8(srs_pdu->cyclic_shift, ppWritePackedMsg, end) && + push8(srs_pdu->frequency_position, ppWritePackedMsg, end) && + push8(srs_pdu->frequency_shift, ppWritePackedMsg, end) && + push8(srs_pdu->frequency_hopping, ppWritePackedMsg, end) && + push8(srs_pdu->group_or_sequence_hopping, ppWritePackedMsg, end) && + push8(srs_pdu->resource_type, ppWritePackedMsg, end) && + push16(srs_pdu->t_srs, ppWritePackedMsg, end) && + push16(srs_pdu->t_offset, ppWritePackedMsg, end) + // TODO: ignoring beamforming tlv for now + ); } -static uint8_t pack_ul_config_request_ulsch_pdu(nfapi_ul_config_ulsch_pdu* ulsch_pdu, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - return ( pack_tlv(NFAPI_UL_CONFIG_REQUEST_ULSCH_PDU_REL8_TAG, &ulsch_pdu->ulsch_pdu_rel8, ppWritePackedMsg, end, &pack_ul_config_request_ulsch_rel8_value) && - pack_tlv(NFAPI_UL_CONFIG_REQUEST_ULSCH_PDU_REL10_TAG, &ulsch_pdu->ulsch_pdu_rel10, ppWritePackedMsg, end, &pack_ul_config_request_ulsch_rel10_value) && - pack_tlv(NFAPI_UL_CONFIG_REQUEST_ULSCH_PDU_REL11_TAG, &ulsch_pdu->ulsch_pdu_rel11, ppWritePackedMsg, end, &pack_ul_config_request_ulsch_rel11_value) && - pack_tlv(NFAPI_UL_CONFIG_REQUEST_ULSCH_PDU_REL13_TAG, &ulsch_pdu->ulsch_pdu_rel13, ppWritePackedMsg, end, &pack_ul_config_request_ulsch_rel13_value)); +static uint8_t pack_ul_config_request_ulsch_pdu(nfapi_ul_config_ulsch_pdu *ulsch_pdu, uint8_t **ppWritePackedMsg, uint8_t *end) { + return ( pack_tlv(NFAPI_UL_CONFIG_REQUEST_ULSCH_PDU_REL8_TAG, &ulsch_pdu->ulsch_pdu_rel8, ppWritePackedMsg, end, &pack_ul_config_request_ulsch_rel8_value) && + pack_tlv(NFAPI_UL_CONFIG_REQUEST_ULSCH_PDU_REL10_TAG, &ulsch_pdu->ulsch_pdu_rel10, ppWritePackedMsg, end, &pack_ul_config_request_ulsch_rel10_value) && + pack_tlv(NFAPI_UL_CONFIG_REQUEST_ULSCH_PDU_REL11_TAG, &ulsch_pdu->ulsch_pdu_rel11, ppWritePackedMsg, end, &pack_ul_config_request_ulsch_rel11_value) && + pack_tlv(NFAPI_UL_CONFIG_REQUEST_ULSCH_PDU_REL13_TAG, &ulsch_pdu->ulsch_pdu_rel13, ppWritePackedMsg, end, &pack_ul_config_request_ulsch_rel13_value)); } -static uint8_t pack_ul_config_request_cqi_ri_rel8_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_ul_config_cqi_ri_information_rel8_t* cqi_ri_info_rel8 = (nfapi_ul_config_cqi_ri_information_rel8_t*)tlv; - - return ( push8(cqi_ri_info_rel8->dl_cqi_pmi_size_rank_1, ppWritePackedMsg, end) && - push8(cqi_ri_info_rel8->dl_cqi_pmi_size_rank_greater_1, ppWritePackedMsg, end) && - push8(cqi_ri_info_rel8->ri_size, ppWritePackedMsg, end) && - push8(cqi_ri_info_rel8->delta_offset_cqi, ppWritePackedMsg, end) && - push8(cqi_ri_info_rel8->delta_offset_ri, ppWritePackedMsg, end)); +static uint8_t pack_ul_config_request_cqi_ri_rel8_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_ul_config_cqi_ri_information_rel8_t *cqi_ri_info_rel8 = (nfapi_ul_config_cqi_ri_information_rel8_t *)tlv; + return ( push8(cqi_ri_info_rel8->dl_cqi_pmi_size_rank_1, ppWritePackedMsg, end) && + push8(cqi_ri_info_rel8->dl_cqi_pmi_size_rank_greater_1, ppWritePackedMsg, end) && + push8(cqi_ri_info_rel8->ri_size, ppWritePackedMsg, end) && + push8(cqi_ri_info_rel8->delta_offset_cqi, ppWritePackedMsg, end) && + push8(cqi_ri_info_rel8->delta_offset_ri, ppWritePackedMsg, end)); } -static uint8_t pack_ul_config_request_cqi_ri_rel9_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_ul_config_cqi_ri_information_rel9_t* cqi_ri_info_rel9 = (nfapi_ul_config_cqi_ri_information_rel9_t*)tlv; +static uint8_t pack_ul_config_request_cqi_ri_rel9_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_ul_config_cqi_ri_information_rel9_t *cqi_ri_info_rel9 = (nfapi_ul_config_cqi_ri_information_rel9_t *)tlv; - if(!(push8(cqi_ri_info_rel9->report_type, ppWritePackedMsg, end) && - push8(cqi_ri_info_rel9->delta_offset_cqi, ppWritePackedMsg, end) && - push8(cqi_ri_info_rel9->delta_offset_ri, ppWritePackedMsg, end))) - { - return 0; - } + if(!(push8(cqi_ri_info_rel9->report_type, ppWritePackedMsg, end) && + push8(cqi_ri_info_rel9->delta_offset_cqi, ppWritePackedMsg, end) && + push8(cqi_ri_info_rel9->delta_offset_ri, ppWritePackedMsg, end))) { + return 0; + } - switch(cqi_ri_info_rel9->report_type) - { - case NFAPI_CSI_REPORT_TYPE_PERIODIC: - { - if(!(push8(cqi_ri_info_rel9->periodic_cqi_pmi_ri_report.dl_cqi_pmi_ri_size, ppWritePackedMsg, end) && - push8(cqi_ri_info_rel9->periodic_cqi_pmi_ri_report.control_type, ppWritePackedMsg, end))) - { - return 0; - } - } - break; - case NFAPI_CSI_REPORT_TYPE_APERIODIC: - { - if(push8(cqi_ri_info_rel9->aperiodic_cqi_pmi_ri_report.number_of_cc, ppWritePackedMsg, end) == 0) - return 0; + switch(cqi_ri_info_rel9->report_type) { + case NFAPI_CSI_REPORT_TYPE_PERIODIC: { + if(!(push8(cqi_ri_info_rel9->periodic_cqi_pmi_ri_report.dl_cqi_pmi_ri_size, ppWritePackedMsg, end) && + push8(cqi_ri_info_rel9->periodic_cqi_pmi_ri_report.control_type, ppWritePackedMsg, end))) { + return 0; + } + } + break; - uint8_t i; - for(i = 0; i < cqi_ri_info_rel9->aperiodic_cqi_pmi_ri_report.number_of_cc; ++i) - { - if(push8(cqi_ri_info_rel9->aperiodic_cqi_pmi_ri_report.cc[i].ri_size, ppWritePackedMsg, end) == 0) - return 0; + case NFAPI_CSI_REPORT_TYPE_APERIODIC: { + if(push8(cqi_ri_info_rel9->aperiodic_cqi_pmi_ri_report.number_of_cc, ppWritePackedMsg, end) == 0) + return 0; - uint8_t j; - for(j = 0; j < 8; ++j) - { - if(push8(cqi_ri_info_rel9->aperiodic_cqi_pmi_ri_report.cc[i].dl_cqi_pmi_size[j], ppWritePackedMsg, end) == 0) - return 0; - } - } - } - break; - default: - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "FIXME : Invalid report type %d \n", cqi_ri_info_rel9->report_type ); - } - break; - }; + uint8_t i; - return 1; + for(i = 0; i < cqi_ri_info_rel9->aperiodic_cqi_pmi_ri_report.number_of_cc; ++i) { + if(push8(cqi_ri_info_rel9->aperiodic_cqi_pmi_ri_report.cc[i].ri_size, ppWritePackedMsg, end) == 0) + return 0; + + uint8_t j; + + for(j = 0; j < 8; ++j) { + if(push8(cqi_ri_info_rel9->aperiodic_cqi_pmi_ri_report.cc[i].dl_cqi_pmi_size[j], ppWritePackedMsg, end) == 0) + return 0; + } + } + } + break; + + default: { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "FIXME : Invalid report type %d \n", cqi_ri_info_rel9->report_type ); + } + break; + }; + + return 1; } -static uint8_t pack_ul_config_request_cqi_ri_rel13_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_ul_config_cqi_ri_information_rel13_t* cqi_ri_info_rel13 = (nfapi_ul_config_cqi_ri_information_rel13_t*)tlv; +static uint8_t pack_ul_config_request_cqi_ri_rel13_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_ul_config_cqi_ri_information_rel13_t *cqi_ri_info_rel13 = (nfapi_ul_config_cqi_ri_information_rel13_t *)tlv; - switch(cqi_ri_info_rel13->report_type) - { - case NFAPI_CSI_REPORT_TYPE_PERIODIC: - { - if(push16(cqi_ri_info_rel13->periodic_cqi_pmi_ri_report.dl_cqi_pmi_ri_size_2, ppWritePackedMsg, end) == 0) - return 0; - } - break; - case NFAPI_CSI_REPORT_TYPE_APERIODIC: - { - // No parameters - } - break; - default: - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "FIXME : Invalid report type %d \n", cqi_ri_info_rel13->report_type ); - } - break; - }; + switch(cqi_ri_info_rel13->report_type) { + case NFAPI_CSI_REPORT_TYPE_PERIODIC: { + if(push16(cqi_ri_info_rel13->periodic_cqi_pmi_ri_report.dl_cqi_pmi_ri_size_2, ppWritePackedMsg, end) == 0) + return 0; + } + break; - return 1; + case NFAPI_CSI_REPORT_TYPE_APERIODIC: { + // No parameters + } + break; + + default: { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "FIXME : Invalid report type %d \n", cqi_ri_info_rel13->report_type ); + } + break; + }; + + return 1; } -static uint8_t pack_ul_config_request_cqi_ri_information(nfapi_ul_config_cqi_ri_information* cqi_ri_info, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - return (pack_tlv(NFAPI_UL_CONFIG_REQUEST_CQI_RI_INFORMATION_REL8_TAG, &cqi_ri_info->cqi_ri_information_rel8, ppWritePackedMsg, end, &pack_ul_config_request_cqi_ri_rel8_value) && - pack_tlv(NFAPI_UL_CONFIG_REQUEST_CQI_RI_INFORMATION_REL9_TAG, &cqi_ri_info->cqi_ri_information_rel9, ppWritePackedMsg, end, &pack_ul_config_request_cqi_ri_rel9_value) && - pack_tlv(NFAPI_UL_CONFIG_REQUEST_CQI_RI_INFORMATION_REL13_TAG, &cqi_ri_info->cqi_ri_information_rel13, ppWritePackedMsg, end, &pack_ul_config_request_cqi_ri_rel13_value)); - +static uint8_t pack_ul_config_request_cqi_ri_information(nfapi_ul_config_cqi_ri_information *cqi_ri_info, uint8_t **ppWritePackedMsg, uint8_t *end) { + return (pack_tlv(NFAPI_UL_CONFIG_REQUEST_CQI_RI_INFORMATION_REL8_TAG, &cqi_ri_info->cqi_ri_information_rel8, ppWritePackedMsg, end, &pack_ul_config_request_cqi_ri_rel8_value) && + pack_tlv(NFAPI_UL_CONFIG_REQUEST_CQI_RI_INFORMATION_REL9_TAG, &cqi_ri_info->cqi_ri_information_rel9, ppWritePackedMsg, end, &pack_ul_config_request_cqi_ri_rel9_value) && + pack_tlv(NFAPI_UL_CONFIG_REQUEST_CQI_RI_INFORMATION_REL13_TAG, &cqi_ri_info->cqi_ri_information_rel13, ppWritePackedMsg, end, &pack_ul_config_request_cqi_ri_rel13_value)); } -static uint8_t pack_ul_config_request_init_tx_params_rel8_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_ul_config_initial_transmission_parameters_rel8_t* init_tx_params_rel8 = (nfapi_ul_config_initial_transmission_parameters_rel8_t*)tlv; - - return (push8(init_tx_params_rel8->n_srs_initial, ppWritePackedMsg, end) && - push8(init_tx_params_rel8->initial_number_of_resource_blocks, ppWritePackedMsg, end)); +static uint8_t pack_ul_config_request_init_tx_params_rel8_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_ul_config_initial_transmission_parameters_rel8_t *init_tx_params_rel8 = (nfapi_ul_config_initial_transmission_parameters_rel8_t *)tlv; + return (push8(init_tx_params_rel8->n_srs_initial, ppWritePackedMsg, end) && + push8(init_tx_params_rel8->initial_number_of_resource_blocks, ppWritePackedMsg, end)); } -static uint8_t pack_ul_config_request_initial_transmission_parameters(nfapi_ul_config_initial_transmission_parameters* init_tx_params, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - return pack_tlv(NFAPI_UL_CONFIG_REQUEST_INITIAL_TRANSMISSION_PARAMETERS_REL8_TAG, &init_tx_params->initial_transmission_parameters_rel8, ppWritePackedMsg, end, &pack_ul_config_request_init_tx_params_rel8_value); +static uint8_t pack_ul_config_request_initial_transmission_parameters(nfapi_ul_config_initial_transmission_parameters *init_tx_params, uint8_t **ppWritePackedMsg, uint8_t *end) { + return pack_tlv(NFAPI_UL_CONFIG_REQUEST_INITIAL_TRANSMISSION_PARAMETERS_REL8_TAG, &init_tx_params->initial_transmission_parameters_rel8, ppWritePackedMsg, end, + &pack_ul_config_request_init_tx_params_rel8_value); } -static uint8_t pack_ul_config_request_ulsch_harq_info_rel10_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_ul_config_ulsch_harq_information_rel10_t* harq_info_rel10 = (nfapi_ul_config_ulsch_harq_information_rel10_t*)tlv; - - return (push8(harq_info_rel10->harq_size, ppWritePackedMsg, end) && - push8(harq_info_rel10->delta_offset_harq, ppWritePackedMsg, end) && - push8(harq_info_rel10->ack_nack_mode, ppWritePackedMsg, end)); +static uint8_t pack_ul_config_request_ulsch_harq_info_rel10_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_ul_config_ulsch_harq_information_rel10_t *harq_info_rel10 = (nfapi_ul_config_ulsch_harq_information_rel10_t *)tlv; + return (push8(harq_info_rel10->harq_size, ppWritePackedMsg, end) && + push8(harq_info_rel10->delta_offset_harq, ppWritePackedMsg, end) && + push8(harq_info_rel10->ack_nack_mode, ppWritePackedMsg, end)); } -static uint8_t pack_ul_config_request_ulsch_harq_info_rel13_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_ul_config_ulsch_harq_information_rel13_t* harq_info_rel13 = (nfapi_ul_config_ulsch_harq_information_rel13_t*)tlv; - - return (push16(harq_info_rel13->harq_size_2, ppWritePackedMsg, end) && - push8(harq_info_rel13->delta_offset_harq_2, ppWritePackedMsg, end)); +static uint8_t pack_ul_config_request_ulsch_harq_info_rel13_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_ul_config_ulsch_harq_information_rel13_t *harq_info_rel13 = (nfapi_ul_config_ulsch_harq_information_rel13_t *)tlv; + return (push16(harq_info_rel13->harq_size_2, ppWritePackedMsg, end) && + push8(harq_info_rel13->delta_offset_harq_2, ppWritePackedMsg, end)); } -static uint8_t pack_ul_config_request_ulsch_harq_information(nfapi_ul_config_ulsch_harq_information* harq_info, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - return ( pack_tlv(NFAPI_UL_CONFIG_REQUEST_ULSCH_HARQ_INFORMATION_REL10_TAG, &harq_info->harq_information_rel10, ppWritePackedMsg, end, &pack_ul_config_request_ulsch_harq_info_rel10_value) && - pack_tlv(NFAPI_UL_CONFIG_REQUEST_ULSCH_HARQ_INFORMATION_REL13_TAG, &harq_info->harq_information_rel13, ppWritePackedMsg, end, &pack_ul_config_request_ulsch_harq_info_rel13_value)); +static uint8_t pack_ul_config_request_ulsch_harq_information(nfapi_ul_config_ulsch_harq_information *harq_info, uint8_t **ppWritePackedMsg, uint8_t *end) { + return ( pack_tlv(NFAPI_UL_CONFIG_REQUEST_ULSCH_HARQ_INFORMATION_REL10_TAG, &harq_info->harq_information_rel10, ppWritePackedMsg, end, &pack_ul_config_request_ulsch_harq_info_rel10_value) && + pack_tlv(NFAPI_UL_CONFIG_REQUEST_ULSCH_HARQ_INFORMATION_REL13_TAG, &harq_info->harq_information_rel13, ppWritePackedMsg, end, &pack_ul_config_request_ulsch_harq_info_rel13_value)); } -static uint8_t pack_ul_config_request_ue_info_rel8_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_ul_config_ue_information_rel8_t* ue_info_rel8 = (nfapi_ul_config_ue_information_rel8_t*)tlv; - - return ( push32(ue_info_rel8->handle, ppWritePackedMsg, end) && - push16(ue_info_rel8->rnti, ppWritePackedMsg, end)); +static uint8_t pack_ul_config_request_ue_info_rel8_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_ul_config_ue_information_rel8_t *ue_info_rel8 = (nfapi_ul_config_ue_information_rel8_t *)tlv; + return ( push32(ue_info_rel8->handle, ppWritePackedMsg, end) && + push16(ue_info_rel8->rnti, ppWritePackedMsg, end)); } -static uint8_t pack_ul_config_request_ue_info_rel11_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_ul_config_ue_information_rel11_t* ue_info_rel11 = (nfapi_ul_config_ue_information_rel11_t*)tlv; - - return ( push8(ue_info_rel11->virtual_cell_id_enabled_flag, ppWritePackedMsg, end) && - push16(ue_info_rel11->npusch_identity, ppWritePackedMsg, end)); +static uint8_t pack_ul_config_request_ue_info_rel11_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_ul_config_ue_information_rel11_t *ue_info_rel11 = (nfapi_ul_config_ue_information_rel11_t *)tlv; + return ( push8(ue_info_rel11->virtual_cell_id_enabled_flag, ppWritePackedMsg, end) && + push16(ue_info_rel11->npusch_identity, ppWritePackedMsg, end)); } -static uint8_t pack_ul_config_request_ue_info_rel13_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_ul_config_ue_information_rel13_t* ue_info_rel13 = (nfapi_ul_config_ue_information_rel13_t*)tlv; - - return ( push8(ue_info_rel13->ue_type, ppWritePackedMsg, end) && - push8(ue_info_rel13->empty_symbols, ppWritePackedMsg, end) && - push16(ue_info_rel13->total_number_of_repetitions, ppWritePackedMsg, end) && - push16(ue_info_rel13->repetition_number, ppWritePackedMsg, end)); +static uint8_t pack_ul_config_request_ue_info_rel13_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_ul_config_ue_information_rel13_t *ue_info_rel13 = (nfapi_ul_config_ue_information_rel13_t *)tlv; + return ( push8(ue_info_rel13->ue_type, ppWritePackedMsg, end) && + push8(ue_info_rel13->empty_symbols, ppWritePackedMsg, end) && + push16(ue_info_rel13->total_number_of_repetitions, ppWritePackedMsg, end) && + push16(ue_info_rel13->repetition_number, ppWritePackedMsg, end)); } -static uint8_t pack_ul_config_request_ue_information(nfapi_ul_config_ue_information* ue_info, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - return ( pack_tlv(NFAPI_UL_CONFIG_REQUEST_UE_INFORMATION_REL8_TAG, &ue_info->ue_information_rel8, ppWritePackedMsg, end, &pack_ul_config_request_ue_info_rel8_value) && - pack_tlv(NFAPI_UL_CONFIG_REQUEST_UE_INFORMATION_REL11_TAG, &ue_info->ue_information_rel11, ppWritePackedMsg, end, &pack_ul_config_request_ue_info_rel11_value) && - pack_tlv(NFAPI_UL_CONFIG_REQUEST_UE_INFORMATION_REL13_TAG, &ue_info->ue_information_rel13, ppWritePackedMsg, end, &pack_ul_config_request_ue_info_rel13_value)); +static uint8_t pack_ul_config_request_ue_information(nfapi_ul_config_ue_information *ue_info, uint8_t **ppWritePackedMsg, uint8_t *end) { + return ( pack_tlv(NFAPI_UL_CONFIG_REQUEST_UE_INFORMATION_REL8_TAG, &ue_info->ue_information_rel8, ppWritePackedMsg, end, &pack_ul_config_request_ue_info_rel8_value) && + pack_tlv(NFAPI_UL_CONFIG_REQUEST_UE_INFORMATION_REL11_TAG, &ue_info->ue_information_rel11, ppWritePackedMsg, end, &pack_ul_config_request_ue_info_rel11_value) && + pack_tlv(NFAPI_UL_CONFIG_REQUEST_UE_INFORMATION_REL13_TAG, &ue_info->ue_information_rel13, ppWritePackedMsg, end, &pack_ul_config_request_ue_info_rel13_value)); } -static uint8_t pack_ul_config_request_harq_info_rel10_tdd_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_ul_config_harq_information_rel10_tdd_t* harq_info_rel10_tdd = (nfapi_ul_config_harq_information_rel10_tdd_t*)tlv; - - return ( push8(harq_info_rel10_tdd->harq_size, ppWritePackedMsg, end) && - push8(harq_info_rel10_tdd->ack_nack_mode, ppWritePackedMsg, end) && - push8(harq_info_rel10_tdd->number_of_pucch_resources, ppWritePackedMsg, end) && - push16(harq_info_rel10_tdd->n_pucch_1_0, ppWritePackedMsg, end) && - push16(harq_info_rel10_tdd->n_pucch_1_1, ppWritePackedMsg, end) && - push16(harq_info_rel10_tdd->n_pucch_1_2, ppWritePackedMsg, end) && - push16(harq_info_rel10_tdd->n_pucch_1_3, ppWritePackedMsg, end)); +static uint8_t pack_ul_config_request_harq_info_rel10_tdd_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_ul_config_harq_information_rel10_tdd_t *harq_info_rel10_tdd = (nfapi_ul_config_harq_information_rel10_tdd_t *)tlv; + return ( push8(harq_info_rel10_tdd->harq_size, ppWritePackedMsg, end) && + push8(harq_info_rel10_tdd->ack_nack_mode, ppWritePackedMsg, end) && + push8(harq_info_rel10_tdd->number_of_pucch_resources, ppWritePackedMsg, end) && + push16(harq_info_rel10_tdd->n_pucch_1_0, ppWritePackedMsg, end) && + push16(harq_info_rel10_tdd->n_pucch_1_1, ppWritePackedMsg, end) && + push16(harq_info_rel10_tdd->n_pucch_1_2, ppWritePackedMsg, end) && + push16(harq_info_rel10_tdd->n_pucch_1_3, ppWritePackedMsg, end)); } -static uint8_t pack_ul_config_request_harq_info_rel8_fdd_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_ul_config_harq_information_rel8_fdd_t* harq_info_rel8_fdd = (nfapi_ul_config_harq_information_rel8_fdd_t*)tlv; - - return ( push16(harq_info_rel8_fdd->n_pucch_1_0, ppWritePackedMsg, end) && - push8(harq_info_rel8_fdd->harq_size, ppWritePackedMsg, end)); +static uint8_t pack_ul_config_request_harq_info_rel8_fdd_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_ul_config_harq_information_rel8_fdd_t *harq_info_rel8_fdd = (nfapi_ul_config_harq_information_rel8_fdd_t *)tlv; + return ( push16(harq_info_rel8_fdd->n_pucch_1_0, ppWritePackedMsg, end) && + push8(harq_info_rel8_fdd->harq_size, ppWritePackedMsg, end)); } -static uint8_t pack_ul_config_request_harq_info_rel9_fdd_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_ul_config_harq_information_rel9_fdd_t* harq_info_rel9_fdd = (nfapi_ul_config_harq_information_rel9_fdd_t*)tlv; - - return ( push8(harq_info_rel9_fdd->harq_size, ppWritePackedMsg, end) && - push8(harq_info_rel9_fdd->ack_nack_mode, ppWritePackedMsg, end) && - push8(harq_info_rel9_fdd->number_of_pucch_resources, ppWritePackedMsg, end) && - push16(harq_info_rel9_fdd->n_pucch_1_0, ppWritePackedMsg, end) && - push16(harq_info_rel9_fdd->n_pucch_1_1, ppWritePackedMsg, end) && - push16(harq_info_rel9_fdd->n_pucch_1_2, ppWritePackedMsg, end) && - push16(harq_info_rel9_fdd->n_pucch_1_3, ppWritePackedMsg, end)); +static uint8_t pack_ul_config_request_harq_info_rel9_fdd_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_ul_config_harq_information_rel9_fdd_t *harq_info_rel9_fdd = (nfapi_ul_config_harq_information_rel9_fdd_t *)tlv; + return ( push8(harq_info_rel9_fdd->harq_size, ppWritePackedMsg, end) && + push8(harq_info_rel9_fdd->ack_nack_mode, ppWritePackedMsg, end) && + push8(harq_info_rel9_fdd->number_of_pucch_resources, ppWritePackedMsg, end) && + push16(harq_info_rel9_fdd->n_pucch_1_0, ppWritePackedMsg, end) && + push16(harq_info_rel9_fdd->n_pucch_1_1, ppWritePackedMsg, end) && + push16(harq_info_rel9_fdd->n_pucch_1_2, ppWritePackedMsg, end) && + push16(harq_info_rel9_fdd->n_pucch_1_3, ppWritePackedMsg, end)); } -static uint8_t pack_ul_config_request_harq_info_rel11_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_ul_config_harq_information_rel11_t* harq_info_rel11 = (nfapi_ul_config_harq_information_rel11_t*)tlv; - - return ( push8(harq_info_rel11->num_ant_ports, ppWritePackedMsg, end) && - push16(harq_info_rel11->n_pucch_2_0, ppWritePackedMsg, end) && - push16(harq_info_rel11->n_pucch_2_1, ppWritePackedMsg, end) && - push16(harq_info_rel11->n_pucch_2_2, ppWritePackedMsg, end) && - push16(harq_info_rel11->n_pucch_2_3, ppWritePackedMsg, end)); +static uint8_t pack_ul_config_request_harq_info_rel11_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_ul_config_harq_information_rel11_t *harq_info_rel11 = (nfapi_ul_config_harq_information_rel11_t *)tlv; + return ( push8(harq_info_rel11->num_ant_ports, ppWritePackedMsg, end) && + push16(harq_info_rel11->n_pucch_2_0, ppWritePackedMsg, end) && + push16(harq_info_rel11->n_pucch_2_1, ppWritePackedMsg, end) && + push16(harq_info_rel11->n_pucch_2_2, ppWritePackedMsg, end) && + push16(harq_info_rel11->n_pucch_2_3, ppWritePackedMsg, end)); } -static uint8_t pack_ul_config_request_harq_info_rel13_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_ul_config_harq_information_rel13_t* harq_info_rel13 = (nfapi_ul_config_harq_information_rel13_t*)tlv; - - return ( push16(harq_info_rel13->harq_size_2, ppWritePackedMsg, end) && - push8(harq_info_rel13->starting_prb, ppWritePackedMsg, end) && - push8(harq_info_rel13->n_prb, ppWritePackedMsg, end) && - push8(harq_info_rel13->cdm_index, ppWritePackedMsg, end) && - push8(harq_info_rel13->n_srs, ppWritePackedMsg, end)); +static uint8_t pack_ul_config_request_harq_info_rel13_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_ul_config_harq_information_rel13_t *harq_info_rel13 = (nfapi_ul_config_harq_information_rel13_t *)tlv; + return ( push16(harq_info_rel13->harq_size_2, ppWritePackedMsg, end) && + push8(harq_info_rel13->starting_prb, ppWritePackedMsg, end) && + push8(harq_info_rel13->n_prb, ppWritePackedMsg, end) && + push8(harq_info_rel13->cdm_index, ppWritePackedMsg, end) && + push8(harq_info_rel13->n_srs, ppWritePackedMsg, end)); } -static uint8_t pack_ul_config_request_harq_information(nfapi_ul_config_harq_information* harq_info, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - return ( pack_tlv(NFAPI_UL_CONFIG_REQUEST_HARQ_INFORMATION_REL10_TDD_TAG, &harq_info->harq_information_rel10_tdd, ppWritePackedMsg, end, &pack_ul_config_request_harq_info_rel10_tdd_value) && - pack_tlv(NFAPI_UL_CONFIG_REQUEST_HARQ_INFORMATION_REL8_FDD_TAG, &harq_info->harq_information_rel8_fdd, ppWritePackedMsg, end, &pack_ul_config_request_harq_info_rel8_fdd_value) && - pack_tlv(NFAPI_UL_CONFIG_REQUEST_HARQ_INFORMATION_REL9_FDD_TAG, &harq_info->harq_information_rel9_fdd, ppWritePackedMsg, end, &pack_ul_config_request_harq_info_rel9_fdd_value) && - pack_tlv(NFAPI_UL_CONFIG_REQUEST_HARQ_INFORMATION_REL11_TAG, &harq_info->harq_information_rel11, ppWritePackedMsg, end, &pack_ul_config_request_harq_info_rel11_value) && - pack_tlv(NFAPI_UL_CONFIG_REQUEST_HARQ_INFORMATION_REL13_TAG, &harq_info->harq_information_rel13, ppWritePackedMsg, end, &pack_ul_config_request_harq_info_rel13_value)); - +static uint8_t pack_ul_config_request_harq_information(nfapi_ul_config_harq_information *harq_info, uint8_t **ppWritePackedMsg, uint8_t *end) { + return ( pack_tlv(NFAPI_UL_CONFIG_REQUEST_HARQ_INFORMATION_REL10_TDD_TAG, &harq_info->harq_information_rel10_tdd, ppWritePackedMsg, end, &pack_ul_config_request_harq_info_rel10_tdd_value) && + pack_tlv(NFAPI_UL_CONFIG_REQUEST_HARQ_INFORMATION_REL8_FDD_TAG, &harq_info->harq_information_rel8_fdd, ppWritePackedMsg, end, &pack_ul_config_request_harq_info_rel8_fdd_value) && + pack_tlv(NFAPI_UL_CONFIG_REQUEST_HARQ_INFORMATION_REL9_FDD_TAG, &harq_info->harq_information_rel9_fdd, ppWritePackedMsg, end, &pack_ul_config_request_harq_info_rel9_fdd_value) && + pack_tlv(NFAPI_UL_CONFIG_REQUEST_HARQ_INFORMATION_REL11_TAG, &harq_info->harq_information_rel11, ppWritePackedMsg, end, &pack_ul_config_request_harq_info_rel11_value) && + pack_tlv(NFAPI_UL_CONFIG_REQUEST_HARQ_INFORMATION_REL13_TAG, &harq_info->harq_information_rel13, ppWritePackedMsg, end, &pack_ul_config_request_harq_info_rel13_value)); } -static uint8_t pack_ul_config_request_cqi_info_rel8_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_ul_config_cqi_information_rel8_t* cqi_info_rel8 = (nfapi_ul_config_cqi_information_rel8_t*)tlv; - - return ( push16(cqi_info_rel8->pucch_index, ppWritePackedMsg, end) && - push8(cqi_info_rel8->dl_cqi_pmi_size, ppWritePackedMsg, end)); +static uint8_t pack_ul_config_request_cqi_info_rel8_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_ul_config_cqi_information_rel8_t *cqi_info_rel8 = (nfapi_ul_config_cqi_information_rel8_t *)tlv; + return ( push16(cqi_info_rel8->pucch_index, ppWritePackedMsg, end) && + push8(cqi_info_rel8->dl_cqi_pmi_size, ppWritePackedMsg, end)); } -static uint8_t pack_ul_config_request_cqi_info_rel10_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_ul_config_cqi_information_rel10_t* cqi_info_rel10 = (nfapi_ul_config_cqi_information_rel10_t*)tlv; - - return ( push8(cqi_info_rel10->number_of_pucch_resource, ppWritePackedMsg, end) && - push16(cqi_info_rel10->pucch_index_p1, ppWritePackedMsg, end)); +static uint8_t pack_ul_config_request_cqi_info_rel10_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_ul_config_cqi_information_rel10_t *cqi_info_rel10 = (nfapi_ul_config_cqi_information_rel10_t *)tlv; + return ( push8(cqi_info_rel10->number_of_pucch_resource, ppWritePackedMsg, end) && + push16(cqi_info_rel10->pucch_index_p1, ppWritePackedMsg, end)); } -static uint8_t pack_ul_config_request_cqi_info_rel13_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_ul_config_cqi_information_rel13_t* cqi_info_rel13 = (nfapi_ul_config_cqi_information_rel13_t*)tlv; - - return ( push8(cqi_info_rel13->csi_mode, ppWritePackedMsg, end) && - push16(cqi_info_rel13->dl_cqi_pmi_size_2, ppWritePackedMsg, end) && - push8(cqi_info_rel13->starting_prb, ppWritePackedMsg, end) && - push8(cqi_info_rel13->n_prb, ppWritePackedMsg, end) && - push8(cqi_info_rel13->cdm_index, ppWritePackedMsg, end) && - push8(cqi_info_rel13->n_srs, ppWritePackedMsg, end)); +static uint8_t pack_ul_config_request_cqi_info_rel13_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_ul_config_cqi_information_rel13_t *cqi_info_rel13 = (nfapi_ul_config_cqi_information_rel13_t *)tlv; + return ( push8(cqi_info_rel13->csi_mode, ppWritePackedMsg, end) && + push16(cqi_info_rel13->dl_cqi_pmi_size_2, ppWritePackedMsg, end) && + push8(cqi_info_rel13->starting_prb, ppWritePackedMsg, end) && + push8(cqi_info_rel13->n_prb, ppWritePackedMsg, end) && + push8(cqi_info_rel13->cdm_index, ppWritePackedMsg, end) && + push8(cqi_info_rel13->n_srs, ppWritePackedMsg, end)); } -static uint8_t pack_ul_config_request_cqi_information(nfapi_ul_config_cqi_information* cqi_info, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - return ( pack_tlv(NFAPI_UL_CONFIG_REQUEST_CQI_INFORMATION_REL8_TAG, &cqi_info->cqi_information_rel8, ppWritePackedMsg, end, &pack_ul_config_request_cqi_info_rel8_value) && - pack_tlv(NFAPI_UL_CONFIG_REQUEST_CQI_INFORMATION_REL10_TAG, &cqi_info->cqi_information_rel10, ppWritePackedMsg, end, &pack_ul_config_request_cqi_info_rel10_value) && - pack_tlv(NFAPI_UL_CONFIG_REQUEST_CQI_INFORMATION_REL13_TAG, &cqi_info->cqi_information_rel13, ppWritePackedMsg, end, &pack_ul_config_request_cqi_info_rel13_value)); - +static uint8_t pack_ul_config_request_cqi_information(nfapi_ul_config_cqi_information *cqi_info, uint8_t **ppWritePackedMsg, uint8_t *end) { + return ( pack_tlv(NFAPI_UL_CONFIG_REQUEST_CQI_INFORMATION_REL8_TAG, &cqi_info->cqi_information_rel8, ppWritePackedMsg, end, &pack_ul_config_request_cqi_info_rel8_value) && + pack_tlv(NFAPI_UL_CONFIG_REQUEST_CQI_INFORMATION_REL10_TAG, &cqi_info->cqi_information_rel10, ppWritePackedMsg, end, &pack_ul_config_request_cqi_info_rel10_value) && + pack_tlv(NFAPI_UL_CONFIG_REQUEST_CQI_INFORMATION_REL13_TAG, &cqi_info->cqi_information_rel13, ppWritePackedMsg, end, &pack_ul_config_request_cqi_info_rel13_value)); } -static uint8_t pack_ul_config_request_sr_info_rel8_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_ul_config_sr_information_rel8_t* sr_info_rel8 = (nfapi_ul_config_sr_information_rel8_t*)tlv; - return push16(sr_info_rel8->pucch_index, ppWritePackedMsg, end); +static uint8_t pack_ul_config_request_sr_info_rel8_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_ul_config_sr_information_rel8_t *sr_info_rel8 = (nfapi_ul_config_sr_information_rel8_t *)tlv; + return push16(sr_info_rel8->pucch_index, ppWritePackedMsg, end); } -static uint8_t pack_ul_config_request_sr_info_rel10_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_ul_config_sr_information_rel10_t* sr_info_rel10 = (nfapi_ul_config_sr_information_rel10_t*)tlv; - - return ( push8(sr_info_rel10->number_of_pucch_resources, ppWritePackedMsg, end) && - push16(sr_info_rel10->pucch_index_p1, ppWritePackedMsg, end)); +static uint8_t pack_ul_config_request_sr_info_rel10_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_ul_config_sr_information_rel10_t *sr_info_rel10 = (nfapi_ul_config_sr_information_rel10_t *)tlv; + return ( push8(sr_info_rel10->number_of_pucch_resources, ppWritePackedMsg, end) && + push16(sr_info_rel10->pucch_index_p1, ppWritePackedMsg, end)); } -static uint8_t pack_ul_config_request_sr_information(nfapi_ul_config_sr_information* sr_info, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - return ( pack_tlv(NFAPI_UL_CONFIG_REQUEST_SR_INFORMATION_REL8_TAG, &sr_info->sr_information_rel8, ppWritePackedMsg, end, &pack_ul_config_request_sr_info_rel8_value) && - pack_tlv(NFAPI_UL_CONFIG_REQUEST_SR_INFORMATION_REL10_TAG, &sr_info->sr_information_rel10, ppWritePackedMsg, end, &pack_ul_config_request_sr_info_rel10_value)); +static uint8_t pack_ul_config_request_sr_information(nfapi_ul_config_sr_information *sr_info, uint8_t **ppWritePackedMsg, uint8_t *end) { + return ( pack_tlv(NFAPI_UL_CONFIG_REQUEST_SR_INFORMATION_REL8_TAG, &sr_info->sr_information_rel8, ppWritePackedMsg, end, &pack_ul_config_request_sr_info_rel8_value) && + pack_tlv(NFAPI_UL_CONFIG_REQUEST_SR_INFORMATION_REL10_TAG, &sr_info->sr_information_rel10, ppWritePackedMsg, end, &pack_ul_config_request_sr_info_rel10_value)); } -static uint8_t pack_ul_config_request_srs_pdu_rel8_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_ul_config_srs_pdu_rel8_t* srs_pdu_rel8 = (nfapi_ul_config_srs_pdu_rel8_t*)tlv; - - return (push32(srs_pdu_rel8->handle, ppWritePackedMsg, end) && - push16(srs_pdu_rel8->size, ppWritePackedMsg, end) && - push16(srs_pdu_rel8->rnti, ppWritePackedMsg, end) && - push8(srs_pdu_rel8->srs_bandwidth, ppWritePackedMsg, end) && - push8(srs_pdu_rel8->frequency_domain_position, ppWritePackedMsg, end) && - push8(srs_pdu_rel8->srs_hopping_bandwidth, ppWritePackedMsg, end) && - push8(srs_pdu_rel8->transmission_comb, ppWritePackedMsg, end) && - push16(srs_pdu_rel8->i_srs, ppWritePackedMsg, end) && - push8(srs_pdu_rel8->sounding_reference_cyclic_shift, ppWritePackedMsg, end)); +static uint8_t pack_ul_config_request_srs_pdu_rel8_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_ul_config_srs_pdu_rel8_t *srs_pdu_rel8 = (nfapi_ul_config_srs_pdu_rel8_t *)tlv; + return (push32(srs_pdu_rel8->handle, ppWritePackedMsg, end) && + push16(srs_pdu_rel8->size, ppWritePackedMsg, end) && + push16(srs_pdu_rel8->rnti, ppWritePackedMsg, end) && + push8(srs_pdu_rel8->srs_bandwidth, ppWritePackedMsg, end) && + push8(srs_pdu_rel8->frequency_domain_position, ppWritePackedMsg, end) && + push8(srs_pdu_rel8->srs_hopping_bandwidth, ppWritePackedMsg, end) && + push8(srs_pdu_rel8->transmission_comb, ppWritePackedMsg, end) && + push16(srs_pdu_rel8->i_srs, ppWritePackedMsg, end) && + push8(srs_pdu_rel8->sounding_reference_cyclic_shift, ppWritePackedMsg, end)); } -static uint8_t pack_ul_config_request_srs_pdu_rel10_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_ul_config_srs_pdu_rel10_t* srs_pdu_rel10 = (nfapi_ul_config_srs_pdu_rel10_t*)tlv; - return push8(srs_pdu_rel10->antenna_port, ppWritePackedMsg, end); +static uint8_t pack_ul_config_request_srs_pdu_rel10_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_ul_config_srs_pdu_rel10_t *srs_pdu_rel10 = (nfapi_ul_config_srs_pdu_rel10_t *)tlv; + return push8(srs_pdu_rel10->antenna_port, ppWritePackedMsg, end); } -static uint8_t pack_ul_config_request_srs_pdu_rel13_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_ul_config_srs_pdu_rel13_t* srs_pdu_rel13 = (nfapi_ul_config_srs_pdu_rel13_t*)tlv; - - return ( push8(srs_pdu_rel13->number_of_combs, ppWritePackedMsg, end)); +static uint8_t pack_ul_config_request_srs_pdu_rel13_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_ul_config_srs_pdu_rel13_t *srs_pdu_rel13 = (nfapi_ul_config_srs_pdu_rel13_t *)tlv; + return ( push8(srs_pdu_rel13->number_of_combs, ppWritePackedMsg, end)); } -static uint8_t pack_ul_config_request_nb_harq_rel13_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_ul_config_nb_harq_information_rel13_fdd_t* nb_harq_pdu_rel13 = (nfapi_ul_config_nb_harq_information_rel13_fdd_t*)tlv; - - return ( push8(nb_harq_pdu_rel13->harq_ack_resource, ppWritePackedMsg, end)); +static uint8_t pack_ul_config_request_nb_harq_rel13_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_ul_config_nb_harq_information_rel13_fdd_t *nb_harq_pdu_rel13 = (nfapi_ul_config_nb_harq_information_rel13_fdd_t *)tlv; + return ( push8(nb_harq_pdu_rel13->harq_ack_resource, ppWritePackedMsg, end)); } -static uint8_t pack_ul_config_request_nulsch_pdu_rel13_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_ul_config_nulsch_pdu_rel13_t* nulsch_pdu_rel13 = (nfapi_ul_config_nulsch_pdu_rel13_t*)tlv; - - return (push8(nulsch_pdu_rel13->nulsch_format, ppWritePackedMsg, end) && - push32(nulsch_pdu_rel13->handle, ppWritePackedMsg, end) && - push16(nulsch_pdu_rel13->size, ppWritePackedMsg, end) && - push16(nulsch_pdu_rel13->rnti, ppWritePackedMsg, end) && - push8(nulsch_pdu_rel13->subcarrier_indication, ppWritePackedMsg, end) && - push8(nulsch_pdu_rel13->resource_assignment, ppWritePackedMsg, end) && - push8(nulsch_pdu_rel13->mcs, ppWritePackedMsg, end) && - push8(nulsch_pdu_rel13->redudancy_version, ppWritePackedMsg, end) && - push8(nulsch_pdu_rel13->repetition_number, ppWritePackedMsg, end) && - push8(nulsch_pdu_rel13->new_data_indication, ppWritePackedMsg, end) && - push8(nulsch_pdu_rel13->n_srs, ppWritePackedMsg, end) && - push16(nulsch_pdu_rel13->scrambling_sequence_initialization_cinit, ppWritePackedMsg, end) && - push16(nulsch_pdu_rel13->sf_idx, ppWritePackedMsg, end) && - pack_ul_config_request_ue_information(&(nulsch_pdu_rel13->ue_information), ppWritePackedMsg, end) && - pack_tlv(NFAPI_UL_CONFIG_REQUEST_NB_HARQ_INFORMATION_REL13_FDD_TAG, &nulsch_pdu_rel13->nb_harq_information.nb_harq_information_rel13_fdd, ppWritePackedMsg, end, &pack_ul_config_request_nb_harq_rel13_value)); +static uint8_t pack_ul_config_request_nulsch_pdu_rel13_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_ul_config_nulsch_pdu_rel13_t *nulsch_pdu_rel13 = (nfapi_ul_config_nulsch_pdu_rel13_t *)tlv; + return (push8(nulsch_pdu_rel13->nulsch_format, ppWritePackedMsg, end) && + push32(nulsch_pdu_rel13->handle, ppWritePackedMsg, end) && + push16(nulsch_pdu_rel13->size, ppWritePackedMsg, end) && + push16(nulsch_pdu_rel13->rnti, ppWritePackedMsg, end) && + push8(nulsch_pdu_rel13->subcarrier_indication, ppWritePackedMsg, end) && + push8(nulsch_pdu_rel13->resource_assignment, ppWritePackedMsg, end) && + push8(nulsch_pdu_rel13->mcs, ppWritePackedMsg, end) && + push8(nulsch_pdu_rel13->redudancy_version, ppWritePackedMsg, end) && + push8(nulsch_pdu_rel13->repetition_number, ppWritePackedMsg, end) && + push8(nulsch_pdu_rel13->new_data_indication, ppWritePackedMsg, end) && + push8(nulsch_pdu_rel13->n_srs, ppWritePackedMsg, end) && + push16(nulsch_pdu_rel13->scrambling_sequence_initialization_cinit, ppWritePackedMsg, end) && + push16(nulsch_pdu_rel13->sf_idx, ppWritePackedMsg, end) && + pack_ul_config_request_ue_information(&(nulsch_pdu_rel13->ue_information), ppWritePackedMsg, end) && + pack_tlv(NFAPI_UL_CONFIG_REQUEST_NB_HARQ_INFORMATION_REL13_FDD_TAG, &nulsch_pdu_rel13->nb_harq_information.nb_harq_information_rel13_fdd, ppWritePackedMsg, end, + &pack_ul_config_request_nb_harq_rel13_value)); } -static uint8_t pack_ul_config_request_nrach_pdu_rel13_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_ul_config_nrach_pdu_rel13_t* nrach_pdu_rel13 = (nfapi_ul_config_nrach_pdu_rel13_t*)tlv; - - return ( push8(nrach_pdu_rel13->nprach_config_0, ppWritePackedMsg, end) && - push8(nrach_pdu_rel13->nprach_config_1, ppWritePackedMsg, end) && - push8(nrach_pdu_rel13->nprach_config_2, ppWritePackedMsg, end)); - +static uint8_t pack_ul_config_request_nrach_pdu_rel13_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_ul_config_nrach_pdu_rel13_t *nrach_pdu_rel13 = (nfapi_ul_config_nrach_pdu_rel13_t *)tlv; + return ( push8(nrach_pdu_rel13->nprach_config_0, ppWritePackedMsg, end) && + push8(nrach_pdu_rel13->nprach_config_1, ppWritePackedMsg, end) && + push8(nrach_pdu_rel13->nprach_config_2, ppWritePackedMsg, end)); } -static uint8_t pack_ul_tti_pdu_list_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_nr_ul_tti_request_number_of_pdus_t* value = (nfapi_nr_ul_tti_request_number_of_pdus_t*)tlv; +static uint8_t pack_ul_tti_pdu_list_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_nr_ul_tti_request_number_of_pdus_t *value = (nfapi_nr_ul_tti_request_number_of_pdus_t *)tlv; - if(!(push16(value->pdu_size, ppWritePackedMsg, end) && - push16(value->pdu_type, ppWritePackedMsg, end) )) - return 0; + if(!(push16(value->pdu_size, ppWritePackedMsg, end) && + push16(value->pdu_type, ppWritePackedMsg, end) )) + return 0; + // first match the pdu type, then call the respective function + switch(value->pdu_type) { + case NFAPI_NR_UL_CONFIG_PRACH_PDU_TYPE: { + if(!pack_ul_tti_request_prach_pdu(&value->prach_pdu, ppWritePackedMsg, end)) + return 0; + } + break; - // first match the pdu type, then call the respective function - switch(value->pdu_type) - { - case NFAPI_NR_UL_CONFIG_PRACH_PDU_TYPE: - { - if(!pack_ul_tti_request_prach_pdu(&value->prach_pdu, ppWritePackedMsg, end)) - return 0; - } - break; + case NFAPI_NR_UL_CONFIG_PUCCH_PDU_TYPE: { + if(!pack_ul_tti_request_pucch_pdu(&value->pucch_pdu, ppWritePackedMsg, end)) + return 0; + } + break; - case NFAPI_NR_UL_CONFIG_PUCCH_PDU_TYPE: - { - if(!pack_ul_tti_request_pucch_pdu(&value->pucch_pdu, ppWritePackedMsg, end)) - return 0; - } - break; - case NFAPI_NR_UL_CONFIG_PUSCH_PDU_TYPE: - { - if(!pack_ul_tti_request_pusch_pdu(&value->pusch_pdu, ppWritePackedMsg, end)) - return 0; - } - break; - case NFAPI_NR_UL_CONFIG_SRS_PDU_TYPE: - { - if(!pack_ul_tti_request_srs_pdu(&value->srs_pdu, ppWritePackedMsg, end)) - return 0; - } - break; + case NFAPI_NR_UL_CONFIG_PUSCH_PDU_TYPE: { + if(!pack_ul_tti_request_pusch_pdu(&value->pusch_pdu, ppWritePackedMsg, end)) + return 0; + } + break; - default: - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "FIXME : Invalid UL_TTI pdu type %d \n", value->pdu_type ); - } - break; - } + case NFAPI_NR_UL_CONFIG_SRS_PDU_TYPE: { + if(!pack_ul_tti_request_srs_pdu(&value->srs_pdu, ppWritePackedMsg, end)) + return 0; + } + break; - return 1; + default: { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "FIXME : Invalid UL_TTI pdu type %d \n", value->pdu_type ); + } + break; + } + + return 1; } -static uint8_t pack_ul_tti_groups_list_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_nr_ul_tti_request_number_of_groups_t* value = (nfapi_nr_ul_tti_request_number_of_groups_t*)tlv; +static uint8_t pack_ul_tti_groups_list_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_nr_ul_tti_request_number_of_groups_t *value = (nfapi_nr_ul_tti_request_number_of_groups_t *)tlv; - if(!push8(value->n_ue, ppWritePackedMsg, end)) - return 0; - for(int i=0; in_ue;i++) - { - if(!push8(value->ue_list[i].pdu_idx, ppWritePackedMsg, end)) - return 0; - } - return 1; + if(!push8(value->n_ue, ppWritePackedMsg, end)) + return 0; + + for(int i=0; in_ue; i++) { + if(!push8(value->ue_list[i].pdu_idx, ppWritePackedMsg, end)) + return 0; + } + + return 1; } -static uint8_t pack_ul_config_request_body_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_ul_config_request_body_t* value = (nfapi_ul_config_request_body_t*)tlv; +static uint8_t pack_ul_config_request_body_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_ul_config_request_body_t *value = (nfapi_ul_config_request_body_t *)tlv; - if(!(push8(value->number_of_pdus, ppWritePackedMsg, end) && - push8(value->rach_prach_frequency_resources, ppWritePackedMsg, end) && - push8(value->srs_present, ppWritePackedMsg, end))) - return 0; + if(!(push8(value->number_of_pdus, ppWritePackedMsg, end) && + push8(value->rach_prach_frequency_resources, ppWritePackedMsg, end) && + push8(value->srs_present, ppWritePackedMsg, end))) + return 0; - uint16_t i = 0; - for(i = 0; i < value->number_of_pdus; ++i) - { - nfapi_ul_config_request_pdu_t* pdu = &(value->ul_config_pdu_list[i]); + uint16_t i = 0; - if(push8(pdu->pdu_type, ppWritePackedMsg, end) == 0) - return 0; + for(i = 0; i < value->number_of_pdus; ++i) { + nfapi_ul_config_request_pdu_t *pdu = &(value->ul_config_pdu_list[i]); - // Put a 0 size in and then determine the size after the pdu - // has been writen and write the calculated size - uint8_t* pWritePackedMsgPduSize = *ppWritePackedMsg; - pdu->pdu_size = 0; - if(push8(pdu->pdu_size, ppWritePackedMsg, end) == 0) - return 0; + if(push8(pdu->pdu_type, ppWritePackedMsg, end) == 0) + return 0; - switch(pdu->pdu_type) - { - case NFAPI_UL_CONFIG_ULSCH_PDU_TYPE: - { - if(!pack_ul_config_request_ulsch_pdu(&(pdu->ulsch_pdu), ppWritePackedMsg, end)) - return 0; - } - break; - case NFAPI_UL_CONFIG_ULSCH_CQI_RI_PDU_TYPE: - { - if(!(pack_ul_config_request_ulsch_pdu(&(pdu->ulsch_cqi_ri_pdu.ulsch_pdu), ppWritePackedMsg, end) && - pack_ul_config_request_cqi_ri_information(&(pdu->ulsch_cqi_ri_pdu.cqi_ri_information), ppWritePackedMsg, end) && - pack_ul_config_request_initial_transmission_parameters(&(pdu->ulsch_cqi_ri_pdu.initial_transmission_parameters), ppWritePackedMsg, end))) - return 0; - } - break; - case NFAPI_UL_CONFIG_ULSCH_HARQ_PDU_TYPE: - { - if(!(pack_ul_config_request_ulsch_pdu(&(pdu->ulsch_harq_pdu.ulsch_pdu), ppWritePackedMsg, end) && - pack_ul_config_request_ulsch_harq_information(&(pdu->ulsch_harq_pdu.harq_information), ppWritePackedMsg, end) && - pack_ul_config_request_initial_transmission_parameters(&(pdu->ulsch_harq_pdu.initial_transmission_parameters), ppWritePackedMsg, end))) - return 0; - } - break; - case NFAPI_UL_CONFIG_ULSCH_CQI_HARQ_RI_PDU_TYPE: - { - if(!(pack_ul_config_request_ulsch_pdu(&(pdu->ulsch_cqi_harq_ri_pdu.ulsch_pdu), ppWritePackedMsg, end) && - pack_ul_config_request_cqi_ri_information(&(pdu->ulsch_cqi_harq_ri_pdu.cqi_ri_information), ppWritePackedMsg, end) && - pack_ul_config_request_ulsch_harq_information(&(pdu->ulsch_cqi_harq_ri_pdu.harq_information), ppWritePackedMsg, end) && - pack_ul_config_request_initial_transmission_parameters(&(pdu->ulsch_cqi_harq_ri_pdu.initial_transmission_parameters), ppWritePackedMsg, end))) - return 0; - } - break; - case NFAPI_UL_CONFIG_UCI_CQI_PDU_TYPE: - { - if(!(pack_ul_config_request_ue_information(&(pdu->uci_cqi_pdu.ue_information), ppWritePackedMsg, end) && - pack_ul_config_request_cqi_information(&(pdu->uci_cqi_pdu.cqi_information), ppWritePackedMsg, end))) - return 0; - } - break; - case NFAPI_UL_CONFIG_UCI_SR_PDU_TYPE: - { - if(!(pack_ul_config_request_ue_information(&(pdu->uci_sr_pdu.ue_information), ppWritePackedMsg, end) && - pack_ul_config_request_sr_information(&(pdu->uci_sr_pdu.sr_information), ppWritePackedMsg, end))) - return 0; - } - break; - case NFAPI_UL_CONFIG_UCI_HARQ_PDU_TYPE: - { - if(!(pack_ul_config_request_ue_information(&(pdu->uci_harq_pdu.ue_information), ppWritePackedMsg, end) && - pack_ul_config_request_harq_information(&(pdu->uci_harq_pdu.harq_information), ppWritePackedMsg, end))) - return 0; - } - break; - case NFAPI_UL_CONFIG_UCI_SR_HARQ_PDU_TYPE: - { - if(!(pack_ul_config_request_ue_information(&(pdu->uci_sr_harq_pdu.ue_information), ppWritePackedMsg, end) && - pack_ul_config_request_sr_information(&(pdu->uci_sr_harq_pdu.sr_information), ppWritePackedMsg, end) && - pack_ul_config_request_harq_information(&(pdu->uci_sr_harq_pdu.harq_information), ppWritePackedMsg, end))) - return 0; - } - break; - case NFAPI_UL_CONFIG_UCI_CQI_HARQ_PDU_TYPE: - { - if(!(pack_ul_config_request_ue_information(&(pdu->uci_cqi_harq_pdu.ue_information), ppWritePackedMsg, end) && - pack_ul_config_request_cqi_information(&(pdu->uci_cqi_harq_pdu.cqi_information), ppWritePackedMsg, end) && - pack_ul_config_request_harq_information(&(pdu->uci_cqi_harq_pdu.harq_information), ppWritePackedMsg, end))) - return 0; - } - break; - case NFAPI_UL_CONFIG_UCI_CQI_SR_PDU_TYPE: - { - if(!(pack_ul_config_request_ue_information(&(pdu->uci_cqi_sr_pdu.ue_information), ppWritePackedMsg, end) && - pack_ul_config_request_cqi_information(&(pdu->uci_cqi_sr_pdu.cqi_information), ppWritePackedMsg, end) && - pack_ul_config_request_sr_information(&(pdu->uci_cqi_sr_pdu.sr_information), ppWritePackedMsg, end))) - return 0; - } - break; - case NFAPI_UL_CONFIG_UCI_CQI_SR_HARQ_PDU_TYPE: - { - if(!(pack_ul_config_request_ue_information(&(pdu->uci_cqi_sr_harq_pdu.ue_information), ppWritePackedMsg, end) && - pack_ul_config_request_cqi_information(&(pdu->uci_cqi_sr_harq_pdu.cqi_information), ppWritePackedMsg, end) && - pack_ul_config_request_sr_information(&(pdu->uci_cqi_sr_harq_pdu.sr_information), ppWritePackedMsg, end) && - pack_ul_config_request_harq_information(&(pdu->uci_cqi_sr_harq_pdu.harq_information), ppWritePackedMsg, end))) - return 0; - } - break; - case NFAPI_UL_CONFIG_SRS_PDU_TYPE: - { - if(!(pack_tlv(NFAPI_UL_CONFIG_REQUEST_SRS_PDU_REL8_TAG, &pdu->srs_pdu.srs_pdu_rel8, ppWritePackedMsg, end, &pack_ul_config_request_srs_pdu_rel8_value) && - pack_tlv(NFAPI_UL_CONFIG_REQUEST_SRS_PDU_REL10_TAG, &pdu->srs_pdu.srs_pdu_rel10, ppWritePackedMsg, end, &pack_ul_config_request_srs_pdu_rel10_value) && - pack_tlv(NFAPI_UL_CONFIG_REQUEST_SRS_PDU_REL13_TAG, &pdu->srs_pdu.srs_pdu_rel13, ppWritePackedMsg, end, &pack_ul_config_request_srs_pdu_rel13_value))) - return 0; - } - break; - case NFAPI_UL_CONFIG_HARQ_BUFFER_PDU_TYPE: - { - if(!(pack_ul_config_request_ue_information(&(pdu->harq_buffer_pdu.ue_information), ppWritePackedMsg, end))) - return 0; - } - break; - case NFAPI_UL_CONFIG_ULSCH_UCI_CSI_PDU_TYPE: - { - if(!(pack_ul_config_request_ulsch_pdu(&(pdu->ulsch_uci_csi_pdu.ulsch_pdu), ppWritePackedMsg, end) && - pack_ul_config_request_cqi_information(&(pdu->ulsch_uci_csi_pdu.csi_information), ppWritePackedMsg, end))) - return 0; - } - break; - case NFAPI_UL_CONFIG_ULSCH_UCI_HARQ_PDU_TYPE: - { - if(!(pack_ul_config_request_ulsch_pdu(&(pdu->ulsch_uci_harq_pdu.ulsch_pdu), ppWritePackedMsg, end) && - pack_ul_config_request_harq_information(&(pdu->ulsch_uci_harq_pdu.harq_information), ppWritePackedMsg, end))) - return 0; - } - break; - case NFAPI_UL_CONFIG_ULSCH_CSI_UCI_HARQ_PDU_TYPE: - { - if(!(pack_ul_config_request_ulsch_pdu(&(pdu->ulsch_csi_uci_harq_pdu.ulsch_pdu), ppWritePackedMsg, end) && - pack_ul_config_request_cqi_information(&(pdu->ulsch_csi_uci_harq_pdu.csi_information), ppWritePackedMsg, end) && - pack_ul_config_request_harq_information(&(pdu->ulsch_csi_uci_harq_pdu.harq_information), ppWritePackedMsg, end))) - return 0; - } - break; - case NFAPI_UL_CONFIG_NULSCH_PDU_TYPE: - { - if(!(pack_tlv(NFAPI_UL_CONFIG_REQUEST_NULSCH_PDU_REL13_TAG, &pdu->nulsch_pdu.nulsch_pdu_rel13, ppWritePackedMsg, end, &pack_ul_config_request_nulsch_pdu_rel13_value))) - return 0; - } - break; - case NFAPI_UL_CONFIG_NRACH_PDU_TYPE: - { - if(!(pack_tlv(NFAPI_UL_CONFIG_REQUEST_NRACH_PDU_REL13_TAG, &pdu->nrach_pdu.nrach_pdu_rel13, ppWritePackedMsg, end, &pack_ul_config_request_nrach_pdu_rel13_value))) - return 0; - } - break; - default: - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "FIXME : Invalid pdu type %d \n", pdu->pdu_type ); - } - break; - }; + // Put a 0 size in and then determine the size after the pdu + // has been writen and write the calculated size + uint8_t *pWritePackedMsgPduSize = *ppWritePackedMsg; + pdu->pdu_size = 0; - // add 1 for the pdu_type. The delta will include the pdu_size - pdu->pdu_size = 1 + (*ppWritePackedMsg - pWritePackedMsgPduSize); - push8(pdu->pdu_size, &pWritePackedMsgPduSize, end); - - } - return 1; + if(push8(pdu->pdu_size, ppWritePackedMsg, end) == 0) + return 0; + + switch(pdu->pdu_type) { + case NFAPI_UL_CONFIG_ULSCH_PDU_TYPE: { + if(!pack_ul_config_request_ulsch_pdu(&(pdu->ulsch_pdu), ppWritePackedMsg, end)) + return 0; + } + break; + + case NFAPI_UL_CONFIG_ULSCH_CQI_RI_PDU_TYPE: { + if(!(pack_ul_config_request_ulsch_pdu(&(pdu->ulsch_cqi_ri_pdu.ulsch_pdu), ppWritePackedMsg, end) && + pack_ul_config_request_cqi_ri_information(&(pdu->ulsch_cqi_ri_pdu.cqi_ri_information), ppWritePackedMsg, end) && + pack_ul_config_request_initial_transmission_parameters(&(pdu->ulsch_cqi_ri_pdu.initial_transmission_parameters), ppWritePackedMsg, end))) + return 0; + } + break; + + case NFAPI_UL_CONFIG_ULSCH_HARQ_PDU_TYPE: { + if(!(pack_ul_config_request_ulsch_pdu(&(pdu->ulsch_harq_pdu.ulsch_pdu), ppWritePackedMsg, end) && + pack_ul_config_request_ulsch_harq_information(&(pdu->ulsch_harq_pdu.harq_information), ppWritePackedMsg, end) && + pack_ul_config_request_initial_transmission_parameters(&(pdu->ulsch_harq_pdu.initial_transmission_parameters), ppWritePackedMsg, end))) + return 0; + } + break; + + case NFAPI_UL_CONFIG_ULSCH_CQI_HARQ_RI_PDU_TYPE: { + if(!(pack_ul_config_request_ulsch_pdu(&(pdu->ulsch_cqi_harq_ri_pdu.ulsch_pdu), ppWritePackedMsg, end) && + pack_ul_config_request_cqi_ri_information(&(pdu->ulsch_cqi_harq_ri_pdu.cqi_ri_information), ppWritePackedMsg, end) && + pack_ul_config_request_ulsch_harq_information(&(pdu->ulsch_cqi_harq_ri_pdu.harq_information), ppWritePackedMsg, end) && + pack_ul_config_request_initial_transmission_parameters(&(pdu->ulsch_cqi_harq_ri_pdu.initial_transmission_parameters), ppWritePackedMsg, end))) + return 0; + } + break; + + case NFAPI_UL_CONFIG_UCI_CQI_PDU_TYPE: { + if(!(pack_ul_config_request_ue_information(&(pdu->uci_cqi_pdu.ue_information), ppWritePackedMsg, end) && + pack_ul_config_request_cqi_information(&(pdu->uci_cqi_pdu.cqi_information), ppWritePackedMsg, end))) + return 0; + } + break; + + case NFAPI_UL_CONFIG_UCI_SR_PDU_TYPE: { + if(!(pack_ul_config_request_ue_information(&(pdu->uci_sr_pdu.ue_information), ppWritePackedMsg, end) && + pack_ul_config_request_sr_information(&(pdu->uci_sr_pdu.sr_information), ppWritePackedMsg, end))) + return 0; + } + break; + + case NFAPI_UL_CONFIG_UCI_HARQ_PDU_TYPE: { + if(!(pack_ul_config_request_ue_information(&(pdu->uci_harq_pdu.ue_information), ppWritePackedMsg, end) && + pack_ul_config_request_harq_information(&(pdu->uci_harq_pdu.harq_information), ppWritePackedMsg, end))) + return 0; + } + break; + + case NFAPI_UL_CONFIG_UCI_SR_HARQ_PDU_TYPE: { + if(!(pack_ul_config_request_ue_information(&(pdu->uci_sr_harq_pdu.ue_information), ppWritePackedMsg, end) && + pack_ul_config_request_sr_information(&(pdu->uci_sr_harq_pdu.sr_information), ppWritePackedMsg, end) && + pack_ul_config_request_harq_information(&(pdu->uci_sr_harq_pdu.harq_information), ppWritePackedMsg, end))) + return 0; + } + break; + + case NFAPI_UL_CONFIG_UCI_CQI_HARQ_PDU_TYPE: { + if(!(pack_ul_config_request_ue_information(&(pdu->uci_cqi_harq_pdu.ue_information), ppWritePackedMsg, end) && + pack_ul_config_request_cqi_information(&(pdu->uci_cqi_harq_pdu.cqi_information), ppWritePackedMsg, end) && + pack_ul_config_request_harq_information(&(pdu->uci_cqi_harq_pdu.harq_information), ppWritePackedMsg, end))) + return 0; + } + break; + + case NFAPI_UL_CONFIG_UCI_CQI_SR_PDU_TYPE: { + if(!(pack_ul_config_request_ue_information(&(pdu->uci_cqi_sr_pdu.ue_information), ppWritePackedMsg, end) && + pack_ul_config_request_cqi_information(&(pdu->uci_cqi_sr_pdu.cqi_information), ppWritePackedMsg, end) && + pack_ul_config_request_sr_information(&(pdu->uci_cqi_sr_pdu.sr_information), ppWritePackedMsg, end))) + return 0; + } + break; + + case NFAPI_UL_CONFIG_UCI_CQI_SR_HARQ_PDU_TYPE: { + if(!(pack_ul_config_request_ue_information(&(pdu->uci_cqi_sr_harq_pdu.ue_information), ppWritePackedMsg, end) && + pack_ul_config_request_cqi_information(&(pdu->uci_cqi_sr_harq_pdu.cqi_information), ppWritePackedMsg, end) && + pack_ul_config_request_sr_information(&(pdu->uci_cqi_sr_harq_pdu.sr_information), ppWritePackedMsg, end) && + pack_ul_config_request_harq_information(&(pdu->uci_cqi_sr_harq_pdu.harq_information), ppWritePackedMsg, end))) + return 0; + } + break; + + case NFAPI_UL_CONFIG_SRS_PDU_TYPE: { + if(!(pack_tlv(NFAPI_UL_CONFIG_REQUEST_SRS_PDU_REL8_TAG, &pdu->srs_pdu.srs_pdu_rel8, ppWritePackedMsg, end, &pack_ul_config_request_srs_pdu_rel8_value) && + pack_tlv(NFAPI_UL_CONFIG_REQUEST_SRS_PDU_REL10_TAG, &pdu->srs_pdu.srs_pdu_rel10, ppWritePackedMsg, end, &pack_ul_config_request_srs_pdu_rel10_value) && + pack_tlv(NFAPI_UL_CONFIG_REQUEST_SRS_PDU_REL13_TAG, &pdu->srs_pdu.srs_pdu_rel13, ppWritePackedMsg, end, &pack_ul_config_request_srs_pdu_rel13_value))) + return 0; + } + break; + + case NFAPI_UL_CONFIG_HARQ_BUFFER_PDU_TYPE: { + if(!(pack_ul_config_request_ue_information(&(pdu->harq_buffer_pdu.ue_information), ppWritePackedMsg, end))) + return 0; + } + break; + + case NFAPI_UL_CONFIG_ULSCH_UCI_CSI_PDU_TYPE: { + if(!(pack_ul_config_request_ulsch_pdu(&(pdu->ulsch_uci_csi_pdu.ulsch_pdu), ppWritePackedMsg, end) && + pack_ul_config_request_cqi_information(&(pdu->ulsch_uci_csi_pdu.csi_information), ppWritePackedMsg, end))) + return 0; + } + break; + + case NFAPI_UL_CONFIG_ULSCH_UCI_HARQ_PDU_TYPE: { + if(!(pack_ul_config_request_ulsch_pdu(&(pdu->ulsch_uci_harq_pdu.ulsch_pdu), ppWritePackedMsg, end) && + pack_ul_config_request_harq_information(&(pdu->ulsch_uci_harq_pdu.harq_information), ppWritePackedMsg, end))) + return 0; + } + break; + + case NFAPI_UL_CONFIG_ULSCH_CSI_UCI_HARQ_PDU_TYPE: { + if(!(pack_ul_config_request_ulsch_pdu(&(pdu->ulsch_csi_uci_harq_pdu.ulsch_pdu), ppWritePackedMsg, end) && + pack_ul_config_request_cqi_information(&(pdu->ulsch_csi_uci_harq_pdu.csi_information), ppWritePackedMsg, end) && + pack_ul_config_request_harq_information(&(pdu->ulsch_csi_uci_harq_pdu.harq_information), ppWritePackedMsg, end))) + return 0; + } + break; + + case NFAPI_UL_CONFIG_NULSCH_PDU_TYPE: { + if(!(pack_tlv(NFAPI_UL_CONFIG_REQUEST_NULSCH_PDU_REL13_TAG, &pdu->nulsch_pdu.nulsch_pdu_rel13, ppWritePackedMsg, end, &pack_ul_config_request_nulsch_pdu_rel13_value))) + return 0; + } + break; + + case NFAPI_UL_CONFIG_NRACH_PDU_TYPE: { + if(!(pack_tlv(NFAPI_UL_CONFIG_REQUEST_NRACH_PDU_REL13_TAG, &pdu->nrach_pdu.nrach_pdu_rel13, ppWritePackedMsg, end, &pack_ul_config_request_nrach_pdu_rel13_value))) + return 0; + } + break; + + default: { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "FIXME : Invalid pdu type %d \n", pdu->pdu_type ); + } + break; + }; + + // add 1 for the pdu_type. The delta will include the pdu_size + pdu->pdu_size = 1 + (*ppWritePackedMsg - pWritePackedMsgPduSize); + + push8(pdu->pdu_size, &pWritePackedMsgPduSize, end); + } + + return 1; } -static uint8_t pack_ul_tti_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) -{ - nfapi_nr_ul_tti_request_t *pNfapiMsg = (nfapi_nr_ul_tti_request_t*)msg; +static uint8_t pack_ul_tti_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t *config) { + nfapi_nr_ul_tti_request_t *pNfapiMsg = (nfapi_nr_ul_tti_request_t *)msg; - if (!(push16(pNfapiMsg->SFN , ppWritePackedMsg, end) && - push16(pNfapiMsg->Slot , ppWritePackedMsg, end) && - push8(pNfapiMsg->n_pdus , ppWritePackedMsg, end) && - push8(pNfapiMsg->rach_present, ppWritePackedMsg, end) && - push8(pNfapiMsg->n_ulsch, ppWritePackedMsg, end) && - push8(pNfapiMsg->n_ulcch, ppWritePackedMsg, end) && - push8(pNfapiMsg->n_group, ppWritePackedMsg, end) )) - return 0; - - for(int i=0; in_pdus; i++) - { - if(!pack_ul_tti_pdu_list_value(&pNfapiMsg->pdus_list[i], ppWritePackedMsg, end)) - return 0; - } + if (!(push16(pNfapiMsg->SFN, ppWritePackedMsg, end) && + push16(pNfapiMsg->Slot, ppWritePackedMsg, end) && + push8(pNfapiMsg->n_pdus, ppWritePackedMsg, end) && + push8(pNfapiMsg->rach_present, ppWritePackedMsg, end) && + push8(pNfapiMsg->n_ulsch, ppWritePackedMsg, end) && + push8(pNfapiMsg->n_ulcch, ppWritePackedMsg, end) && + push8(pNfapiMsg->n_group, ppWritePackedMsg, end) )) + return 0; - for(int i=0; in_group; i++) - { - if(!pack_ul_tti_groups_list_value(&pNfapiMsg->groups_list[i], ppWritePackedMsg, end)) - return 0; + for(int i=0; in_pdus; i++) { + if(!pack_ul_tti_pdu_list_value(&pNfapiMsg->pdus_list[i], ppWritePackedMsg, end)) + return 0; + } - } + for(int i=0; in_group; i++) { + if(!pack_ul_tti_groups_list_value(&pNfapiMsg->groups_list[i], ppWritePackedMsg, end)) + return 0; + } - return 1; + return 1; } -static uint8_t pack_ul_config_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) -{ - nfapi_ul_config_request_t *pNfapiMsg = (nfapi_ul_config_request_t*)msg; - - return ( push16(pNfapiMsg->sfn_sf, ppWritePackedMsg, end) && - pack_tlv(NFAPI_UL_CONFIG_REQUEST_BODY_TAG, &pNfapiMsg->ul_config_request_body, ppWritePackedMsg, end, &pack_ul_config_request_body_value) && - pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)) ; +static uint8_t pack_ul_config_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t *config) { + nfapi_ul_config_request_t *pNfapiMsg = (nfapi_ul_config_request_t *)msg; + return ( push16(pNfapiMsg->sfn_sf, ppWritePackedMsg, end) && + pack_tlv(NFAPI_UL_CONFIG_REQUEST_BODY_TAG, &pNfapiMsg->ul_config_request_body, ppWritePackedMsg, end, &pack_ul_config_request_body_value) && + pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)) ; } -static uint8_t pack_hi_dci0_hi_rel8_pdu_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_hi_dci0_hi_pdu_rel8_t* hi_pdu_rel8 = (nfapi_hi_dci0_hi_pdu_rel8_t*)tlv; - - return ( push8(hi_pdu_rel8->resource_block_start, ppWritePackedMsg, end) && - push8(hi_pdu_rel8->cyclic_shift_2_for_drms, ppWritePackedMsg, end) && - push8(hi_pdu_rel8->hi_value, ppWritePackedMsg, end) && - push8(hi_pdu_rel8->i_phich, ppWritePackedMsg, end) && - push16(hi_pdu_rel8->transmission_power, ppWritePackedMsg, end)); +static uint8_t pack_hi_dci0_hi_rel8_pdu_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_hi_dci0_hi_pdu_rel8_t *hi_pdu_rel8 = (nfapi_hi_dci0_hi_pdu_rel8_t *)tlv; + return ( push8(hi_pdu_rel8->resource_block_start, ppWritePackedMsg, end) && + push8(hi_pdu_rel8->cyclic_shift_2_for_drms, ppWritePackedMsg, end) && + push8(hi_pdu_rel8->hi_value, ppWritePackedMsg, end) && + push8(hi_pdu_rel8->i_phich, ppWritePackedMsg, end) && + push16(hi_pdu_rel8->transmission_power, ppWritePackedMsg, end)); } -static uint8_t pack_hi_dci0_hi_rel10_pdu_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_hi_dci0_hi_pdu_rel10_t* hi_pdu_rel10 = (nfapi_hi_dci0_hi_pdu_rel10_t*)tlv; - - return ( push8(hi_pdu_rel10->flag_tb2, ppWritePackedMsg, end) && - push8(hi_pdu_rel10->hi_value_2, ppWritePackedMsg, end)); +static uint8_t pack_hi_dci0_hi_rel10_pdu_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_hi_dci0_hi_pdu_rel10_t *hi_pdu_rel10 = (nfapi_hi_dci0_hi_pdu_rel10_t *)tlv; + return ( push8(hi_pdu_rel10->flag_tb2, ppWritePackedMsg, end) && + push8(hi_pdu_rel10->hi_value_2, ppWritePackedMsg, end)); } -static uint8_t pack_hi_dci0_dci_rel8_pdu_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_hi_dci0_dci_pdu_rel8_t* dci_pdu_rel8 = (nfapi_hi_dci0_dci_pdu_rel8_t*)tlv; - - return ( push8(dci_pdu_rel8->dci_format, ppWritePackedMsg, end) && - push8(dci_pdu_rel8->cce_index, ppWritePackedMsg, end) && - push8(dci_pdu_rel8->aggregation_level, ppWritePackedMsg, end) && - push16(dci_pdu_rel8->rnti, ppWritePackedMsg, end) && - push8(dci_pdu_rel8->resource_block_start, ppWritePackedMsg, end) && - push8(dci_pdu_rel8->number_of_resource_block, ppWritePackedMsg, end) && - push8(dci_pdu_rel8->mcs_1, ppWritePackedMsg, end) && - push8(dci_pdu_rel8->cyclic_shift_2_for_drms, ppWritePackedMsg, end) && - push8(dci_pdu_rel8->frequency_hopping_enabled_flag, ppWritePackedMsg, end) && - push8(dci_pdu_rel8->frequency_hopping_bits, ppWritePackedMsg, end) && - push8(dci_pdu_rel8->new_data_indication_1, ppWritePackedMsg, end) && - push8(dci_pdu_rel8->ue_tx_antenna_seleciton, ppWritePackedMsg, end) && - push8(dci_pdu_rel8->tpc, ppWritePackedMsg, end) && - push8(dci_pdu_rel8->cqi_csi_request, ppWritePackedMsg, end) && - push8(dci_pdu_rel8->ul_index, ppWritePackedMsg, end) && - push8(dci_pdu_rel8->dl_assignment_index, ppWritePackedMsg, end) && - push32(dci_pdu_rel8->tpc_bitmap, ppWritePackedMsg, end) && - push16(dci_pdu_rel8->transmission_power, ppWritePackedMsg, end)); +static uint8_t pack_hi_dci0_dci_rel8_pdu_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_hi_dci0_dci_pdu_rel8_t *dci_pdu_rel8 = (nfapi_hi_dci0_dci_pdu_rel8_t *)tlv; + return ( push8(dci_pdu_rel8->dci_format, ppWritePackedMsg, end) && + push8(dci_pdu_rel8->cce_index, ppWritePackedMsg, end) && + push8(dci_pdu_rel8->aggregation_level, ppWritePackedMsg, end) && + push16(dci_pdu_rel8->rnti, ppWritePackedMsg, end) && + push8(dci_pdu_rel8->resource_block_start, ppWritePackedMsg, end) && + push8(dci_pdu_rel8->number_of_resource_block, ppWritePackedMsg, end) && + push8(dci_pdu_rel8->mcs_1, ppWritePackedMsg, end) && + push8(dci_pdu_rel8->cyclic_shift_2_for_drms, ppWritePackedMsg, end) && + push8(dci_pdu_rel8->frequency_hopping_enabled_flag, ppWritePackedMsg, end) && + push8(dci_pdu_rel8->frequency_hopping_bits, ppWritePackedMsg, end) && + push8(dci_pdu_rel8->new_data_indication_1, ppWritePackedMsg, end) && + push8(dci_pdu_rel8->ue_tx_antenna_seleciton, ppWritePackedMsg, end) && + push8(dci_pdu_rel8->tpc, ppWritePackedMsg, end) && + push8(dci_pdu_rel8->cqi_csi_request, ppWritePackedMsg, end) && + push8(dci_pdu_rel8->ul_index, ppWritePackedMsg, end) && + push8(dci_pdu_rel8->dl_assignment_index, ppWritePackedMsg, end) && + push32(dci_pdu_rel8->tpc_bitmap, ppWritePackedMsg, end) && + push16(dci_pdu_rel8->transmission_power, ppWritePackedMsg, end)); } -static uint8_t pack_hi_dci0_dci_rel10_pdu_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_hi_dci0_dci_pdu_rel10_t* dci_pdu_rel10 = (nfapi_hi_dci0_dci_pdu_rel10_t*)tlv; - - return ( push8(dci_pdu_rel10->cross_carrier_scheduling_flag, ppWritePackedMsg, end) && - push8(dci_pdu_rel10->carrier_indicator, ppWritePackedMsg, end) && - push8(dci_pdu_rel10->size_of_cqi_csi_feild, ppWritePackedMsg, end) && - push8(dci_pdu_rel10->srs_flag, ppWritePackedMsg, end) && - push8(dci_pdu_rel10->srs_request, ppWritePackedMsg, end) && - push8(dci_pdu_rel10->resource_allocation_flag, ppWritePackedMsg, end) && - push8(dci_pdu_rel10->resource_allocation_type, ppWritePackedMsg, end) && - push32(dci_pdu_rel10->resource_block_coding, ppWritePackedMsg, end) && - push8(dci_pdu_rel10->mcs_2, ppWritePackedMsg, end) && - push8(dci_pdu_rel10->new_data_indication_2, ppWritePackedMsg, end) && - push8(dci_pdu_rel10->number_of_antenna_ports, ppWritePackedMsg, end) && - push8(dci_pdu_rel10->tpmi, ppWritePackedMsg, end) && - push8(dci_pdu_rel10->total_dci_length_including_padding, ppWritePackedMsg, end) && - push8(dci_pdu_rel10->n_ul_rb, ppWritePackedMsg, end)); +static uint8_t pack_hi_dci0_dci_rel10_pdu_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_hi_dci0_dci_pdu_rel10_t *dci_pdu_rel10 = (nfapi_hi_dci0_dci_pdu_rel10_t *)tlv; + return ( push8(dci_pdu_rel10->cross_carrier_scheduling_flag, ppWritePackedMsg, end) && + push8(dci_pdu_rel10->carrier_indicator, ppWritePackedMsg, end) && + push8(dci_pdu_rel10->size_of_cqi_csi_feild, ppWritePackedMsg, end) && + push8(dci_pdu_rel10->srs_flag, ppWritePackedMsg, end) && + push8(dci_pdu_rel10->srs_request, ppWritePackedMsg, end) && + push8(dci_pdu_rel10->resource_allocation_flag, ppWritePackedMsg, end) && + push8(dci_pdu_rel10->resource_allocation_type, ppWritePackedMsg, end) && + push32(dci_pdu_rel10->resource_block_coding, ppWritePackedMsg, end) && + push8(dci_pdu_rel10->mcs_2, ppWritePackedMsg, end) && + push8(dci_pdu_rel10->new_data_indication_2, ppWritePackedMsg, end) && + push8(dci_pdu_rel10->number_of_antenna_ports, ppWritePackedMsg, end) && + push8(dci_pdu_rel10->tpmi, ppWritePackedMsg, end) && + push8(dci_pdu_rel10->total_dci_length_including_padding, ppWritePackedMsg, end) && + push8(dci_pdu_rel10->n_ul_rb, ppWritePackedMsg, end)); } -static uint8_t pack_hi_dci0_dci_rel12_pdu_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_hi_dci0_dci_pdu_rel12_t* dci_pdu_rel12 = (nfapi_hi_dci0_dci_pdu_rel12_t*)tlv; - - return ( push8(dci_pdu_rel12->pscch_resource, ppWritePackedMsg, end) && - push8(dci_pdu_rel12->time_resource_pattern, ppWritePackedMsg, end)); +static uint8_t pack_hi_dci0_dci_rel12_pdu_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_hi_dci0_dci_pdu_rel12_t *dci_pdu_rel12 = (nfapi_hi_dci0_dci_pdu_rel12_t *)tlv; + return ( push8(dci_pdu_rel12->pscch_resource, ppWritePackedMsg, end) && + push8(dci_pdu_rel12->time_resource_pattern, ppWritePackedMsg, end)); } -static uint8_t pack_hi_dci0_mpdcch_dci_rel13_pdu_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_hi_dci0_mpdcch_dci_pdu_rel13_t* mpdcch_dci_pdu_rel13 = (nfapi_hi_dci0_mpdcch_dci_pdu_rel13_t*)tlv; - - return ( push8(mpdcch_dci_pdu_rel13->mpdcch_narrowband, ppWritePackedMsg, end) && - push8(mpdcch_dci_pdu_rel13->number_of_prb_pairs, ppWritePackedMsg, end) && - push8(mpdcch_dci_pdu_rel13->resource_block_assignment, ppWritePackedMsg, end) && - push8(mpdcch_dci_pdu_rel13->mpdcch_transmission_type, ppWritePackedMsg, end) && - push8(mpdcch_dci_pdu_rel13->start_symbol, ppWritePackedMsg, end) && - push8(mpdcch_dci_pdu_rel13->ecce_index, ppWritePackedMsg, end) && - push8(mpdcch_dci_pdu_rel13->aggreagation_level, ppWritePackedMsg, end) && - push8(mpdcch_dci_pdu_rel13->rnti_type, ppWritePackedMsg, end) && - push16(mpdcch_dci_pdu_rel13->rnti, ppWritePackedMsg, end) && - push8(mpdcch_dci_pdu_rel13->ce_mode, ppWritePackedMsg, end) && - push16(mpdcch_dci_pdu_rel13->drms_scrambling_init, ppWritePackedMsg, end) && - push16(mpdcch_dci_pdu_rel13->initial_transmission_sf_io, ppWritePackedMsg, end) && - push16(mpdcch_dci_pdu_rel13->transmission_power, ppWritePackedMsg, end) && - push8(mpdcch_dci_pdu_rel13->dci_format, ppWritePackedMsg, end) && - push8(mpdcch_dci_pdu_rel13->resource_block_start, ppWritePackedMsg, end) && - push8(mpdcch_dci_pdu_rel13->number_of_resource_blocks, ppWritePackedMsg, end) && - push8(mpdcch_dci_pdu_rel13->mcs, ppWritePackedMsg, end) && - push8(mpdcch_dci_pdu_rel13->pusch_repetition_levels, ppWritePackedMsg, end) && - push8(mpdcch_dci_pdu_rel13->frequency_hopping_flag, ppWritePackedMsg, end) && - push8(mpdcch_dci_pdu_rel13->new_data_indication, ppWritePackedMsg, end) && - push8(mpdcch_dci_pdu_rel13->harq_process, ppWritePackedMsg, end) && - push8(mpdcch_dci_pdu_rel13->redudency_version, ppWritePackedMsg, end) && - push8(mpdcch_dci_pdu_rel13->tpc, ppWritePackedMsg, end) && - push8(mpdcch_dci_pdu_rel13->csi_request, ppWritePackedMsg, end) && - push8(mpdcch_dci_pdu_rel13->ul_inex, ppWritePackedMsg, end) && - push8(mpdcch_dci_pdu_rel13->dai_presence_flag, ppWritePackedMsg, end) && - push8(mpdcch_dci_pdu_rel13->dl_assignment_index, ppWritePackedMsg, end) && - push8(mpdcch_dci_pdu_rel13->srs_request, ppWritePackedMsg, end) && - push8(mpdcch_dci_pdu_rel13->dci_subframe_repetition_number, ppWritePackedMsg, end) && - push32(mpdcch_dci_pdu_rel13->tcp_bitmap, ppWritePackedMsg, end) && - push8(mpdcch_dci_pdu_rel13->total_dci_length_include_padding, ppWritePackedMsg, end) && - push8(mpdcch_dci_pdu_rel13->number_of_tx_antenna_ports, ppWritePackedMsg, end) && - pusharray16(mpdcch_dci_pdu_rel13->precoding_value, NFAPI_MAX_TX_PHYSICAL_ANTENNA_PORTS, mpdcch_dci_pdu_rel13->number_of_tx_antenna_ports, ppWritePackedMsg, end)); - +static uint8_t pack_hi_dci0_mpdcch_dci_rel13_pdu_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_hi_dci0_mpdcch_dci_pdu_rel13_t *mpdcch_dci_pdu_rel13 = (nfapi_hi_dci0_mpdcch_dci_pdu_rel13_t *)tlv; + return ( push8(mpdcch_dci_pdu_rel13->mpdcch_narrowband, ppWritePackedMsg, end) && + push8(mpdcch_dci_pdu_rel13->number_of_prb_pairs, ppWritePackedMsg, end) && + push8(mpdcch_dci_pdu_rel13->resource_block_assignment, ppWritePackedMsg, end) && + push8(mpdcch_dci_pdu_rel13->mpdcch_transmission_type, ppWritePackedMsg, end) && + push8(mpdcch_dci_pdu_rel13->start_symbol, ppWritePackedMsg, end) && + push8(mpdcch_dci_pdu_rel13->ecce_index, ppWritePackedMsg, end) && + push8(mpdcch_dci_pdu_rel13->aggreagation_level, ppWritePackedMsg, end) && + push8(mpdcch_dci_pdu_rel13->rnti_type, ppWritePackedMsg, end) && + push16(mpdcch_dci_pdu_rel13->rnti, ppWritePackedMsg, end) && + push8(mpdcch_dci_pdu_rel13->ce_mode, ppWritePackedMsg, end) && + push16(mpdcch_dci_pdu_rel13->drms_scrambling_init, ppWritePackedMsg, end) && + push16(mpdcch_dci_pdu_rel13->initial_transmission_sf_io, ppWritePackedMsg, end) && + push16(mpdcch_dci_pdu_rel13->transmission_power, ppWritePackedMsg, end) && + push8(mpdcch_dci_pdu_rel13->dci_format, ppWritePackedMsg, end) && + push8(mpdcch_dci_pdu_rel13->resource_block_start, ppWritePackedMsg, end) && + push8(mpdcch_dci_pdu_rel13->number_of_resource_blocks, ppWritePackedMsg, end) && + push8(mpdcch_dci_pdu_rel13->mcs, ppWritePackedMsg, end) && + push8(mpdcch_dci_pdu_rel13->pusch_repetition_levels, ppWritePackedMsg, end) && + push8(mpdcch_dci_pdu_rel13->frequency_hopping_flag, ppWritePackedMsg, end) && + push8(mpdcch_dci_pdu_rel13->new_data_indication, ppWritePackedMsg, end) && + push8(mpdcch_dci_pdu_rel13->harq_process, ppWritePackedMsg, end) && + push8(mpdcch_dci_pdu_rel13->redudency_version, ppWritePackedMsg, end) && + push8(mpdcch_dci_pdu_rel13->tpc, ppWritePackedMsg, end) && + push8(mpdcch_dci_pdu_rel13->csi_request, ppWritePackedMsg, end) && + push8(mpdcch_dci_pdu_rel13->ul_inex, ppWritePackedMsg, end) && + push8(mpdcch_dci_pdu_rel13->dai_presence_flag, ppWritePackedMsg, end) && + push8(mpdcch_dci_pdu_rel13->dl_assignment_index, ppWritePackedMsg, end) && + push8(mpdcch_dci_pdu_rel13->srs_request, ppWritePackedMsg, end) && + push8(mpdcch_dci_pdu_rel13->dci_subframe_repetition_number, ppWritePackedMsg, end) && + push32(mpdcch_dci_pdu_rel13->tcp_bitmap, ppWritePackedMsg, end) && + push8(mpdcch_dci_pdu_rel13->total_dci_length_include_padding, ppWritePackedMsg, end) && + push8(mpdcch_dci_pdu_rel13->number_of_tx_antenna_ports, ppWritePackedMsg, end) && + pusharray16(mpdcch_dci_pdu_rel13->precoding_value, NFAPI_MAX_TX_PHYSICAL_ANTENNA_PORTS, mpdcch_dci_pdu_rel13->number_of_tx_antenna_ports, ppWritePackedMsg, end)); } -static uint8_t pack_hi_dci0_npdcch_dci_rel13_pdu_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_hi_dci0_npdcch_dci_pdu_rel13_t* npdcch_dci_pdu_rel13 = (nfapi_hi_dci0_npdcch_dci_pdu_rel13_t*)tlv; - - return ( push8(npdcch_dci_pdu_rel13->ncce_index, ppWritePackedMsg, end) && - push8(npdcch_dci_pdu_rel13->aggregation_level, ppWritePackedMsg, end) && - push8(npdcch_dci_pdu_rel13->start_symbol, ppWritePackedMsg, end) && - push16(npdcch_dci_pdu_rel13->rnti, ppWritePackedMsg, end) && - push8(npdcch_dci_pdu_rel13->scrambling_reinitialization_batch_index, ppWritePackedMsg, end) && - push8(npdcch_dci_pdu_rel13->nrs_antenna_ports_assumed_by_the_ue, ppWritePackedMsg, end) && - push8(npdcch_dci_pdu_rel13->subcarrier_indication, ppWritePackedMsg, end) && - push8(npdcch_dci_pdu_rel13->resource_assignment, ppWritePackedMsg, end) && - push8(npdcch_dci_pdu_rel13->scheduling_delay, ppWritePackedMsg, end) && - push8(npdcch_dci_pdu_rel13->mcs, ppWritePackedMsg, end) && - push8(npdcch_dci_pdu_rel13->redudancy_version, ppWritePackedMsg, end) && - push8(npdcch_dci_pdu_rel13->repetition_number, ppWritePackedMsg, end) && - push8(npdcch_dci_pdu_rel13->new_data_indicator, ppWritePackedMsg, end) && - push8(npdcch_dci_pdu_rel13->dci_subframe_repetition_number, ppWritePackedMsg, end)); +static uint8_t pack_hi_dci0_npdcch_dci_rel13_pdu_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_hi_dci0_npdcch_dci_pdu_rel13_t *npdcch_dci_pdu_rel13 = (nfapi_hi_dci0_npdcch_dci_pdu_rel13_t *)tlv; + return ( push8(npdcch_dci_pdu_rel13->ncce_index, ppWritePackedMsg, end) && + push8(npdcch_dci_pdu_rel13->aggregation_level, ppWritePackedMsg, end) && + push8(npdcch_dci_pdu_rel13->start_symbol, ppWritePackedMsg, end) && + push16(npdcch_dci_pdu_rel13->rnti, ppWritePackedMsg, end) && + push8(npdcch_dci_pdu_rel13->scrambling_reinitialization_batch_index, ppWritePackedMsg, end) && + push8(npdcch_dci_pdu_rel13->nrs_antenna_ports_assumed_by_the_ue, ppWritePackedMsg, end) && + push8(npdcch_dci_pdu_rel13->subcarrier_indication, ppWritePackedMsg, end) && + push8(npdcch_dci_pdu_rel13->resource_assignment, ppWritePackedMsg, end) && + push8(npdcch_dci_pdu_rel13->scheduling_delay, ppWritePackedMsg, end) && + push8(npdcch_dci_pdu_rel13->mcs, ppWritePackedMsg, end) && + push8(npdcch_dci_pdu_rel13->redudancy_version, ppWritePackedMsg, end) && + push8(npdcch_dci_pdu_rel13->repetition_number, ppWritePackedMsg, end) && + push8(npdcch_dci_pdu_rel13->new_data_indicator, ppWritePackedMsg, end) && + push8(npdcch_dci_pdu_rel13->dci_subframe_repetition_number, ppWritePackedMsg, end)); } -static uint8_t pack_hi_dci0_request_body_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_hi_dci0_request_body_t* value = (nfapi_hi_dci0_request_body_t*)tlv; +static uint8_t pack_hi_dci0_request_body_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_hi_dci0_request_body_t *value = (nfapi_hi_dci0_request_body_t *)tlv; - if(!(push16(value->sfnsf, ppWritePackedMsg, end) && - push8(value->number_of_dci, ppWritePackedMsg, end) && - push8(value->number_of_hi, ppWritePackedMsg, end))) - return 0; + if(!(push16(value->sfnsf, ppWritePackedMsg, end) && + push8(value->number_of_dci, ppWritePackedMsg, end) && + push8(value->number_of_hi, ppWritePackedMsg, end))) + return 0; - uint16_t i = 0; - uint16_t total_number_of_pdus = value->number_of_dci + value->number_of_hi; - for(i = 0; i < total_number_of_pdus; ++i) - { - nfapi_hi_dci0_request_pdu_t* pdu = &(value->hi_dci0_pdu_list[i]); + uint16_t i = 0; + uint16_t total_number_of_pdus = value->number_of_dci + value->number_of_hi; - if(push8(pdu->pdu_type, ppWritePackedMsg, end) == 0) - return 0; + for(i = 0; i < total_number_of_pdus; ++i) { + nfapi_hi_dci0_request_pdu_t *pdu = &(value->hi_dci0_pdu_list[i]); - // Put a 0 size in and then determine the size after the pdu - // has been writen and write the calculated size - uint8_t* pWritePackedMsgPduSize = *ppWritePackedMsg; - pdu->pdu_size = 0; - if(push8(pdu->pdu_size, ppWritePackedMsg, end) == 0) - return 0; + if(push8(pdu->pdu_type, ppWritePackedMsg, end) == 0) + return 0; - switch(pdu->pdu_type) - { - case NFAPI_HI_DCI0_HI_PDU_TYPE: - { - if(!(pack_tlv(NFAPI_HI_DCI0_REQUEST_HI_PDU_REL8_TAG, &pdu->hi_pdu.hi_pdu_rel8, ppWritePackedMsg, end, pack_hi_dci0_hi_rel8_pdu_value) && - pack_tlv(NFAPI_HI_DCI0_REQUEST_HI_PDU_REL10_TAG, &pdu->hi_pdu.hi_pdu_rel10, ppWritePackedMsg, end, pack_hi_dci0_hi_rel10_pdu_value))) - return 0; - } - break; - case NFAPI_HI_DCI0_DCI_PDU_TYPE: - { - if(!(pack_tlv(NFAPI_HI_DCI0_REQUEST_DCI_PDU_REL8_TAG, &pdu->dci_pdu.dci_pdu_rel8, ppWritePackedMsg, end, pack_hi_dci0_dci_rel8_pdu_value) && - pack_tlv(NFAPI_HI_DCI0_REQUEST_DCI_PDU_REL10_TAG, &pdu->dci_pdu.dci_pdu_rel10, ppWritePackedMsg, end, pack_hi_dci0_dci_rel10_pdu_value) && - pack_tlv(NFAPI_HI_DCI0_REQUEST_DCI_PDU_REL12_TAG, &pdu->dci_pdu.dci_pdu_rel12, ppWritePackedMsg, end, pack_hi_dci0_dci_rel12_pdu_value))) - return 0; - } - break; - case NFAPI_HI_DCI0_EPDCCH_DCI_PDU_TYPE: - { - if(!(pack_tlv(NFAPI_HI_DCI0_REQUEST_EPDCCH_DCI_PDU_REL8_TAG, &pdu->epdcch_dci_pdu.epdcch_dci_pdu_rel8, ppWritePackedMsg, end, pack_hi_dci0_dci_rel8_pdu_value) && - pack_tlv(NFAPI_HI_DCI0_REQUEST_EPDCCH_DCI_PDU_REL10_TAG, &pdu->epdcch_dci_pdu.epdcch_dci_pdu_rel10, ppWritePackedMsg, end, pack_hi_dci0_dci_rel10_pdu_value) && - pack_tlv(NFAPI_HI_DCI0_REQUEST_EPDCCH_PARAMETERS_REL11_TAG, &pdu->epdcch_dci_pdu.epdcch_parameters_rel11, ppWritePackedMsg, end, pack_dl_config_epdcch_parameters_rel11_value))) - return 0; - } - break; - case NFAPI_HI_DCI0_MPDCCH_DCI_PDU_TYPE: - { - if(!(pack_tlv(NFAPI_HI_DCI0_REQUEST_MPDCCH_DCI_PDU_REL13_TAG, &pdu->mpdcch_dci_pdu.mpdcch_dci_pdu_rel13, ppWritePackedMsg, end, pack_hi_dci0_mpdcch_dci_rel13_pdu_value))) - return 0; - } - break; - case NFAPI_HI_DCI0_NPDCCH_DCI_PDU_TYPE: - { - if(!(pack_tlv(NFAPI_HI_DCI0_REQUEST_NPDCCH_DCI_PDU_REL13_TAG, &pdu->npdcch_dci_pdu.npdcch_dci_pdu_rel13, ppWritePackedMsg, end, pack_hi_dci0_npdcch_dci_rel13_pdu_value))) - return 0; - } - break; - default: - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "FIXME : Invalid pdu type %d \n", pdu->pdu_type ); - } - break; - }; + // Put a 0 size in and then determine the size after the pdu + // has been writen and write the calculated size + uint8_t *pWritePackedMsgPduSize = *ppWritePackedMsg; + pdu->pdu_size = 0; - // add 1 for the pdu_type. The delta will include the pdu_size - pdu->pdu_size = 1 + (*ppWritePackedMsg - pWritePackedMsgPduSize); - push8(pdu->pdu_size, &pWritePackedMsgPduSize, end); - - } + if(push8(pdu->pdu_size, ppWritePackedMsg, end) == 0) + return 0; - return 1; + switch(pdu->pdu_type) { + case NFAPI_HI_DCI0_HI_PDU_TYPE: { + if(!(pack_tlv(NFAPI_HI_DCI0_REQUEST_HI_PDU_REL8_TAG, &pdu->hi_pdu.hi_pdu_rel8, ppWritePackedMsg, end, pack_hi_dci0_hi_rel8_pdu_value) && + pack_tlv(NFAPI_HI_DCI0_REQUEST_HI_PDU_REL10_TAG, &pdu->hi_pdu.hi_pdu_rel10, ppWritePackedMsg, end, pack_hi_dci0_hi_rel10_pdu_value))) + return 0; + } + break; + + case NFAPI_HI_DCI0_DCI_PDU_TYPE: { + if(!(pack_tlv(NFAPI_HI_DCI0_REQUEST_DCI_PDU_REL8_TAG, &pdu->dci_pdu.dci_pdu_rel8, ppWritePackedMsg, end, pack_hi_dci0_dci_rel8_pdu_value) && + pack_tlv(NFAPI_HI_DCI0_REQUEST_DCI_PDU_REL10_TAG, &pdu->dci_pdu.dci_pdu_rel10, ppWritePackedMsg, end, pack_hi_dci0_dci_rel10_pdu_value) && + pack_tlv(NFAPI_HI_DCI0_REQUEST_DCI_PDU_REL12_TAG, &pdu->dci_pdu.dci_pdu_rel12, ppWritePackedMsg, end, pack_hi_dci0_dci_rel12_pdu_value))) + return 0; + } + break; + + case NFAPI_HI_DCI0_EPDCCH_DCI_PDU_TYPE: { + if(!(pack_tlv(NFAPI_HI_DCI0_REQUEST_EPDCCH_DCI_PDU_REL8_TAG, &pdu->epdcch_dci_pdu.epdcch_dci_pdu_rel8, ppWritePackedMsg, end, pack_hi_dci0_dci_rel8_pdu_value) && + pack_tlv(NFAPI_HI_DCI0_REQUEST_EPDCCH_DCI_PDU_REL10_TAG, &pdu->epdcch_dci_pdu.epdcch_dci_pdu_rel10, ppWritePackedMsg, end, pack_hi_dci0_dci_rel10_pdu_value) && + pack_tlv(NFAPI_HI_DCI0_REQUEST_EPDCCH_PARAMETERS_REL11_TAG, &pdu->epdcch_dci_pdu.epdcch_parameters_rel11, ppWritePackedMsg, end, pack_dl_config_epdcch_parameters_rel11_value))) + return 0; + } + break; + + case NFAPI_HI_DCI0_MPDCCH_DCI_PDU_TYPE: { + if(!(pack_tlv(NFAPI_HI_DCI0_REQUEST_MPDCCH_DCI_PDU_REL13_TAG, &pdu->mpdcch_dci_pdu.mpdcch_dci_pdu_rel13, ppWritePackedMsg, end, pack_hi_dci0_mpdcch_dci_rel13_pdu_value))) + return 0; + } + break; + + case NFAPI_HI_DCI0_NPDCCH_DCI_PDU_TYPE: { + if(!(pack_tlv(NFAPI_HI_DCI0_REQUEST_NPDCCH_DCI_PDU_REL13_TAG, &pdu->npdcch_dci_pdu.npdcch_dci_pdu_rel13, ppWritePackedMsg, end, pack_hi_dci0_npdcch_dci_rel13_pdu_value))) + return 0; + } + break; + + default: { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "FIXME : Invalid pdu type %d \n", pdu->pdu_type ); + } + break; + }; + + // add 1 for the pdu_type. The delta will include the pdu_size + pdu->pdu_size = 1 + (*ppWritePackedMsg - pWritePackedMsgPduSize); + + push8(pdu->pdu_size, &pWritePackedMsgPduSize, end); + } + + return 1; } -static uint8_t pack_ul_dci_pdu_list_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_nr_ul_dci_request_pdus_t* value = (nfapi_nr_ul_dci_request_pdus_t*)tlv; - - for(uint8_t i = 0; i < MAX_DCI_CORESET; ++i) - { - if(!push16(value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].RNTI, ppWritePackedMsg, end) && - push16(value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].ScramblingId, ppWritePackedMsg, end) && +static uint8_t pack_ul_dci_pdu_list_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_nr_ul_dci_request_pdus_t *value = (nfapi_nr_ul_dci_request_pdus_t *)tlv; - push16(value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].ScramblingRNTI, ppWritePackedMsg, end) && - push8(value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].CceIndex, ppWritePackedMsg, end) && - push8(value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].AggregationLevel, ppWritePackedMsg, end) && - push8(value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].beta_PDCCH_1_0, ppWritePackedMsg, end) && + for(uint8_t i = 0; i < MAX_DCI_CORESET; ++i) { + if(!push16(value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].RNTI, ppWritePackedMsg, end) && + push16(value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].ScramblingId, ppWritePackedMsg, end) && + push16(value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].ScramblingRNTI, ppWritePackedMsg, end) && + push8(value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].CceIndex, ppWritePackedMsg, end) && + push8(value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].AggregationLevel, ppWritePackedMsg, end) && + push8(value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].beta_PDCCH_1_0, ppWritePackedMsg, end) && + push8(value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].powerControlOffsetSS, ppWritePackedMsg, end) && + push16(value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].PayloadSizeBits, ppWritePackedMsg, end) && + pusharray8(value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].Payload, DCI_PAYLOAD_BYTE_LEN, value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].PayloadSizeBits, ppWritePackedMsg, end)); - push8(value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].powerControlOffsetSS, ppWritePackedMsg, end) && - push16(value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].PayloadSizeBits, ppWritePackedMsg, end) && - - pusharray8(value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].Payload, DCI_PAYLOAD_BYTE_LEN, value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].PayloadSizeBits, ppWritePackedMsg, end)); - - return 0; - } - - return (push16(value->PDUType, ppWritePackedMsg, end) && - push16(value->PDUSize, ppWritePackedMsg, end) && - push16(value->pdcch_pdu.pdcch_pdu_rel15.BWPSize, ppWritePackedMsg, end) && - push16(value->pdcch_pdu.pdcch_pdu_rel15.BWPStart, ppWritePackedMsg, end) && - push8(value->pdcch_pdu.pdcch_pdu_rel15.SubcarrierSpacing, ppWritePackedMsg, end) && - push8(value->pdcch_pdu.pdcch_pdu_rel15.CyclicPrefix, ppWritePackedMsg, end) && - - push8(value->pdcch_pdu.pdcch_pdu_rel15.StartSymbolIndex, ppWritePackedMsg, end) && - push8(value->pdcch_pdu.pdcch_pdu_rel15.DurationSymbols, ppWritePackedMsg, end) && - pusharray8(value->pdcch_pdu.pdcch_pdu_rel15.FreqDomainResource, 6, 6, ppWritePackedMsg, end) && - push8(value->pdcch_pdu.pdcch_pdu_rel15.CceRegMappingType, ppWritePackedMsg, end) && - - push8(value->pdcch_pdu.pdcch_pdu_rel15.RegBundleSize, ppWritePackedMsg, end) && - push8(value->pdcch_pdu.pdcch_pdu_rel15.InterleaverSize, ppWritePackedMsg, end) && - push8(value->pdcch_pdu.pdcch_pdu_rel15.CoreSetType, ppWritePackedMsg, end) && - push16(value->pdcch_pdu.pdcch_pdu_rel15.ShiftIndex, ppWritePackedMsg, end)); + return 0; + } + return (push16(value->PDUType, ppWritePackedMsg, end) && + push16(value->PDUSize, ppWritePackedMsg, end) && + push16(value->pdcch_pdu.pdcch_pdu_rel15.BWPSize, ppWritePackedMsg, end) && + push16(value->pdcch_pdu.pdcch_pdu_rel15.BWPStart, ppWritePackedMsg, end) && + push8(value->pdcch_pdu.pdcch_pdu_rel15.SubcarrierSpacing, ppWritePackedMsg, end) && + push8(value->pdcch_pdu.pdcch_pdu_rel15.CyclicPrefix, ppWritePackedMsg, end) && + push8(value->pdcch_pdu.pdcch_pdu_rel15.StartSymbolIndex, ppWritePackedMsg, end) && + push8(value->pdcch_pdu.pdcch_pdu_rel15.DurationSymbols, ppWritePackedMsg, end) && + pusharray8(value->pdcch_pdu.pdcch_pdu_rel15.FreqDomainResource, 6, 6, ppWritePackedMsg, end) && + push8(value->pdcch_pdu.pdcch_pdu_rel15.CceRegMappingType, ppWritePackedMsg, end) && + push8(value->pdcch_pdu.pdcch_pdu_rel15.RegBundleSize, ppWritePackedMsg, end) && + push8(value->pdcch_pdu.pdcch_pdu_rel15.InterleaverSize, ppWritePackedMsg, end) && + push8(value->pdcch_pdu.pdcch_pdu_rel15.CoreSetType, ppWritePackedMsg, end) && + push16(value->pdcch_pdu.pdcch_pdu_rel15.ShiftIndex, ppWritePackedMsg, end)); } -static uint8_t pack_ul_dci_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) -{ - nfapi_nr_ul_dci_request_t *pNfapiMsg = (nfapi_nr_ul_dci_request_t*)msg; - - if (!(push16(pNfapiMsg->SFN, ppWritePackedMsg, end) && - push16(pNfapiMsg->Slot, ppWritePackedMsg, end) && - push8(pNfapiMsg->numPdus, ppWritePackedMsg, end) - )) - return 0; +static uint8_t pack_ul_dci_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t *config) { + nfapi_nr_ul_dci_request_t *pNfapiMsg = (nfapi_nr_ul_dci_request_t *)msg; - for(int i=0; inumPdus; i++) - { - if(!pack_ul_dci_pdu_list_value(&pNfapiMsg->ul_dci_pdu_list[i], ppWritePackedMsg, end)) - return 0; - } - return 1; + if (!(push16(pNfapiMsg->SFN, ppWritePackedMsg, end) && + push16(pNfapiMsg->Slot, ppWritePackedMsg, end) && + push8(pNfapiMsg->numPdus, ppWritePackedMsg, end) + )) + return 0; + for(int i=0; inumPdus; i++) { + if(!pack_ul_dci_pdu_list_value(&pNfapiMsg->ul_dci_pdu_list[i], ppWritePackedMsg, end)) + return 0; + } + return 1; } -static uint8_t pack_hi_dci0_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) -{ - nfapi_hi_dci0_request_t *pNfapiMsg = (nfapi_hi_dci0_request_t*)msg; - - return ( push16(pNfapiMsg->sfn_sf, ppWritePackedMsg, end) && - pack_tlv(NFAPI_HI_DCI0_REQUEST_BODY_TAG, &pNfapiMsg->hi_dci0_request_body, ppWritePackedMsg, end, &pack_hi_dci0_request_body_value) && - pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); +static uint8_t pack_hi_dci0_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t *config) { + nfapi_hi_dci0_request_t *pNfapiMsg = (nfapi_hi_dci0_request_t *)msg; + return ( push16(pNfapiMsg->sfn_sf, ppWritePackedMsg, end) && + pack_tlv(NFAPI_HI_DCI0_REQUEST_BODY_TAG, &pNfapiMsg->hi_dci0_request_body, ppWritePackedMsg, end, &pack_hi_dci0_request_body_value) && + pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); } //pack_tx_data_pdu_list_value -static uint8_t pack_tx_data_pdu_list_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_nr_pdu_t* value = (nfapi_nr_pdu_t*)tlv; - - if(!(push32(value->num_TLV, ppWritePackedMsg, end) && - push16(value->PDU_index, ppWritePackedMsg, end) && - push16(value->PDU_length, ppWritePackedMsg, end) - )) - return 0; +static uint8_t pack_tx_data_pdu_list_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_nr_pdu_t *value = (nfapi_nr_pdu_t *)tlv; - uint16_t i = 0; - uint16_t total_number_of_tlvs = value->num_TLV; - for(; i < total_number_of_tlvs; ++i) - { - - if (!(push16(value->TLVs[i].length, ppWritePackedMsg, end) && - push16(value->TLVs[i].tag, ppWritePackedMsg, end))) - return 0; + if(!(push32(value->num_TLV, ppWritePackedMsg, end) && + push16(value->PDU_index, ppWritePackedMsg, end) && + push16(value->PDU_length, ppWritePackedMsg, end) + )) + return 0; - switch(value->TLVs[i].tag) - { - case 0: - { - if(!pusharray32(value->TLVs[i].value.direct, 16384, value->TLVs[i].length, ppWritePackedMsg, end)) - return 0; - break; + uint16_t i = 0; + uint16_t total_number_of_tlvs = value->num_TLV; - } + for(; i < total_number_of_tlvs; ++i) { + if (!(push16(value->TLVs[i].length, ppWritePackedMsg, end) && + push16(value->TLVs[i].tag, ppWritePackedMsg, end))) + return 0; - case 1: - { - if(!pusharray32(value->TLVs[i].value.ptr, value->TLVs[i].length , value->TLVs[i].length, ppWritePackedMsg, end)) - return 0; - break; + switch(value->TLVs[i].tag) { + case 0: { + if(!pusharray32(value->TLVs[i].value.direct, 16384, value->TLVs[i].length, ppWritePackedMsg, end)) + return 0; - } - - default: - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "FIXME : Invalid tag value %d \n", value->TLVs[i].tag ); - break; - } - - } - } - return 1; + break; + } + + case 1: { + if(!pusharray32(value->TLVs[i].value.ptr, value->TLVs[i].length, value->TLVs[i].length, ppWritePackedMsg, end)) + return 0; + + break; + } + + default: { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "FIXME : Invalid tag value %d \n", value->TLVs[i].tag ); + break; + } + } + } + + return 1; } -static uint8_t pack_tx_request_body_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_tx_request_body_t* value = (nfapi_tx_request_body_t*)tlv; - - if(push16(value->number_of_pdus, ppWritePackedMsg, end) == 0) - return 0; +static uint8_t pack_tx_request_body_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_tx_request_body_t *value = (nfapi_tx_request_body_t *)tlv; - uint16_t i = 0; - uint16_t total_number_of_pdus = value->number_of_pdus; - for(; i < total_number_of_pdus; ++i) - { - nfapi_tx_request_pdu_t* pdu = &(value->tx_pdu_list[i]); - - if(!(push16(pdu->pdu_length, ppWritePackedMsg, end) && - push16(pdu->pdu_index, ppWritePackedMsg, end))) - return 0; + if(push16(value->number_of_pdus, ppWritePackedMsg, end) == 0) + return 0; - uint8_t j; - for(j = 0; j < pdu->num_segments; ++j) - { - // Use -1 as it is unbounded - // DJP - does not handle -1 - // DJP - if(pusharray8(pdu->segments[j].segment_data, (uint32_t)(-1), pdu->segments[j].segment_length, ppWritePackedMsg, end) == 0) - int push_ret = pusharray8(pdu->segments[j].segment_data, 65535, pdu->segments[j].segment_length, ppWritePackedMsg, end); - - if (pdu->segments[j].segment_length == 3) - { - NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() BCH? segment_data:%x %x %x\n", __FUNCTION__, - pdu->segments[j].segment_data[0], - pdu->segments[j].segment_data[1], - pdu->segments[j].segment_data[2] - ); - } - //NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() segment_data:%p segment_length:%u pusharray8()=%d\n", __FUNCTION__, pdu->segments[j].segment_data, pdu->segments[j].segment_length, push_ret); + uint16_t i = 0; + uint16_t total_number_of_pdus = value->number_of_pdus; - if (push_ret == 0) - { - return 0; - } - } - } + for(; i < total_number_of_pdus; ++i) { + nfapi_tx_request_pdu_t *pdu = &(value->tx_pdu_list[i]); - return 1; + if(!(push16(pdu->pdu_length, ppWritePackedMsg, end) && + push16(pdu->pdu_index, ppWritePackedMsg, end))) + return 0; + + uint8_t j; + + for(j = 0; j < pdu->num_segments; ++j) { + // Use -1 as it is unbounded + // DJP - does not handle -1 + // DJP - if(pusharray8(pdu->segments[j].segment_data, (uint32_t)(-1), pdu->segments[j].segment_length, ppWritePackedMsg, end) == 0) + int push_ret = pusharray8(pdu->segments[j].segment_data, 65535, pdu->segments[j].segment_length, ppWritePackedMsg, end); + + if (pdu->segments[j].segment_length == 3) { + NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() BCH? segment_data:%x %x %x\n", __FUNCTION__, + pdu->segments[j].segment_data[0], + pdu->segments[j].segment_data[1], + pdu->segments[j].segment_data[2] + ); + } + + //NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() segment_data:%p segment_length:%u pusharray8()=%d\n", __FUNCTION__, pdu->segments[j].segment_data, pdu->segments[j].segment_length, push_ret); + + if (push_ret == 0) { + return 0; + } + } + } + + return 1; } -static uint8_t pack_tx_data_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) -{ - nfapi_nr_tx_data_request_t *pNfapiMsg = (nfapi_nr_tx_data_request_t*)msg; - - if (!( - push16(pNfapiMsg->SFN, ppWritePackedMsg, end) && - push16(pNfapiMsg->Slot, ppWritePackedMsg, end) && - push16(pNfapiMsg->Number_of_PDUs, ppWritePackedMsg, end) - )) - return 0; +static uint8_t pack_tx_data_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t *config) { + nfapi_nr_tx_data_request_t *pNfapiMsg = (nfapi_nr_tx_data_request_t *)msg; - for(int i=0; iNumber_of_PDUs; i++) - { - if(!pack_tx_data_pdu_list_value(&pNfapiMsg->pdu_list[i], ppWritePackedMsg, end)) - return 0; - } + if (!( + push16(pNfapiMsg->SFN, ppWritePackedMsg, end) && + push16(pNfapiMsg->Slot, ppWritePackedMsg, end) && + push16(pNfapiMsg->Number_of_PDUs, ppWritePackedMsg, end) + )) + return 0; - return 1; + for(int i=0; iNumber_of_PDUs; i++) { + if(!pack_tx_data_pdu_list_value(&pNfapiMsg->pdu_list[i], ppWritePackedMsg, end)) + return 0; + } + + return 1; } -static uint8_t pack_tx_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) -{ - nfapi_tx_request_t *pNfapiMsg = (nfapi_tx_request_t*)msg; - - int x = push16(pNfapiMsg->sfn_sf, ppWritePackedMsg, end); - int y = pack_tlv(NFAPI_TX_REQUEST_BODY_TAG, &pNfapiMsg->tx_request_body, ppWritePackedMsg, end, &pack_tx_request_body_value); - int z = pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config); - - //NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() x:%d y:%d z:%d\n", __FUNCTION__, x, y, z); - - return x && y && z; +static uint8_t pack_tx_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t *config) { + nfapi_tx_request_t *pNfapiMsg = (nfapi_tx_request_t *)msg; + int x = push16(pNfapiMsg->sfn_sf, ppWritePackedMsg, end); + int y = pack_tlv(NFAPI_TX_REQUEST_BODY_TAG, &pNfapiMsg->tx_request_body, ppWritePackedMsg, end, &pack_tx_request_body_value); + int z = pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config); + //NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() x:%d y:%d z:%d\n", __FUNCTION__, x, y, z); + return x && y && z; } -static uint8_t pack_release_request_body_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_ue_release_request_body_t* value = (nfapi_ue_release_request_body_t*)tlv; - if(push16(value->number_of_TLVs, ppWritePackedMsg, end) == 0){ +static uint8_t pack_release_request_body_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_ue_release_request_body_t *value = (nfapi_ue_release_request_body_t *)tlv; + + if(push16(value->number_of_TLVs, ppWritePackedMsg, end) == 0) { return 0; } uint8_t j; uint16_t num = value->number_of_TLVs; - for(j = 0; j < num; ++j){ - if(push16(value->ue_release_request_TLVs_list[j].rnti, ppWritePackedMsg, end) == 0){ + + for(j = 0; j < num; ++j) { + if(push16(value->ue_release_request_TLVs_list[j].rnti, ppWritePackedMsg, end) == 0) { return 0; } } + return 1; } -static uint8_t pack_ue_release_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) -{ - nfapi_ue_release_request_t *pNfapiMsg = (nfapi_ue_release_request_t*)msg; +static uint8_t pack_ue_release_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t *config) { + nfapi_ue_release_request_t *pNfapiMsg = (nfapi_ue_release_request_t *)msg; int x = push16(pNfapiMsg->sfn_sf, ppWritePackedMsg, end); int y = pack_tlv(NFAPI_UE_RELEASE_BODY_TAG, &pNfapiMsg->ue_release_request_body, ppWritePackedMsg, end, &pack_release_request_body_value); int z = pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config); return x && y && z; } -static uint8_t pack_ue_release_response(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) -{ - - nfapi_ue_release_response_t *pNfapiMsg = (nfapi_ue_release_response_t*)msg; - - int x = push32(pNfapiMsg->error_code, ppWritePackedMsg, end); - int z = pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config); - return x && z; +static uint8_t pack_ue_release_response(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t *config) { + nfapi_ue_release_response_t *pNfapiMsg = (nfapi_ue_release_response_t *)msg; + int x = push32(pNfapiMsg->error_code, ppWritePackedMsg, end); + int z = pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config); + return x && z; } -static uint8_t pack_rx_ue_information_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_rx_ue_information* value = (nfapi_rx_ue_information*)tlv; - - return ( push32(value->handle, ppWritePackedMsg, end) && - push16(value->rnti, ppWritePackedMsg, end) ); +static uint8_t pack_rx_ue_information_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_rx_ue_information *value = (nfapi_rx_ue_information *)tlv; + return ( push32(value->handle, ppWritePackedMsg, end) && + push16(value->rnti, ppWritePackedMsg, end) ); } -static uint8_t unpack_rx_ue_information_value(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_rx_ue_information* value = (nfapi_rx_ue_information*)tlv; - - return ( pull32(ppReadPackedMsg, &value->handle, end) && - pull16(ppReadPackedMsg, &value->rnti, end)); +static uint8_t unpack_rx_ue_information_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_rx_ue_information *value = (nfapi_rx_ue_information *)tlv; + return ( pull32(ppReadPackedMsg, &value->handle, end) && + pull16(ppReadPackedMsg, &value->rnti, end)); } -static uint8_t pack_harq_indication_tdd_harq_data_bundling(nfapi_harq_indication_tdd_harq_data_bundling_t* data, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - return ( push8(data->value_0, ppWritePackedMsg, end) && - push8(data->value_1, ppWritePackedMsg, end)); +static uint8_t pack_harq_indication_tdd_harq_data_bundling(nfapi_harq_indication_tdd_harq_data_bundling_t *data, uint8_t **ppWritePackedMsg, uint8_t *end) { + return ( push8(data->value_0, ppWritePackedMsg, end) && + push8(data->value_1, ppWritePackedMsg, end)); } -static uint8_t pack_harq_indication_tdd_harq_data_multiplexing(nfapi_harq_indication_tdd_harq_data_multiplexing_t* data, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - return ( push8(data->value_0, ppWritePackedMsg, end) && - push8(data->value_1, ppWritePackedMsg, end) && - push8(data->value_2, ppWritePackedMsg, end) && - push8(data->value_3, ppWritePackedMsg, end)); +static uint8_t pack_harq_indication_tdd_harq_data_multiplexing(nfapi_harq_indication_tdd_harq_data_multiplexing_t *data, uint8_t **ppWritePackedMsg, uint8_t *end) { + return ( push8(data->value_0, ppWritePackedMsg, end) && + push8(data->value_1, ppWritePackedMsg, end) && + push8(data->value_2, ppWritePackedMsg, end) && + push8(data->value_3, ppWritePackedMsg, end)); } -static uint8_t pack_harq_indication_tdd_harq_data_special_bundling(nfapi_harq_indication_tdd_harq_data_special_bundling_t* data, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - return ( push8(data->value_0, ppWritePackedMsg, end) ); +static uint8_t pack_harq_indication_tdd_harq_data_special_bundling(nfapi_harq_indication_tdd_harq_data_special_bundling_t *data, uint8_t **ppWritePackedMsg, uint8_t *end) { + return ( push8(data->value_0, ppWritePackedMsg, end) ); } -static uint8_t pack_harq_indication_tdd_harq_data(nfapi_harq_indication_tdd_harq_data_t* data, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - return ( push8(data->value_0, ppWritePackedMsg, end) ); +static uint8_t pack_harq_indication_tdd_harq_data(nfapi_harq_indication_tdd_harq_data_t *data, uint8_t **ppWritePackedMsg, uint8_t *end) { + return ( push8(data->value_0, ppWritePackedMsg, end) ); } -static uint8_t pack_harq_indication_tdd_rel8_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_harq_indication_tdd_rel8_t* harq_indication_tdd_rel8 = (nfapi_harq_indication_tdd_rel8_t*)tlv; - - if(!(push8(harq_indication_tdd_rel8->mode, ppWritePackedMsg, end) && - push8(harq_indication_tdd_rel8->number_of_ack_nack, ppWritePackedMsg, end))) - return 0; +static uint8_t pack_harq_indication_tdd_rel8_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_harq_indication_tdd_rel8_t *harq_indication_tdd_rel8 = (nfapi_harq_indication_tdd_rel8_t *)tlv; - uint8_t result = 0; - switch(harq_indication_tdd_rel8->mode) - { - case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_BUNDLING: - result = pack_harq_indication_tdd_harq_data_bundling(&harq_indication_tdd_rel8->harq_data.bundling, ppWritePackedMsg, end); - break; - case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_MULIPLEXING: - result = pack_harq_indication_tdd_harq_data_multiplexing(&harq_indication_tdd_rel8->harq_data.multiplex, ppWritePackedMsg, end); - break; - case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_SPECIAL_BUNDLING: - result = pack_harq_indication_tdd_harq_data_special_bundling(&harq_indication_tdd_rel8->harq_data.special_bundling, ppWritePackedMsg, end); - break; - case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_CHANNEL_SELECTION: - case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_FORMAT_3: - result = 1; - break; - default: - // err.... - break; - } + if(!(push8(harq_indication_tdd_rel8->mode, ppWritePackedMsg, end) && + push8(harq_indication_tdd_rel8->number_of_ack_nack, ppWritePackedMsg, end))) + return 0; - return result; - + uint8_t result = 0; + + switch(harq_indication_tdd_rel8->mode) { + case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_BUNDLING: + result = pack_harq_indication_tdd_harq_data_bundling(&harq_indication_tdd_rel8->harq_data.bundling, ppWritePackedMsg, end); + break; + + case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_MULIPLEXING: + result = pack_harq_indication_tdd_harq_data_multiplexing(&harq_indication_tdd_rel8->harq_data.multiplex, ppWritePackedMsg, end); + break; + + case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_SPECIAL_BUNDLING: + result = pack_harq_indication_tdd_harq_data_special_bundling(&harq_indication_tdd_rel8->harq_data.special_bundling, ppWritePackedMsg, end); + break; + + case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_CHANNEL_SELECTION: + case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_FORMAT_3: + result = 1; + break; + + default: + // err.... + break; + } + + return result; } -static uint8_t pack_harq_indication_tdd_rel9_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_harq_indication_tdd_rel9_t* harq_indication_tdd_rel9 = (nfapi_harq_indication_tdd_rel9_t*)tlv; - - if(!(push8(harq_indication_tdd_rel9->mode, ppWritePackedMsg, end) && - push8(harq_indication_tdd_rel9->number_of_ack_nack, ppWritePackedMsg, end))) - return 0; +static uint8_t pack_harq_indication_tdd_rel9_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_harq_indication_tdd_rel9_t *harq_indication_tdd_rel9 = (nfapi_harq_indication_tdd_rel9_t *)tlv; - uint8_t idx; - for(idx = 0; idx < harq_indication_tdd_rel9->number_of_ack_nack; ++idx) - { - uint8_t result = 0; + if(!(push8(harq_indication_tdd_rel9->mode, ppWritePackedMsg, end) && + push8(harq_indication_tdd_rel9->number_of_ack_nack, ppWritePackedMsg, end))) + return 0; - switch(harq_indication_tdd_rel9->mode) - { - case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_BUNDLING: - result = pack_harq_indication_tdd_harq_data(&(harq_indication_tdd_rel9->harq_data[idx].bundling), ppWritePackedMsg, end); - break; - case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_MULIPLEXING: - result = pack_harq_indication_tdd_harq_data(&harq_indication_tdd_rel9->harq_data[idx].multiplex, ppWritePackedMsg, end); - break; - case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_SPECIAL_BUNDLING: - result = pack_harq_indication_tdd_harq_data_special_bundling(&harq_indication_tdd_rel9->harq_data[idx].special_bundling, ppWritePackedMsg, end); - break; - case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_CHANNEL_SELECTION: - result = pack_harq_indication_tdd_harq_data(&harq_indication_tdd_rel9->harq_data[idx].channel_selection, ppWritePackedMsg, end); - break; - case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_FORMAT_3: - result = pack_harq_indication_tdd_harq_data(&harq_indication_tdd_rel9->harq_data[idx].format_3, ppWritePackedMsg, end); - break; - default: - // err.... - break; - } + uint8_t idx; - if(result == 0) - return 0; - } + for(idx = 0; idx < harq_indication_tdd_rel9->number_of_ack_nack; ++idx) { + uint8_t result = 0; - return 1; + switch(harq_indication_tdd_rel9->mode) { + case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_BUNDLING: + result = pack_harq_indication_tdd_harq_data(&(harq_indication_tdd_rel9->harq_data[idx].bundling), ppWritePackedMsg, end); + break; + + case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_MULIPLEXING: + result = pack_harq_indication_tdd_harq_data(&harq_indication_tdd_rel9->harq_data[idx].multiplex, ppWritePackedMsg, end); + break; + + case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_SPECIAL_BUNDLING: + result = pack_harq_indication_tdd_harq_data_special_bundling(&harq_indication_tdd_rel9->harq_data[idx].special_bundling, ppWritePackedMsg, end); + break; + + case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_CHANNEL_SELECTION: + result = pack_harq_indication_tdd_harq_data(&harq_indication_tdd_rel9->harq_data[idx].channel_selection, ppWritePackedMsg, end); + break; + + case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_FORMAT_3: + result = pack_harq_indication_tdd_harq_data(&harq_indication_tdd_rel9->harq_data[idx].format_3, ppWritePackedMsg, end); + break; + + default: + // err.... + break; + } + + if(result == 0) + return 0; + } + + return 1; } -static uint8_t pack_harq_indication_tdd_rel13_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_harq_indication_tdd_rel13_t* harq_indication_tdd_rel13 = (nfapi_harq_indication_tdd_rel13_t*)tlv; - - if(!(push8(harq_indication_tdd_rel13->mode, ppWritePackedMsg, end) && - push16(harq_indication_tdd_rel13->number_of_ack_nack, ppWritePackedMsg, end))) - return 0; +static uint8_t pack_harq_indication_tdd_rel13_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_harq_indication_tdd_rel13_t *harq_indication_tdd_rel13 = (nfapi_harq_indication_tdd_rel13_t *)tlv; - uint8_t idx; - for(idx = 0; idx < harq_indication_tdd_rel13->number_of_ack_nack; ++idx) - { - uint8_t result = 0; - switch(harq_indication_tdd_rel13->mode) - { - case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_BUNDLING: - result = pack_harq_indication_tdd_harq_data(&harq_indication_tdd_rel13->harq_data[idx].bundling, ppWritePackedMsg, end); - break; - case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_MULIPLEXING: - result = pack_harq_indication_tdd_harq_data(&harq_indication_tdd_rel13->harq_data[idx].multiplex, ppWritePackedMsg, end); - break; - case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_SPECIAL_BUNDLING: - result = pack_harq_indication_tdd_harq_data_special_bundling(&harq_indication_tdd_rel13->harq_data[idx].special_bundling, ppWritePackedMsg, end); - break; - case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_CHANNEL_SELECTION: - result = pack_harq_indication_tdd_harq_data(&harq_indication_tdd_rel13->harq_data[idx].channel_selection, ppWritePackedMsg, end); - break; - case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_FORMAT_3: - result = pack_harq_indication_tdd_harq_data(&harq_indication_tdd_rel13->harq_data[idx].format_3, ppWritePackedMsg, end); - break; - case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_FORMAT_4: - result = pack_harq_indication_tdd_harq_data(&harq_indication_tdd_rel13->harq_data[idx].format_4, ppWritePackedMsg, end); - break; - case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_FORMAT_5: - result = pack_harq_indication_tdd_harq_data(&harq_indication_tdd_rel13->harq_data[idx].format_5, ppWritePackedMsg, end); - break; - default: - // err.... - break; - } + if(!(push8(harq_indication_tdd_rel13->mode, ppWritePackedMsg, end) && + push16(harq_indication_tdd_rel13->number_of_ack_nack, ppWritePackedMsg, end))) + return 0; - if(result == 0) - return 0; - } + uint8_t idx; - return 1; + for(idx = 0; idx < harq_indication_tdd_rel13->number_of_ack_nack; ++idx) { + uint8_t result = 0; + + switch(harq_indication_tdd_rel13->mode) { + case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_BUNDLING: + result = pack_harq_indication_tdd_harq_data(&harq_indication_tdd_rel13->harq_data[idx].bundling, ppWritePackedMsg, end); + break; + + case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_MULIPLEXING: + result = pack_harq_indication_tdd_harq_data(&harq_indication_tdd_rel13->harq_data[idx].multiplex, ppWritePackedMsg, end); + break; + + case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_SPECIAL_BUNDLING: + result = pack_harq_indication_tdd_harq_data_special_bundling(&harq_indication_tdd_rel13->harq_data[idx].special_bundling, ppWritePackedMsg, end); + break; + + case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_CHANNEL_SELECTION: + result = pack_harq_indication_tdd_harq_data(&harq_indication_tdd_rel13->harq_data[idx].channel_selection, ppWritePackedMsg, end); + break; + + case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_FORMAT_3: + result = pack_harq_indication_tdd_harq_data(&harq_indication_tdd_rel13->harq_data[idx].format_3, ppWritePackedMsg, end); + break; + + case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_FORMAT_4: + result = pack_harq_indication_tdd_harq_data(&harq_indication_tdd_rel13->harq_data[idx].format_4, ppWritePackedMsg, end); + break; + + case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_FORMAT_5: + result = pack_harq_indication_tdd_harq_data(&harq_indication_tdd_rel13->harq_data[idx].format_5, ppWritePackedMsg, end); + break; + + default: + // err.... + break; + } + + if(result == 0) + return 0; + } + + return 1; } -static uint8_t pack_harq_indication_fdd_rel8_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_harq_indication_fdd_rel8_t* harq_indication_fdd_rel8 = (nfapi_harq_indication_fdd_rel8_t*)tlv; - - return ( push8(harq_indication_fdd_rel8->harq_tb1, ppWritePackedMsg, end) && - push8(harq_indication_fdd_rel8->harq_tb2, ppWritePackedMsg, end)); +static uint8_t pack_harq_indication_fdd_rel8_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_harq_indication_fdd_rel8_t *harq_indication_fdd_rel8 = (nfapi_harq_indication_fdd_rel8_t *)tlv; + return ( push8(harq_indication_fdd_rel8->harq_tb1, ppWritePackedMsg, end) && + push8(harq_indication_fdd_rel8->harq_tb2, ppWritePackedMsg, end)); } -static uint8_t pack_harq_indication_fdd_rel9_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_harq_indication_fdd_rel9_t* harq_indication_fdd_rel9 = (nfapi_harq_indication_fdd_rel9_t*)tlv; - - return ( push8(harq_indication_fdd_rel9->mode, ppWritePackedMsg, end) && - push8(harq_indication_fdd_rel9->number_of_ack_nack, ppWritePackedMsg, end) && - pusharray8(harq_indication_fdd_rel9->harq_tb_n, NFAPI_HARQ_ACK_NACK_REL9_MAX, harq_indication_fdd_rel9->number_of_ack_nack, ppWritePackedMsg, end)); +static uint8_t pack_harq_indication_fdd_rel9_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_harq_indication_fdd_rel9_t *harq_indication_fdd_rel9 = (nfapi_harq_indication_fdd_rel9_t *)tlv; + return ( push8(harq_indication_fdd_rel9->mode, ppWritePackedMsg, end) && + push8(harq_indication_fdd_rel9->number_of_ack_nack, ppWritePackedMsg, end) && + pusharray8(harq_indication_fdd_rel9->harq_tb_n, NFAPI_HARQ_ACK_NACK_REL9_MAX, harq_indication_fdd_rel9->number_of_ack_nack, ppWritePackedMsg, end)); } -static uint8_t pack_harq_indication_fdd_rel13_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_harq_indication_fdd_rel13_t* harq_indication_fdd_rel13 = (nfapi_harq_indication_fdd_rel13_t*)tlv; - - return ( push8(harq_indication_fdd_rel13->mode, ppWritePackedMsg, end) && - push16(harq_indication_fdd_rel13->number_of_ack_nack, ppWritePackedMsg, end) && - pusharray8(harq_indication_fdd_rel13->harq_tb_n, NFAPI_HARQ_ACK_NACK_REL13_MAX, harq_indication_fdd_rel13->number_of_ack_nack, ppWritePackedMsg, end)); +static uint8_t pack_harq_indication_fdd_rel13_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_harq_indication_fdd_rel13_t *harq_indication_fdd_rel13 = (nfapi_harq_indication_fdd_rel13_t *)tlv; + return ( push8(harq_indication_fdd_rel13->mode, ppWritePackedMsg, end) && + push16(harq_indication_fdd_rel13->number_of_ack_nack, ppWritePackedMsg, end) && + pusharray8(harq_indication_fdd_rel13->harq_tb_n, NFAPI_HARQ_ACK_NACK_REL13_MAX, harq_indication_fdd_rel13->number_of_ack_nack, ppWritePackedMsg, end)); } -static uint8_t pack_ul_cqi_information_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_ul_cqi_information_t* value = (nfapi_ul_cqi_information_t*)tlv; - - return ( push8(value->ul_cqi, ppWritePackedMsg, end) && - push8(value->channel, ppWritePackedMsg, end)); - +static uint8_t pack_ul_cqi_information_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_ul_cqi_information_t *value = (nfapi_ul_cqi_information_t *)tlv; + return ( push8(value->ul_cqi, ppWritePackedMsg, end) && + push8(value->channel, ppWritePackedMsg, end)); } -static uint8_t pack_harq_indication_body_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_harq_indication_body_t* value = (nfapi_harq_indication_body_t*)tlv; - - if(push16(value->number_of_harqs, ppWritePackedMsg, end) == 0) - return 0; +static uint8_t pack_harq_indication_body_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_harq_indication_body_t *value = (nfapi_harq_indication_body_t *)tlv; - uint16_t i = 0; - uint16_t total_number_of_pdus = value->number_of_harqs; - for(; i < total_number_of_pdus; ++i) - { - nfapi_harq_indication_pdu_t* pdu = &(value->harq_pdu_list[i]); + if(push16(value->number_of_harqs, ppWritePackedMsg, end) == 0) + return 0; - uint8_t* instance_length_p = *ppWritePackedMsg; - if(!push16(pdu->instance_length, ppWritePackedMsg, end)) - return 0; + uint16_t i = 0; + uint16_t total_number_of_pdus = value->number_of_harqs; - if(!(pack_tlv(NFAPI_RX_UE_INFORMATION_TAG, &pdu->rx_ue_information, ppWritePackedMsg, end, pack_rx_ue_information_value) && - pack_tlv(NFAPI_HARQ_INDICATION_TDD_REL8_TAG, &pdu->harq_indication_tdd_rel8, ppWritePackedMsg, end, pack_harq_indication_tdd_rel8_value) && - pack_tlv(NFAPI_HARQ_INDICATION_TDD_REL9_TAG, &pdu->harq_indication_tdd_rel9, ppWritePackedMsg, end, pack_harq_indication_tdd_rel9_value) && - pack_tlv(NFAPI_HARQ_INDICATION_TDD_REL13_TAG, &pdu->harq_indication_tdd_rel13, ppWritePackedMsg, end, pack_harq_indication_tdd_rel13_value) && - pack_tlv(NFAPI_HARQ_INDICATION_FDD_REL8_TAG, &pdu->harq_indication_fdd_rel8, ppWritePackedMsg, end, pack_harq_indication_fdd_rel8_value) && - pack_tlv(NFAPI_HARQ_INDICATION_FDD_REL9_TAG, &pdu->harq_indication_fdd_rel9, ppWritePackedMsg, end, pack_harq_indication_fdd_rel9_value) && - pack_tlv(NFAPI_HARQ_INDICATION_FDD_REL13_TAG, &pdu->harq_indication_fdd_rel13, ppWritePackedMsg, end, pack_harq_indication_fdd_rel13_value) && - pack_tlv(NFAPI_UL_CQI_INFORMATION_TAG, &pdu->ul_cqi_information, ppWritePackedMsg, end, pack_ul_cqi_information_value))) - return 0; + for(; i < total_number_of_pdus; ++i) { + nfapi_harq_indication_pdu_t *pdu = &(value->harq_pdu_list[i]); + uint8_t *instance_length_p = *ppWritePackedMsg; - // calculate the instance length subtracting the size of the instance - // length feild - uint16_t instance_length = *ppWritePackedMsg - instance_length_p - 2; - push16(instance_length, &instance_length_p, end); - } + if(!push16(pdu->instance_length, ppWritePackedMsg, end)) + return 0; - return 1; + if(!(pack_tlv(NFAPI_RX_UE_INFORMATION_TAG, &pdu->rx_ue_information, ppWritePackedMsg, end, pack_rx_ue_information_value) && + pack_tlv(NFAPI_HARQ_INDICATION_TDD_REL8_TAG, &pdu->harq_indication_tdd_rel8, ppWritePackedMsg, end, pack_harq_indication_tdd_rel8_value) && + pack_tlv(NFAPI_HARQ_INDICATION_TDD_REL9_TAG, &pdu->harq_indication_tdd_rel9, ppWritePackedMsg, end, pack_harq_indication_tdd_rel9_value) && + pack_tlv(NFAPI_HARQ_INDICATION_TDD_REL13_TAG, &pdu->harq_indication_tdd_rel13, ppWritePackedMsg, end, pack_harq_indication_tdd_rel13_value) && + pack_tlv(NFAPI_HARQ_INDICATION_FDD_REL8_TAG, &pdu->harq_indication_fdd_rel8, ppWritePackedMsg, end, pack_harq_indication_fdd_rel8_value) && + pack_tlv(NFAPI_HARQ_INDICATION_FDD_REL9_TAG, &pdu->harq_indication_fdd_rel9, ppWritePackedMsg, end, pack_harq_indication_fdd_rel9_value) && + pack_tlv(NFAPI_HARQ_INDICATION_FDD_REL13_TAG, &pdu->harq_indication_fdd_rel13, ppWritePackedMsg, end, pack_harq_indication_fdd_rel13_value) && + pack_tlv(NFAPI_UL_CQI_INFORMATION_TAG, &pdu->ul_cqi_information, ppWritePackedMsg, end, pack_ul_cqi_information_value))) + return 0; + + // calculate the instance length subtracting the size of the instance + // length feild + uint16_t instance_length = *ppWritePackedMsg - instance_length_p - 2; + push16(instance_length, &instance_length_p, end); + } + + return 1; } -static uint8_t pack_harq_indication(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) -{ - nfapi_harq_indication_t *pNfapiMsg = (nfapi_harq_indication_t*)msg; - - return ( push16(pNfapiMsg->sfn_sf, ppWritePackedMsg, end) && - pack_tlv(NFAPI_HARQ_INDICATION_BODY_TAG, &pNfapiMsg->harq_indication_body, ppWritePackedMsg, end, pack_harq_indication_body_value) && - pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); +static uint8_t pack_harq_indication(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t *config) { + nfapi_harq_indication_t *pNfapiMsg = (nfapi_harq_indication_t *)msg; + return ( push16(pNfapiMsg->sfn_sf, ppWritePackedMsg, end) && + pack_tlv(NFAPI_HARQ_INDICATION_BODY_TAG, &pNfapiMsg->harq_indication_body, ppWritePackedMsg, end, pack_harq_indication_body_value) && + pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); } -static uint8_t pack_crc_indication_rel8_body(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_crc_indication_rel8_t* crc_indication_rel8 = (nfapi_crc_indication_rel8_t*)tlv; - - return ( push8(crc_indication_rel8->crc_flag, ppWritePackedMsg, end) ); +static uint8_t pack_crc_indication_rel8_body(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_crc_indication_rel8_t *crc_indication_rel8 = (nfapi_crc_indication_rel8_t *)tlv; + return ( push8(crc_indication_rel8->crc_flag, ppWritePackedMsg, end) ); } -static uint8_t pack_crc_indication_body_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_crc_indication_body_t* value = (nfapi_crc_indication_body_t*)tlv; - - if(push16(value->number_of_crcs, ppWritePackedMsg, end) == 0) - return 0; +static uint8_t pack_crc_indication_body_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_crc_indication_body_t *value = (nfapi_crc_indication_body_t *)tlv; - uint16_t i = 0; - uint16_t total_number_of_pdus = value->number_of_crcs; - for(; i < total_number_of_pdus; ++i) - { - nfapi_crc_indication_pdu_t* pdu = &(value->crc_pdu_list[i]); - - uint8_t* instance_length_p = *ppWritePackedMsg; - if(!push16(pdu->instance_length, ppWritePackedMsg, end)) - return 0; - - if(!(pack_tlv(NFAPI_RX_UE_INFORMATION_TAG, &pdu->rx_ue_information, ppWritePackedMsg, end, pack_rx_ue_information_value) && - pack_tlv(NFAPI_CRC_INDICATION_REL8_TAG, &pdu->crc_indication_rel8, ppWritePackedMsg, end, pack_crc_indication_rel8_body))) - return 0; + if(push16(value->number_of_crcs, ppWritePackedMsg, end) == 0) + return 0; - // calculate the instance length subtracting the size of the instance - // length feild - uint16_t instance_length = *ppWritePackedMsg - instance_length_p - 2; - push16(instance_length, &instance_length_p, end); - } - return 1; + uint16_t i = 0; + uint16_t total_number_of_pdus = value->number_of_crcs; + + for(; i < total_number_of_pdus; ++i) { + nfapi_crc_indication_pdu_t *pdu = &(value->crc_pdu_list[i]); + uint8_t *instance_length_p = *ppWritePackedMsg; + + if(!push16(pdu->instance_length, ppWritePackedMsg, end)) + return 0; + + if(!(pack_tlv(NFAPI_RX_UE_INFORMATION_TAG, &pdu->rx_ue_information, ppWritePackedMsg, end, pack_rx_ue_information_value) && + pack_tlv(NFAPI_CRC_INDICATION_REL8_TAG, &pdu->crc_indication_rel8, ppWritePackedMsg, end, pack_crc_indication_rel8_body))) + return 0; + + // calculate the instance length subtracting the size of the instance + // length feild + uint16_t instance_length = *ppWritePackedMsg - instance_length_p - 2; + push16(instance_length, &instance_length_p, end); + } + + return 1; } -static uint8_t pack_crc_indication(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) -{ - nfapi_crc_indication_t *pNfapiMsg = (nfapi_crc_indication_t*)msg; - - return ( push16(pNfapiMsg->sfn_sf, ppWritePackedMsg, end) && - pack_tlv(NFAPI_CRC_INDICATION_BODY_TAG, &pNfapiMsg->crc_indication_body, ppWritePackedMsg, end, &pack_crc_indication_body_value) && - pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); - +static uint8_t pack_crc_indication(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t *config) { + nfapi_crc_indication_t *pNfapiMsg = (nfapi_crc_indication_t *)msg; + return ( push16(pNfapiMsg->sfn_sf, ppWritePackedMsg, end) && + pack_tlv(NFAPI_CRC_INDICATION_BODY_TAG, &pNfapiMsg->crc_indication_body, ppWritePackedMsg, end, &pack_crc_indication_body_value) && + pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); } -static uint8_t pack_rx_indication_rel8_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_rx_indication_rel8_t* value = (nfapi_rx_indication_rel8_t*)tlv; - - return ( push16(value->length, ppWritePackedMsg, end) && - push16(value->offset, ppWritePackedMsg, end) && - push8(value->ul_cqi, ppWritePackedMsg, end) && - push16(value->timing_advance, ppWritePackedMsg, end)); +static uint8_t pack_rx_indication_rel8_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_rx_indication_rel8_t *value = (nfapi_rx_indication_rel8_t *)tlv; + return ( push16(value->length, ppWritePackedMsg, end) && + push16(value->offset, ppWritePackedMsg, end) && + push8(value->ul_cqi, ppWritePackedMsg, end) && + push16(value->timing_advance, ppWritePackedMsg, end)); } -static uint8_t pack_rx_indication_rel9_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_rx_indication_rel9_t* value = (nfapi_rx_indication_rel9_t*)tlv; - - return ( push16(value->timing_advance_r9, ppWritePackedMsg, end)); +static uint8_t pack_rx_indication_rel9_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_rx_indication_rel9_t *value = (nfapi_rx_indication_rel9_t *)tlv; + return ( push16(value->timing_advance_r9, ppWritePackedMsg, end)); } -static uint8_t pack_rx_ulsch_indication_body_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_rx_indication_body_t* value = (nfapi_rx_indication_body_t*)tlv; +static uint8_t pack_rx_ulsch_indication_body_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_rx_indication_body_t *value = (nfapi_rx_indication_body_t *)tlv; - //printf("RX ULSCH BODY\n"); + //printf("RX ULSCH BODY\n"); - if( push16(value->number_of_pdus, ppWritePackedMsg, end) == 0) - return 0; + if( push16(value->number_of_pdus, ppWritePackedMsg, end) == 0) + return 0; - // need to calculate the data offset's. - uint16_t i = 0; - uint16_t offset = 2; // taking into account the number_of_pdus - uint16_t total_number_of_pdus = value->number_of_pdus; - //printf("ULSCH:pdus:%d\n", total_number_of_pdus); + // need to calculate the data offset's. + uint16_t i = 0; + uint16_t offset = 2; // taking into account the number_of_pdus + uint16_t total_number_of_pdus = value->number_of_pdus; + //printf("ULSCH:pdus:%d\n", total_number_of_pdus); - for(i = 0; i < total_number_of_pdus; ++i) - { - nfapi_rx_indication_pdu_t* pdu = &(value->rx_pdu_list[i]); - if(pdu->rx_ue_information.tl.tag == NFAPI_RX_UE_INFORMATION_TAG) - { - //printf("NFAPI_RX_UE_INFORMATION_TAG\n"); - offset += 4 + 6; - } - - if(pdu->rx_indication_rel8.tl.tag == NFAPI_RX_INDICATION_REL8_TAG) - { - //printf("NFAPI_RX_INDICATION_REL8_TAG\n"); - offset += 4 + 7; - } + for(i = 0; i < total_number_of_pdus; ++i) { + nfapi_rx_indication_pdu_t *pdu = &(value->rx_pdu_list[i]); - if(pdu->rx_indication_rel9.tl.tag == NFAPI_RX_INDICATION_REL9_TAG) - { - //printf("NFAPI_RX_INDICATION_REL9_TAG\n"); - offset += 4 + 2; - } - } + if(pdu->rx_ue_information.tl.tag == NFAPI_RX_UE_INFORMATION_TAG) { + //printf("NFAPI_RX_UE_INFORMATION_TAG\n"); + offset += 4 + 6; + } - // Now update the structure to include the offset - for(i =0; i < total_number_of_pdus; ++i) - { - nfapi_rx_indication_pdu_t* pdu = &(value->rx_pdu_list[i]); - - if(pdu->rx_indication_rel8.tl.tag == NFAPI_RX_INDICATION_REL8_TAG) - { - if(pdu->rx_indication_rel8.offset == 1) - { - pdu->rx_indication_rel8.offset = offset; - offset += pdu->rx_indication_rel8.length; - } - } - } - - // Write out the pdu - for(i = 0; i < total_number_of_pdus; ++i) - { - nfapi_rx_indication_pdu_t* pdu = &(value->rx_pdu_list[i]); - if(!(pack_tlv(NFAPI_RX_UE_INFORMATION_TAG, &pdu->rx_ue_information, ppWritePackedMsg, end, pack_rx_ue_information_value) && - pack_tlv(NFAPI_RX_INDICATION_REL8_TAG, &pdu->rx_indication_rel8, ppWritePackedMsg, end, pack_rx_indication_rel8_value) && - pack_tlv(NFAPI_RX_INDICATION_REL9_TAG, &pdu->rx_indication_rel9, ppWritePackedMsg, end, pack_rx_indication_rel9_value))) - return 0; - } + if(pdu->rx_indication_rel8.tl.tag == NFAPI_RX_INDICATION_REL8_TAG) { + //printf("NFAPI_RX_INDICATION_REL8_TAG\n"); + offset += 4 + 7; + } - // Write out the pdu data - for(i = 0; i < total_number_of_pdus; ++i) - { - uint16_t length = 0; - nfapi_rx_indication_pdu_t* pdu = &(value->rx_pdu_list[i]); + if(pdu->rx_indication_rel9.tl.tag == NFAPI_RX_INDICATION_REL9_TAG) { + //printf("NFAPI_RX_INDICATION_REL9_TAG\n"); + offset += 4 + 2; + } + } - if(pdu->rx_indication_rel8.tl.tag == NFAPI_RX_INDICATION_REL8_TAG) - { - length = pdu->rx_indication_rel8.length; - } + // Now update the structure to include the offset + for(i =0; i < total_number_of_pdus; ++i) { + nfapi_rx_indication_pdu_t *pdu = &(value->rx_pdu_list[i]); - if( pusharray8(value->rx_pdu_list[i].data, length, length, ppWritePackedMsg, end) == 0) - return 0; - } - return 1; + if(pdu->rx_indication_rel8.tl.tag == NFAPI_RX_INDICATION_REL8_TAG) { + if(pdu->rx_indication_rel8.offset == 1) { + pdu->rx_indication_rel8.offset = offset; + offset += pdu->rx_indication_rel8.length; + } + } + } + + // Write out the pdu + for(i = 0; i < total_number_of_pdus; ++i) { + nfapi_rx_indication_pdu_t *pdu = &(value->rx_pdu_list[i]); + + if(!(pack_tlv(NFAPI_RX_UE_INFORMATION_TAG, &pdu->rx_ue_information, ppWritePackedMsg, end, pack_rx_ue_information_value) && + pack_tlv(NFAPI_RX_INDICATION_REL8_TAG, &pdu->rx_indication_rel8, ppWritePackedMsg, end, pack_rx_indication_rel8_value) && + pack_tlv(NFAPI_RX_INDICATION_REL9_TAG, &pdu->rx_indication_rel9, ppWritePackedMsg, end, pack_rx_indication_rel9_value))) + return 0; + } + + // Write out the pdu data + for(i = 0; i < total_number_of_pdus; ++i) { + uint16_t length = 0; + nfapi_rx_indication_pdu_t *pdu = &(value->rx_pdu_list[i]); + + if(pdu->rx_indication_rel8.tl.tag == NFAPI_RX_INDICATION_REL8_TAG) { + length = pdu->rx_indication_rel8.length; + } + + if( pusharray8(value->rx_pdu_list[i].data, length, length, ppWritePackedMsg, end) == 0) + return 0; + } + + return 1; } -static uint8_t pack_rx_ulsch_indication(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) -{ - nfapi_rx_indication_t *pNfapiMsg = (nfapi_rx_indication_t*)msg; - - return ( push16(pNfapiMsg->sfn_sf, ppWritePackedMsg, end) && - pack_tlv(NFAPI_RX_INDICATION_BODY_TAG, &pNfapiMsg->rx_indication_body, ppWritePackedMsg, end, pack_rx_ulsch_indication_body_value) && - pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); +static uint8_t pack_rx_ulsch_indication(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t *config) { + nfapi_rx_indication_t *pNfapiMsg = (nfapi_rx_indication_t *)msg; + return ( push16(pNfapiMsg->sfn_sf, ppWritePackedMsg, end) && + pack_tlv(NFAPI_RX_INDICATION_BODY_TAG, &pNfapiMsg->rx_indication_body, ppWritePackedMsg, end, pack_rx_ulsch_indication_body_value) && + pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); } -static uint8_t pack_preamble_pdu_rel8_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_preamble_pdu_rel8_t* preamble_rel8 = (nfapi_preamble_pdu_rel8_t*)tlv; - - return ( push16(preamble_rel8->rnti, ppWritePackedMsg, end) && - push8(preamble_rel8->preamble, ppWritePackedMsg, end) && - push16(preamble_rel8->timing_advance, ppWritePackedMsg, end)); +static uint8_t pack_preamble_pdu_rel8_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_preamble_pdu_rel8_t *preamble_rel8 = (nfapi_preamble_pdu_rel8_t *)tlv; + return ( push16(preamble_rel8->rnti, ppWritePackedMsg, end) && + push8(preamble_rel8->preamble, ppWritePackedMsg, end) && + push16(preamble_rel8->timing_advance, ppWritePackedMsg, end)); } -static uint8_t pack_preamble_pdu_rel9_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_preamble_pdu_rel9_t* preamble_rel9 = (nfapi_preamble_pdu_rel9_t*)tlv; - - return ( push16(preamble_rel9->timing_advance_r9, ppWritePackedMsg, end) ); +static uint8_t pack_preamble_pdu_rel9_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_preamble_pdu_rel9_t *preamble_rel9 = (nfapi_preamble_pdu_rel9_t *)tlv; + return ( push16(preamble_rel9->timing_advance_r9, ppWritePackedMsg, end) ); } -static uint8_t pack_preamble_pdu_rel13_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_preamble_pdu_rel13_t* preamble_rel13 = (nfapi_preamble_pdu_rel13_t*)tlv; - - return ( push8(preamble_rel13->rach_resource_type, ppWritePackedMsg, end) ); +static uint8_t pack_preamble_pdu_rel13_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_preamble_pdu_rel13_t *preamble_rel13 = (nfapi_preamble_pdu_rel13_t *)tlv; + return ( push8(preamble_rel13->rach_resource_type, ppWritePackedMsg, end) ); } -static uint8_t pack_rach_indication_body_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_rach_indication_body_t* value = (nfapi_rach_indication_body_t*)tlv; - - if( push16(value->number_of_preambles, ppWritePackedMsg, end) == 0) - return 0; +static uint8_t pack_rach_indication_body_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_rach_indication_body_t *value = (nfapi_rach_indication_body_t *)tlv; - uint16_t i = 0; - uint16_t total_number_of_pdus = value->number_of_preambles; - for(; i < total_number_of_pdus; ++i) - { - nfapi_preamble_pdu_t* pdu = &(value->preamble_list[i]); - - uint8_t* instance_length_p = *ppWritePackedMsg; - if(!push16(pdu->instance_length, ppWritePackedMsg, end)) - return 0; - - if(!(pack_tlv(NFAPI_PREAMBLE_REL8_TAG, &pdu->preamble_rel8, ppWritePackedMsg, end, pack_preamble_pdu_rel8_value) && - pack_tlv(NFAPI_PREAMBLE_REL9_TAG, &pdu->preamble_rel9, ppWritePackedMsg, end, pack_preamble_pdu_rel9_value) && - pack_tlv(NFAPI_PREAMBLE_REL13_TAG, &pdu->preamble_rel13, ppWritePackedMsg, end, pack_preamble_pdu_rel13_value))) - return 0; + if( push16(value->number_of_preambles, ppWritePackedMsg, end) == 0) + return 0; - // calculate the instance length subtracting the size of the instance - // length feild - uint16_t instance_length = *ppWritePackedMsg - instance_length_p - 2; - push16(instance_length, &instance_length_p, end); - } + uint16_t i = 0; + uint16_t total_number_of_pdus = value->number_of_preambles; - return 1; + for(; i < total_number_of_pdus; ++i) { + nfapi_preamble_pdu_t *pdu = &(value->preamble_list[i]); + uint8_t *instance_length_p = *ppWritePackedMsg; + + if(!push16(pdu->instance_length, ppWritePackedMsg, end)) + return 0; + + if(!(pack_tlv(NFAPI_PREAMBLE_REL8_TAG, &pdu->preamble_rel8, ppWritePackedMsg, end, pack_preamble_pdu_rel8_value) && + pack_tlv(NFAPI_PREAMBLE_REL9_TAG, &pdu->preamble_rel9, ppWritePackedMsg, end, pack_preamble_pdu_rel9_value) && + pack_tlv(NFAPI_PREAMBLE_REL13_TAG, &pdu->preamble_rel13, ppWritePackedMsg, end, pack_preamble_pdu_rel13_value))) + return 0; + + // calculate the instance length subtracting the size of the instance + // length feild + uint16_t instance_length = *ppWritePackedMsg - instance_length_p - 2; + push16(instance_length, &instance_length_p, end); + } + + return 1; } -static uint8_t pack_rach_indication(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) -{ - nfapi_rach_indication_t *pNfapiMsg = (nfapi_rach_indication_t*)msg; - - return ( push16(pNfapiMsg->sfn_sf, ppWritePackedMsg, end) && - pack_tlv(NFAPI_RACH_INDICATION_BODY_TAG, &pNfapiMsg->rach_indication_body, ppWritePackedMsg, end, pack_rach_indication_body_value) && - pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); +static uint8_t pack_rach_indication(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t *config) { + nfapi_rach_indication_t *pNfapiMsg = (nfapi_rach_indication_t *)msg; + return ( push16(pNfapiMsg->sfn_sf, ppWritePackedMsg, end) && + pack_tlv(NFAPI_RACH_INDICATION_BODY_TAG, &pNfapiMsg->rach_indication_body, ppWritePackedMsg, end, pack_rach_indication_body_value) && + pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); } -static uint8_t pack_srs_indication_fdd_rel8_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_srs_indication_fdd_rel8_t* srs_pdu_rel8 = (nfapi_srs_indication_fdd_rel8_t*)tlv; - - return ( push16(srs_pdu_rel8->doppler_estimation, ppWritePackedMsg, end) && - push16(srs_pdu_rel8->timing_advance, ppWritePackedMsg, end) && - push8(srs_pdu_rel8->number_of_resource_blocks, ppWritePackedMsg, end) && - push8(srs_pdu_rel8->rb_start, ppWritePackedMsg, end) && - pusharray8(srs_pdu_rel8->snr, NFAPI_NUM_RB_MAX, srs_pdu_rel8->number_of_resource_blocks, ppWritePackedMsg, end)); +static uint8_t pack_srs_indication_fdd_rel8_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_srs_indication_fdd_rel8_t *srs_pdu_rel8 = (nfapi_srs_indication_fdd_rel8_t *)tlv; + return ( push16(srs_pdu_rel8->doppler_estimation, ppWritePackedMsg, end) && + push16(srs_pdu_rel8->timing_advance, ppWritePackedMsg, end) && + push8(srs_pdu_rel8->number_of_resource_blocks, ppWritePackedMsg, end) && + push8(srs_pdu_rel8->rb_start, ppWritePackedMsg, end) && + pusharray8(srs_pdu_rel8->snr, NFAPI_NUM_RB_MAX, srs_pdu_rel8->number_of_resource_blocks, ppWritePackedMsg, end)); } -static uint8_t pack_srs_indication_fdd_rel9_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_srs_indication_fdd_rel9_t* srs_pdu_rel9 = (nfapi_srs_indication_fdd_rel9_t*)tlv; - - return ( push16(srs_pdu_rel9->timing_advance_r9, ppWritePackedMsg, end) ); +static uint8_t pack_srs_indication_fdd_rel9_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_srs_indication_fdd_rel9_t *srs_pdu_rel9 = (nfapi_srs_indication_fdd_rel9_t *)tlv; + return ( push16(srs_pdu_rel9->timing_advance_r9, ppWritePackedMsg, end) ); } -static uint8_t pack_srs_indication_tdd_rel10_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_srs_indication_ttd_rel10_t* srs_pdu_rel10 = (nfapi_srs_indication_ttd_rel10_t*)tlv; - - return ( push8(srs_pdu_rel10->uppts_symbol, ppWritePackedMsg, end) ); - +static uint8_t pack_srs_indication_tdd_rel10_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_srs_indication_ttd_rel10_t *srs_pdu_rel10 = (nfapi_srs_indication_ttd_rel10_t *)tlv; + return ( push8(srs_pdu_rel10->uppts_symbol, ppWritePackedMsg, end) ); } -static uint8_t pack_srs_indication_fdd_rel11_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_srs_indication_fdd_rel11_t* srs_pdu_rel11 = (nfapi_srs_indication_fdd_rel11_t*)tlv; - - return ( push16(srs_pdu_rel11->ul_rtoa, ppWritePackedMsg, end) ) ; +static uint8_t pack_srs_indication_fdd_rel11_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_srs_indication_fdd_rel11_t *srs_pdu_rel11 = (nfapi_srs_indication_fdd_rel11_t *)tlv; + return ( push16(srs_pdu_rel11->ul_rtoa, ppWritePackedMsg, end) ) ; } -static uint8_t pack_tdd_channel_measurement_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_tdd_channel_measurement_t* value = (nfapi_tdd_channel_measurement_t*)tlv; +static uint8_t pack_tdd_channel_measurement_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_tdd_channel_measurement_t *value = (nfapi_tdd_channel_measurement_t *)tlv; - if(!(push8(value->num_prb_per_subband, ppWritePackedMsg, end) && - push8(value->number_of_subbands, ppWritePackedMsg, end) && - push8(value->num_atennas, ppWritePackedMsg, end))) - return 0; + if(!(push8(value->num_prb_per_subband, ppWritePackedMsg, end) && + push8(value->number_of_subbands, ppWritePackedMsg, end) && + push8(value->num_atennas, ppWritePackedMsg, end))) + return 0; - uint8_t idx = 0; - for(idx = 0; idx < value->number_of_subbands; ++idx) - { - if(!(push8(value->subands[idx].subband_index, ppWritePackedMsg, end) && - pusharray16(value->subands[idx].channel, NFAPI_MAX_NUM_PHYSICAL_ANTENNAS, value->num_atennas, ppWritePackedMsg, end))) - return 0; - } + uint8_t idx = 0; - return 1; + for(idx = 0; idx < value->number_of_subbands; ++idx) { + if(!(push8(value->subands[idx].subband_index, ppWritePackedMsg, end) && + pusharray16(value->subands[idx].channel, NFAPI_MAX_NUM_PHYSICAL_ANTENNAS, value->num_atennas, ppWritePackedMsg, end))) + return 0; + } + + return 1; } -static uint8_t pack_srs_indication_body_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_srs_indication_body_t *value = (nfapi_srs_indication_body_t*)tlv; +static uint8_t pack_srs_indication_body_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_srs_indication_body_t *value = (nfapi_srs_indication_body_t *)tlv; - if( push8(value->number_of_ues, ppWritePackedMsg, end) == 0) - return 0; + if( push8(value->number_of_ues, ppWritePackedMsg, end) == 0) + return 0; - uint16_t i = 0; - uint16_t total_number_of_pdus = value->number_of_ues; - for(; i < total_number_of_pdus; ++i) - { - nfapi_srs_indication_pdu_t* pdu = &(value->srs_pdu_list[i]); - - uint8_t* instance_length_p = *ppWritePackedMsg; - if(!push16(pdu->instance_length, ppWritePackedMsg, end)) - return 0; - - if(!(pack_tlv(NFAPI_RX_UE_INFORMATION_TAG, &pdu->rx_ue_information, ppWritePackedMsg, end, &pack_rx_ue_information_value) && - pack_tlv(NFAPI_SRS_INDICATION_FDD_REL8_TAG, &pdu->srs_indication_fdd_rel8, ppWritePackedMsg, end, &pack_srs_indication_fdd_rel8_value) && - pack_tlv(NFAPI_SRS_INDICATION_FDD_REL9_TAG, &pdu->srs_indication_fdd_rel9, ppWritePackedMsg, end, &pack_srs_indication_fdd_rel9_value) && - pack_tlv(NFAPI_SRS_INDICATION_TDD_REL10_TAG, &pdu->srs_indication_tdd_rel10, ppWritePackedMsg, end, &pack_srs_indication_tdd_rel10_value) && - pack_tlv(NFAPI_SRS_INDICATION_FDD_REL11_TAG, &pdu->srs_indication_fdd_rel11, ppWritePackedMsg, end, &pack_srs_indication_fdd_rel11_value) && - pack_tlv(NFAPI_TDD_CHANNEL_MEASUREMENT_TAG, &pdu->tdd_channel_measurement, ppWritePackedMsg, end, &pack_tdd_channel_measurement_value))) - return 0; + uint16_t i = 0; + uint16_t total_number_of_pdus = value->number_of_ues; - // calculate the instance length subtracting the size of the instance - // length feild - uint16_t instance_length = *ppWritePackedMsg - instance_length_p - 2; - push16(instance_length, &instance_length_p, end); - } + for(; i < total_number_of_pdus; ++i) { + nfapi_srs_indication_pdu_t *pdu = &(value->srs_pdu_list[i]); + uint8_t *instance_length_p = *ppWritePackedMsg; - return 1; + if(!push16(pdu->instance_length, ppWritePackedMsg, end)) + return 0; + + if(!(pack_tlv(NFAPI_RX_UE_INFORMATION_TAG, &pdu->rx_ue_information, ppWritePackedMsg, end, &pack_rx_ue_information_value) && + pack_tlv(NFAPI_SRS_INDICATION_FDD_REL8_TAG, &pdu->srs_indication_fdd_rel8, ppWritePackedMsg, end, &pack_srs_indication_fdd_rel8_value) && + pack_tlv(NFAPI_SRS_INDICATION_FDD_REL9_TAG, &pdu->srs_indication_fdd_rel9, ppWritePackedMsg, end, &pack_srs_indication_fdd_rel9_value) && + pack_tlv(NFAPI_SRS_INDICATION_TDD_REL10_TAG, &pdu->srs_indication_tdd_rel10, ppWritePackedMsg, end, &pack_srs_indication_tdd_rel10_value) && + pack_tlv(NFAPI_SRS_INDICATION_FDD_REL11_TAG, &pdu->srs_indication_fdd_rel11, ppWritePackedMsg, end, &pack_srs_indication_fdd_rel11_value) && + pack_tlv(NFAPI_TDD_CHANNEL_MEASUREMENT_TAG, &pdu->tdd_channel_measurement, ppWritePackedMsg, end, &pack_tdd_channel_measurement_value))) + return 0; + + // calculate the instance length subtracting the size of the instance + // length feild + uint16_t instance_length = *ppWritePackedMsg - instance_length_p - 2; + push16(instance_length, &instance_length_p, end); + } + + return 1; } -static uint8_t pack_srs_indication(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) -{ - nfapi_srs_indication_t *pNfapiMsg = (nfapi_srs_indication_t*)msg; - - return ( push16(pNfapiMsg->sfn_sf, ppWritePackedMsg, end) && - pack_tlv(NFAPI_SRS_INDICATION_BODY_TAG, &pNfapiMsg->srs_indication_body, ppWritePackedMsg, end, &pack_srs_indication_body_value) && - pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); - +static uint8_t pack_srs_indication(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t *config) { + nfapi_srs_indication_t *pNfapiMsg = (nfapi_srs_indication_t *)msg; + return ( push16(pNfapiMsg->sfn_sf, ppWritePackedMsg, end) && + pack_tlv(NFAPI_SRS_INDICATION_BODY_TAG, &pNfapiMsg->srs_indication_body, ppWritePackedMsg, end, &pack_srs_indication_body_value) && + pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); } -static uint8_t pack_sr_indication_body_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_sr_indication_body_t* value = (nfapi_sr_indication_body_t*)tlv; +static uint8_t pack_sr_indication_body_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_sr_indication_body_t *value = (nfapi_sr_indication_body_t *)tlv; - if(push16(value->number_of_srs, ppWritePackedMsg, end) == 0) - return 0; + if(push16(value->number_of_srs, ppWritePackedMsg, end) == 0) + return 0; - uint16_t i = 0; - uint16_t total_number_of_pdus = value->number_of_srs; - for(; i < total_number_of_pdus; ++i) - { - nfapi_sr_indication_pdu_t* pdu = &(value->sr_pdu_list[i]); + uint16_t i = 0; + uint16_t total_number_of_pdus = value->number_of_srs; - uint8_t* instance_length_p = *ppWritePackedMsg; - if(!push16(pdu->instance_length, ppWritePackedMsg, end)) - return 0; + for(; i < total_number_of_pdus; ++i) { + nfapi_sr_indication_pdu_t *pdu = &(value->sr_pdu_list[i]); + uint8_t *instance_length_p = *ppWritePackedMsg; - if(!(pack_tlv(NFAPI_RX_UE_INFORMATION_TAG, &pdu->rx_ue_information, ppWritePackedMsg, end, pack_rx_ue_information_value) && - pack_tlv(NFAPI_UL_CQI_INFORMATION_TAG, &pdu->ul_cqi_information, ppWritePackedMsg, end, pack_ul_cqi_information_value))) - return 0; + if(!push16(pdu->instance_length, ppWritePackedMsg, end)) + return 0; - // calculate the instance length subtracting the size of the instance - // length feild - uint16_t instance_length = *ppWritePackedMsg - instance_length_p - 2; - push16(instance_length, &instance_length_p, end); - } - return 1; + if(!(pack_tlv(NFAPI_RX_UE_INFORMATION_TAG, &pdu->rx_ue_information, ppWritePackedMsg, end, pack_rx_ue_information_value) && + pack_tlv(NFAPI_UL_CQI_INFORMATION_TAG, &pdu->ul_cqi_information, ppWritePackedMsg, end, pack_ul_cqi_information_value))) + return 0; + + // calculate the instance length subtracting the size of the instance + // length feild + uint16_t instance_length = *ppWritePackedMsg - instance_length_p - 2; + push16(instance_length, &instance_length_p, end); + } + + return 1; } -static uint8_t pack_sr_indication(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) -{ - nfapi_sr_indication_t *pNfapiMsg = (nfapi_sr_indication_t*)msg; - - return ( push16(pNfapiMsg->sfn_sf, ppWritePackedMsg, end) && - pack_tlv(NFAPI_SR_INDICATION_BODY_TAG, &pNfapiMsg->sr_indication_body, ppWritePackedMsg, end, &pack_sr_indication_body_value) && - pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); - +static uint8_t pack_sr_indication(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t *config) { + nfapi_sr_indication_t *pNfapiMsg = (nfapi_sr_indication_t *)msg; + return ( push16(pNfapiMsg->sfn_sf, ppWritePackedMsg, end) && + pack_tlv(NFAPI_SR_INDICATION_BODY_TAG, &pNfapiMsg->sr_indication_body, ppWritePackedMsg, end, &pack_sr_indication_body_value) && + pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); } -static uint8_t pack_cqi_indication_rel8_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_cqi_indication_rel8_t* cqi_pdu_rel8 = (nfapi_cqi_indication_rel8_t*)tlv; - - return ( push16(cqi_pdu_rel8->length, ppWritePackedMsg, end) && - push16(cqi_pdu_rel8->data_offset, ppWritePackedMsg, end) && - push8(cqi_pdu_rel8->ul_cqi, ppWritePackedMsg, end) && - push8(cqi_pdu_rel8->ri, ppWritePackedMsg, end) && - push16(cqi_pdu_rel8->timing_advance, ppWritePackedMsg, end)); +static uint8_t pack_cqi_indication_rel8_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_cqi_indication_rel8_t *cqi_pdu_rel8 = (nfapi_cqi_indication_rel8_t *)tlv; + return ( push16(cqi_pdu_rel8->length, ppWritePackedMsg, end) && + push16(cqi_pdu_rel8->data_offset, ppWritePackedMsg, end) && + push8(cqi_pdu_rel8->ul_cqi, ppWritePackedMsg, end) && + push8(cqi_pdu_rel8->ri, ppWritePackedMsg, end) && + push16(cqi_pdu_rel8->timing_advance, ppWritePackedMsg, end)); } -static uint8_t pack_cqi_indication_rel9_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_cqi_indication_rel9_t* cqi_pdu_rel9 = (nfapi_cqi_indication_rel9_t*)tlv; - - return ( push16(cqi_pdu_rel9->length, ppWritePackedMsg, end) && - push16(cqi_pdu_rel9->data_offset, ppWritePackedMsg, end) && - push8(cqi_pdu_rel9->ul_cqi, ppWritePackedMsg, end) && - push8(cqi_pdu_rel9->number_of_cc_reported, ppWritePackedMsg, end) && - pusharray8(cqi_pdu_rel9->ri, NFAPI_CC_MAX, cqi_pdu_rel9->number_of_cc_reported, ppWritePackedMsg, end) && - push16(cqi_pdu_rel9->timing_advance, ppWritePackedMsg, end) && - push16(cqi_pdu_rel9->timing_advance_r9, ppWritePackedMsg, end)); +static uint8_t pack_cqi_indication_rel9_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_cqi_indication_rel9_t *cqi_pdu_rel9 = (nfapi_cqi_indication_rel9_t *)tlv; + return ( push16(cqi_pdu_rel9->length, ppWritePackedMsg, end) && + push16(cqi_pdu_rel9->data_offset, ppWritePackedMsg, end) && + push8(cqi_pdu_rel9->ul_cqi, ppWritePackedMsg, end) && + push8(cqi_pdu_rel9->number_of_cc_reported, ppWritePackedMsg, end) && + pusharray8(cqi_pdu_rel9->ri, NFAPI_CC_MAX, cqi_pdu_rel9->number_of_cc_reported, ppWritePackedMsg, end) && + push16(cqi_pdu_rel9->timing_advance, ppWritePackedMsg, end) && + push16(cqi_pdu_rel9->timing_advance_r9, ppWritePackedMsg, end)); } -static uint8_t pack_cqi_indication_body_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_cqi_indication_body_t* value = (nfapi_cqi_indication_body_t*)tlv; +static uint8_t pack_cqi_indication_body_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_cqi_indication_body_t *value = (nfapi_cqi_indication_body_t *)tlv; - if( push16(value->number_of_cqis, ppWritePackedMsg, end) == 0) - return 0; + if( push16(value->number_of_cqis, ppWritePackedMsg, end) == 0) + return 0; - // need to calculate the data offset's. This very bittle due the hardcoding - // of the sizes. can not use the sizeof as we have an array for the Rel9 - // info - uint16_t i = 0; - uint16_t offset = 2; // taking into account the number_of_cqis - uint16_t total_number_of_pdus = value->number_of_cqis; - for(i = 0; i < total_number_of_pdus; ++i) - { - nfapi_cqi_indication_pdu_t* pdu = &(value->cqi_pdu_list[i]); - - offset += 2; // for the instance length - - if(pdu->rx_ue_information.tl.tag == NFAPI_RX_UE_INFORMATION_TAG) - { - offset += 4 + 6; // sizeof(nfapi_rx_ue_information) - sizeof(nfapi_tl_t) - } - - if(pdu->cqi_indication_rel8.tl.tag == NFAPI_CQI_INDICATION_REL8_TAG) - { - offset += 4 + 8; - } + // need to calculate the data offset's. This very bittle due the hardcoding + // of the sizes. can not use the sizeof as we have an array for the Rel9 + // info + uint16_t i = 0; + uint16_t offset = 2; // taking into account the number_of_cqis + uint16_t total_number_of_pdus = value->number_of_cqis; - if(pdu->cqi_indication_rel9.tl.tag == NFAPI_CQI_INDICATION_REL9_TAG) - { - offset += 4 + 10 + pdu->cqi_indication_rel9.number_of_cc_reported; - } + for(i = 0; i < total_number_of_pdus; ++i) { + nfapi_cqi_indication_pdu_t *pdu = &(value->cqi_pdu_list[i]); + offset += 2; // for the instance length - if(pdu->ul_cqi_information.tl.tag == NFAPI_UL_CQI_INFORMATION_TAG) - { - offset += 4 + 2; - } - } + if(pdu->rx_ue_information.tl.tag == NFAPI_RX_UE_INFORMATION_TAG) { + offset += 4 + 6; // sizeof(nfapi_rx_ue_information) - sizeof(nfapi_tl_t) + } - // Now update the structure to include the offset - for(i =0; i < total_number_of_pdus; ++i) - { - nfapi_cqi_indication_pdu_t* pdu = &(value->cqi_pdu_list[i]); - - if(pdu->cqi_indication_rel8.tl.tag == NFAPI_CQI_INDICATION_REL8_TAG) - { - if(pdu->cqi_indication_rel8.data_offset == 1) - { - pdu->cqi_indication_rel8.data_offset = offset; - offset += pdu->cqi_indication_rel8.length; - } - } + if(pdu->cqi_indication_rel8.tl.tag == NFAPI_CQI_INDICATION_REL8_TAG) { + offset += 4 + 8; + } - if(pdu->cqi_indication_rel9.tl.tag == NFAPI_CQI_INDICATION_REL9_TAG) - { - if(pdu->cqi_indication_rel9.data_offset == 1) - { - pdu->cqi_indication_rel9.data_offset = offset; - offset += pdu->cqi_indication_rel9.length; - } - } + if(pdu->cqi_indication_rel9.tl.tag == NFAPI_CQI_INDICATION_REL9_TAG) { + offset += 4 + 10 + pdu->cqi_indication_rel9.number_of_cc_reported; + } - } - - // Write out the cqi information - for(i = 0; i < total_number_of_pdus; ++i) - { - nfapi_cqi_indication_pdu_t* pdu = &(value->cqi_pdu_list[i]); + if(pdu->ul_cqi_information.tl.tag == NFAPI_UL_CQI_INFORMATION_TAG) { + offset += 4 + 2; + } + } - uint8_t* instance_length_p = *ppWritePackedMsg; - if(!push16(pdu->instance_length, ppWritePackedMsg, end)) - return 0; - - if(!(pack_tlv(NFAPI_RX_UE_INFORMATION_TAG, &pdu->rx_ue_information, ppWritePackedMsg, end ,pack_rx_ue_information_value) && - pack_tlv(NFAPI_CQI_INDICATION_REL8_TAG, &pdu->cqi_indication_rel8, ppWritePackedMsg, end, pack_cqi_indication_rel8_value) && - pack_tlv(NFAPI_CQI_INDICATION_REL9_TAG, &pdu->cqi_indication_rel9, ppWritePackedMsg, end, pack_cqi_indication_rel9_value) && - pack_tlv(NFAPI_UL_CQI_INFORMATION_TAG, &pdu->ul_cqi_information, ppWritePackedMsg, end, pack_ul_cqi_information_value))) - return 0; + // Now update the structure to include the offset + for(i =0; i < total_number_of_pdus; ++i) { + nfapi_cqi_indication_pdu_t *pdu = &(value->cqi_pdu_list[i]); - // calculate the instance length subtracting the size of the instance - // length feild - uint16_t instance_length = *ppWritePackedMsg - instance_length_p - 2; - push16(instance_length, &instance_length_p, end); - - } + if(pdu->cqi_indication_rel8.tl.tag == NFAPI_CQI_INDICATION_REL8_TAG) { + if(pdu->cqi_indication_rel8.data_offset == 1) { + pdu->cqi_indication_rel8.data_offset = offset; + offset += pdu->cqi_indication_rel8.length; + } + } - // Write out the cqi raw data - for(i = 0; i < total_number_of_pdus; ++i) - { - uint16_t length = 0; - nfapi_cqi_indication_pdu_t* pdu = &(value->cqi_pdu_list[i]); + if(pdu->cqi_indication_rel9.tl.tag == NFAPI_CQI_INDICATION_REL9_TAG) { + if(pdu->cqi_indication_rel9.data_offset == 1) { + pdu->cqi_indication_rel9.data_offset = offset; + offset += pdu->cqi_indication_rel9.length; + } + } + } - if(pdu->cqi_indication_rel8.tl.tag == NFAPI_CQI_INDICATION_REL8_TAG) - { - length = pdu->cqi_indication_rel8.length; - } + // Write out the cqi information + for(i = 0; i < total_number_of_pdus; ++i) { + nfapi_cqi_indication_pdu_t *pdu = &(value->cqi_pdu_list[i]); + uint8_t *instance_length_p = *ppWritePackedMsg; - if(pdu->cqi_indication_rel9.tl.tag == NFAPI_CQI_INDICATION_REL9_TAG) - { - length = pdu->cqi_indication_rel9.length; - } + if(!push16(pdu->instance_length, ppWritePackedMsg, end)) + return 0; - if( pusharray8(value->cqi_raw_pdu_list[i].pdu, NFAPI_CQI_RAW_MAX_LEN, length, ppWritePackedMsg, end) == 0) - return 0; - } + if(!(pack_tlv(NFAPI_RX_UE_INFORMATION_TAG, &pdu->rx_ue_information, ppWritePackedMsg, end,pack_rx_ue_information_value) && + pack_tlv(NFAPI_CQI_INDICATION_REL8_TAG, &pdu->cqi_indication_rel8, ppWritePackedMsg, end, pack_cqi_indication_rel8_value) && + pack_tlv(NFAPI_CQI_INDICATION_REL9_TAG, &pdu->cqi_indication_rel9, ppWritePackedMsg, end, pack_cqi_indication_rel9_value) && + pack_tlv(NFAPI_UL_CQI_INFORMATION_TAG, &pdu->ul_cqi_information, ppWritePackedMsg, end, pack_ul_cqi_information_value))) + return 0; - return 1; + // calculate the instance length subtracting the size of the instance + // length feild + uint16_t instance_length = *ppWritePackedMsg - instance_length_p - 2; + push16(instance_length, &instance_length_p, end); + } + + // Write out the cqi raw data + for(i = 0; i < total_number_of_pdus; ++i) { + uint16_t length = 0; + nfapi_cqi_indication_pdu_t *pdu = &(value->cqi_pdu_list[i]); + + if(pdu->cqi_indication_rel8.tl.tag == NFAPI_CQI_INDICATION_REL8_TAG) { + length = pdu->cqi_indication_rel8.length; + } + + if(pdu->cqi_indication_rel9.tl.tag == NFAPI_CQI_INDICATION_REL9_TAG) { + length = pdu->cqi_indication_rel9.length; + } + + if( pusharray8(value->cqi_raw_pdu_list[i].pdu, NFAPI_CQI_RAW_MAX_LEN, length, ppWritePackedMsg, end) == 0) + return 0; + } + + return 1; } -static uint8_t pack_cqi_indication(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) -{ - nfapi_cqi_indication_t *pNfapiMsg = (nfapi_cqi_indication_t*)msg; - - return ( push16(pNfapiMsg->sfn_sf, ppWritePackedMsg, end) && - pack_tlv(NFAPI_CQI_INDICATION_BODY_TAG, &pNfapiMsg->cqi_indication_body, ppWritePackedMsg, end, pack_cqi_indication_body_value) && - pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); - +static uint8_t pack_cqi_indication(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t *config) { + nfapi_cqi_indication_t *pNfapiMsg = (nfapi_cqi_indication_t *)msg; + return ( push16(pNfapiMsg->sfn_sf, ppWritePackedMsg, end) && + pack_tlv(NFAPI_CQI_INDICATION_BODY_TAG, &pNfapiMsg->cqi_indication_body, ppWritePackedMsg, end, pack_cqi_indication_body_value) && + pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); } -static uint8_t pack_lbt_pdsch_req_pdu_rel13_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_lbt_pdsch_req_pdu_rel13_t* value = (nfapi_lbt_pdsch_req_pdu_rel13_t*)tlv; - - return ( push32(value->handle, ppWritePackedMsg, end) && - push32(value->mp_cca, ppWritePackedMsg, end) && - push32(value->n_cca, ppWritePackedMsg, end) && - push32(value->offset, ppWritePackedMsg, end) && - push32(value->lte_txop_sf, ppWritePackedMsg, end) && - push16(value->txop_sfn_sf_end, ppWritePackedMsg, end) && - push32(value->lbt_mode, ppWritePackedMsg, end)); +static uint8_t pack_lbt_pdsch_req_pdu_rel13_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_lbt_pdsch_req_pdu_rel13_t *value = (nfapi_lbt_pdsch_req_pdu_rel13_t *)tlv; + return ( push32(value->handle, ppWritePackedMsg, end) && + push32(value->mp_cca, ppWritePackedMsg, end) && + push32(value->n_cca, ppWritePackedMsg, end) && + push32(value->offset, ppWritePackedMsg, end) && + push32(value->lte_txop_sf, ppWritePackedMsg, end) && + push16(value->txop_sfn_sf_end, ppWritePackedMsg, end) && + push32(value->lbt_mode, ppWritePackedMsg, end)); } -static uint8_t pack_lbt_drs_req_pdu_rel13_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_lbt_drs_req_pdu_rel13_t* value = (nfapi_lbt_drs_req_pdu_rel13_t*)tlv; - - return ( push32(value->handle, ppWritePackedMsg, end) && - push32(value->offset, ppWritePackedMsg, end) && - push16(value->sfn_sf_end, ppWritePackedMsg, end) && - push32(value->lbt_mode, ppWritePackedMsg, end)); +static uint8_t pack_lbt_drs_req_pdu_rel13_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_lbt_drs_req_pdu_rel13_t *value = (nfapi_lbt_drs_req_pdu_rel13_t *)tlv; + return ( push32(value->handle, ppWritePackedMsg, end) && + push32(value->offset, ppWritePackedMsg, end) && + push16(value->sfn_sf_end, ppWritePackedMsg, end) && + push32(value->lbt_mode, ppWritePackedMsg, end)); } -static uint8_t pack_lbt_dl_config_request_body_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_lbt_dl_config_request_body_t* value = (nfapi_lbt_dl_config_request_body_t*)tlv; - - if( push16(value->number_of_pdus, ppWritePackedMsg, end) == 0) - return 0; +static uint8_t pack_lbt_dl_config_request_body_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_lbt_dl_config_request_body_t *value = (nfapi_lbt_dl_config_request_body_t *)tlv; - uint16_t i = 0; - uint16_t total_number_of_pdus = value->number_of_pdus; - for(; i < total_number_of_pdus; ++i) - { - nfapi_lbt_dl_config_request_pdu_t* pdu = &(value->lbt_dl_config_req_pdu_list[i]); - - if( push8(pdu->pdu_type, ppWritePackedMsg, end) == 0) - return 0; + if( push16(value->number_of_pdus, ppWritePackedMsg, end) == 0) + return 0; - // Put a 0 size in and then determine the size after the pdu - // has been writen and write the calculated size - uint8_t* pWritePackedMsgPduSize = *ppWritePackedMsg; - pdu->pdu_size = 0; - if( push8(pdu->pdu_size, ppWritePackedMsg, end) == 0) - return 0; + uint16_t i = 0; + uint16_t total_number_of_pdus = value->number_of_pdus; - switch(pdu->pdu_type) - { - case NFAPI_LBT_DL_CONFIG_REQUEST_PDSCH_PDU_TYPE: - { - if( pack_tlv(NFAPI_LBT_PDSCH_REQ_PDU_REL13_TAG, &pdu->lbt_pdsch_req_pdu.lbt_pdsch_req_pdu_rel13, ppWritePackedMsg, end, pack_lbt_pdsch_req_pdu_rel13_value) == 0) - return 0; - } - break; - case NFAPI_LBT_DL_CONFIG_REQUEST_DRS_PDU_TYPE: - { - if(pack_tlv(NFAPI_LBT_DRS_REQ_PDU_REL13_TAG, &pdu->lbt_drs_req_pdu.lbt_drs_req_pdu_rel13, ppWritePackedMsg, end, pack_lbt_drs_req_pdu_rel13_value) == 0) - return 0; - } - break; - default: - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "LBT_DL_CONFIG.request invalid pdu type %d \n", pdu->pdu_type ); - } - break; - }; + for(; i < total_number_of_pdus; ++i) { + nfapi_lbt_dl_config_request_pdu_t *pdu = &(value->lbt_dl_config_req_pdu_list[i]); - // add 1 for the pdu_type. The delta will include the pdu_size - pdu->pdu_size = 1 + (*ppWritePackedMsg - pWritePackedMsgPduSize); - push8(pdu->pdu_size, &pWritePackedMsgPduSize, end); - } + if( push8(pdu->pdu_type, ppWritePackedMsg, end) == 0) + return 0; - return 1; + // Put a 0 size in and then determine the size after the pdu + // has been writen and write the calculated size + uint8_t *pWritePackedMsgPduSize = *ppWritePackedMsg; + pdu->pdu_size = 0; + + if( push8(pdu->pdu_size, ppWritePackedMsg, end) == 0) + return 0; + + switch(pdu->pdu_type) { + case NFAPI_LBT_DL_CONFIG_REQUEST_PDSCH_PDU_TYPE: { + if( pack_tlv(NFAPI_LBT_PDSCH_REQ_PDU_REL13_TAG, &pdu->lbt_pdsch_req_pdu.lbt_pdsch_req_pdu_rel13, ppWritePackedMsg, end, pack_lbt_pdsch_req_pdu_rel13_value) == 0) + return 0; + } + break; + + case NFAPI_LBT_DL_CONFIG_REQUEST_DRS_PDU_TYPE: { + if(pack_tlv(NFAPI_LBT_DRS_REQ_PDU_REL13_TAG, &pdu->lbt_drs_req_pdu.lbt_drs_req_pdu_rel13, ppWritePackedMsg, end, pack_lbt_drs_req_pdu_rel13_value) == 0) + return 0; + } + break; + + default: { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "LBT_DL_CONFIG.request invalid pdu type %d \n", pdu->pdu_type ); + } + break; + }; + + // add 1 for the pdu_type. The delta will include the pdu_size + pdu->pdu_size = 1 + (*ppWritePackedMsg - pWritePackedMsgPduSize); + + push8(pdu->pdu_size, &pWritePackedMsgPduSize, end); + } + + return 1; } -static uint8_t pack_lbt_pdsch_rsp_pdu_rel13_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_lbt_pdsch_rsp_pdu_rel13_t* value = (nfapi_lbt_pdsch_rsp_pdu_rel13_t*)tlv; - - return ( push32(value->handle, ppWritePackedMsg, end) && - push32(value->result, ppWritePackedMsg, end) && - push32(value->lte_txop_symbols, ppWritePackedMsg, end) && - push32(value->initial_partial_sf, ppWritePackedMsg, end)); +static uint8_t pack_lbt_pdsch_rsp_pdu_rel13_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_lbt_pdsch_rsp_pdu_rel13_t *value = (nfapi_lbt_pdsch_rsp_pdu_rel13_t *)tlv; + return ( push32(value->handle, ppWritePackedMsg, end) && + push32(value->result, ppWritePackedMsg, end) && + push32(value->lte_txop_symbols, ppWritePackedMsg, end) && + push32(value->initial_partial_sf, ppWritePackedMsg, end)); } -static uint8_t pack_lbt_drs_rsp_pdu_rel13_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_lbt_drs_rsp_pdu_rel13_t* value = (nfapi_lbt_drs_rsp_pdu_rel13_t*)tlv; - - return ( push32(value->handle, ppWritePackedMsg, end) && - push32(value->result, ppWritePackedMsg, end)); +static uint8_t pack_lbt_drs_rsp_pdu_rel13_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_lbt_drs_rsp_pdu_rel13_t *value = (nfapi_lbt_drs_rsp_pdu_rel13_t *)tlv; + return ( push32(value->handle, ppWritePackedMsg, end) && + push32(value->result, ppWritePackedMsg, end)); } -static uint8_t pack_lbt_dl_config_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) -{ - nfapi_lbt_dl_config_request_t *pNfapiMsg = (nfapi_lbt_dl_config_request_t*)msg; - - return ( push16(pNfapiMsg->sfn_sf, ppWritePackedMsg, end) && - pack_tlv(NFAPI_LBT_DL_CONFIG_REQUEST_BODY_TAG, &pNfapiMsg->lbt_dl_config_request_body, ppWritePackedMsg, end, &pack_lbt_dl_config_request_body_value) && - pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); +static uint8_t pack_lbt_dl_config_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t *config) { + nfapi_lbt_dl_config_request_t *pNfapiMsg = (nfapi_lbt_dl_config_request_t *)msg; + return ( push16(pNfapiMsg->sfn_sf, ppWritePackedMsg, end) && + pack_tlv(NFAPI_LBT_DL_CONFIG_REQUEST_BODY_TAG, &pNfapiMsg->lbt_dl_config_request_body, ppWritePackedMsg, end, &pack_lbt_dl_config_request_body_value) && + pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); } -static uint8_t pack_lbt_dl_config_indication_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_lbt_dl_indication_body_t* value = (nfapi_lbt_dl_indication_body_t*)tlv; - - if( push16(value->number_of_pdus, ppWritePackedMsg, end) == 0) - return 0; +static uint8_t pack_lbt_dl_config_indication_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_lbt_dl_indication_body_t *value = (nfapi_lbt_dl_indication_body_t *)tlv; - uint16_t i = 0; - uint16_t total_number_of_pdus = value->number_of_pdus; - for(; i < total_number_of_pdus; ++i) - { - nfapi_lbt_dl_indication_pdu_t* pdu = &(value->lbt_indication_pdu_list[i]); - - if( push8(pdu->pdu_type, ppWritePackedMsg, end) == 0) - return 0; + if( push16(value->number_of_pdus, ppWritePackedMsg, end) == 0) + return 0; - // Put a 0 size in and then determine the size after the pdu - // has been writen and write the calculated size - uint8_t* pWritePackedMsgPduSize = *ppWritePackedMsg; - pdu->pdu_size = 0; - - if(push8(pdu->pdu_size, ppWritePackedMsg, end) == 0) - return 0; + uint16_t i = 0; + uint16_t total_number_of_pdus = value->number_of_pdus; - switch(pdu->pdu_type) - { - case NFAPI_LBT_DL_RSP_PDSCH_PDU_TYPE: - { - if( pack_tlv(NFAPI_LBT_PDSCH_RSP_PDU_REL13_TAG, &pdu->lbt_pdsch_rsp_pdu.lbt_pdsch_rsp_pdu_rel13, ppWritePackedMsg, end, pack_lbt_pdsch_rsp_pdu_rel13_value) == 0) - return 0; - } - break; - case NFAPI_LBT_DL_RSP_DRS_PDU_TYPE: - { - if( pack_tlv(NFAPI_LBT_DRS_RSP_PDU_REL13_TAG, &pdu->lbt_drs_rsp_pdu.lbt_drs_rsp_pdu_rel13, ppWritePackedMsg, end, pack_lbt_drs_rsp_pdu_rel13_value) == 0) - return 0; - } - break; - default: - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "LBT_DL.indication body invalid pdu type %d \n", pdu->pdu_type ); - } - break; - }; + for(; i < total_number_of_pdus; ++i) { + nfapi_lbt_dl_indication_pdu_t *pdu = &(value->lbt_indication_pdu_list[i]); - // add 1 for the pdu_type. The delta will include the pdu_size - pdu->pdu_size = 1 + (*ppWritePackedMsg - pWritePackedMsgPduSize); - push8(pdu->pdu_size, &pWritePackedMsgPduSize, end); - } + if( push8(pdu->pdu_type, ppWritePackedMsg, end) == 0) + return 0; - return 1; + // Put a 0 size in and then determine the size after the pdu + // has been writen and write the calculated size + uint8_t *pWritePackedMsgPduSize = *ppWritePackedMsg; + pdu->pdu_size = 0; + + if(push8(pdu->pdu_size, ppWritePackedMsg, end) == 0) + return 0; + + switch(pdu->pdu_type) { + case NFAPI_LBT_DL_RSP_PDSCH_PDU_TYPE: { + if( pack_tlv(NFAPI_LBT_PDSCH_RSP_PDU_REL13_TAG, &pdu->lbt_pdsch_rsp_pdu.lbt_pdsch_rsp_pdu_rel13, ppWritePackedMsg, end, pack_lbt_pdsch_rsp_pdu_rel13_value) == 0) + return 0; + } + break; + + case NFAPI_LBT_DL_RSP_DRS_PDU_TYPE: { + if( pack_tlv(NFAPI_LBT_DRS_RSP_PDU_REL13_TAG, &pdu->lbt_drs_rsp_pdu.lbt_drs_rsp_pdu_rel13, ppWritePackedMsg, end, pack_lbt_drs_rsp_pdu_rel13_value) == 0) + return 0; + } + break; + + default: { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "LBT_DL.indication body invalid pdu type %d \n", pdu->pdu_type ); + } + break; + }; + + // add 1 for the pdu_type. The delta will include the pdu_size + pdu->pdu_size = 1 + (*ppWritePackedMsg - pWritePackedMsgPduSize); + + push8(pdu->pdu_size, &pWritePackedMsgPduSize, end); + } + + return 1; } -static uint8_t pack_lbt_dl_indication(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) -{ - nfapi_lbt_dl_indication_t *pNfapiMsg = (nfapi_lbt_dl_indication_t*)msg; - - return ( push16(pNfapiMsg->sfn_sf, ppWritePackedMsg, end) && - pack_tlv(NFAPI_LBT_DL_INDICATION_BODY_TAG, &pNfapiMsg->lbt_dl_indication_body, ppWritePackedMsg, end, &pack_lbt_dl_config_indication_value) && - pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); +static uint8_t pack_lbt_dl_indication(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t *config) { + nfapi_lbt_dl_indication_t *pNfapiMsg = (nfapi_lbt_dl_indication_t *)msg; + return ( push16(pNfapiMsg->sfn_sf, ppWritePackedMsg, end) && + pack_tlv(NFAPI_LBT_DL_INDICATION_BODY_TAG, &pNfapiMsg->lbt_dl_indication_body, ppWritePackedMsg, end, &pack_lbt_dl_config_indication_value) && + pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); } -static uint8_t pack_nb_harq_indication_fdd_rel13_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_nb_harq_indication_fdd_rel13_t* nb_harq_indication_fdd_rel13 = (nfapi_nb_harq_indication_fdd_rel13_t*)tlv; - - return ( push8(nb_harq_indication_fdd_rel13->harq_tb1, ppWritePackedMsg, end) ); +static uint8_t pack_nb_harq_indication_fdd_rel13_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_nb_harq_indication_fdd_rel13_t *nb_harq_indication_fdd_rel13 = (nfapi_nb_harq_indication_fdd_rel13_t *)tlv; + return ( push8(nb_harq_indication_fdd_rel13->harq_tb1, ppWritePackedMsg, end) ); } -static uint8_t pack_nb_harq_indication_body_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_nb_harq_indication_body_t* value = (nfapi_nb_harq_indication_body_t*)tlv; - - if( push16(value->number_of_harqs, ppWritePackedMsg, end) == 0) - return 0; +static uint8_t pack_nb_harq_indication_body_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_nb_harq_indication_body_t *value = (nfapi_nb_harq_indication_body_t *)tlv; - uint16_t i = 0; - uint16_t total_number_of_harqs = value->number_of_harqs; - for(; i < total_number_of_harqs; ++i) - { - nfapi_nb_harq_indication_pdu_t* pdu = &(value->nb_harq_pdu_list[i]); - - uint8_t* instance_length_p = *ppWritePackedMsg; - if(!push16(pdu->instance_length, ppWritePackedMsg, end)) - return 0; + if( push16(value->number_of_harqs, ppWritePackedMsg, end) == 0) + return 0; - if(!(pack_tlv(NFAPI_RX_UE_INFORMATION_TAG, &pdu->rx_ue_information, ppWritePackedMsg, end, pack_rx_ue_information_value) && - pack_tlv(NFAPI_NB_HARQ_INDICATION_FDD_REL13_TAG, &pdu->nb_harq_indication_fdd_rel13, ppWritePackedMsg, end, pack_nb_harq_indication_fdd_rel13_value) && - pack_tlv(NFAPI_UL_CQI_INFORMATION_TAG, &pdu->ul_cqi_information, ppWritePackedMsg, end, pack_ul_cqi_information_value))) - return 0; - - // calculate the instance length subtracting the size of the instance - // length feild - uint16_t instance_length = *ppWritePackedMsg - instance_length_p - 2; - push16(instance_length, &instance_length_p, end); - } + uint16_t i = 0; + uint16_t total_number_of_harqs = value->number_of_harqs; - return 1; + for(; i < total_number_of_harqs; ++i) { + nfapi_nb_harq_indication_pdu_t *pdu = &(value->nb_harq_pdu_list[i]); + uint8_t *instance_length_p = *ppWritePackedMsg; + + if(!push16(pdu->instance_length, ppWritePackedMsg, end)) + return 0; + + if(!(pack_tlv(NFAPI_RX_UE_INFORMATION_TAG, &pdu->rx_ue_information, ppWritePackedMsg, end, pack_rx_ue_information_value) && + pack_tlv(NFAPI_NB_HARQ_INDICATION_FDD_REL13_TAG, &pdu->nb_harq_indication_fdd_rel13, ppWritePackedMsg, end, pack_nb_harq_indication_fdd_rel13_value) && + pack_tlv(NFAPI_UL_CQI_INFORMATION_TAG, &pdu->ul_cqi_information, ppWritePackedMsg, end, pack_ul_cqi_information_value))) + return 0; + + // calculate the instance length subtracting the size of the instance + // length feild + uint16_t instance_length = *ppWritePackedMsg - instance_length_p - 2; + push16(instance_length, &instance_length_p, end); + } + + return 1; } -static uint8_t pack_nb_harq_indication(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) -{ - nfapi_nb_harq_indication_t *pNfapiMsg = (nfapi_nb_harq_indication_t*)msg; - - return ( push16(pNfapiMsg->sfn_sf, ppWritePackedMsg, end) && - pack_tlv(NFAPI_NB_HARQ_INDICATION_BODY_TAG, &pNfapiMsg->nb_harq_indication_body, ppWritePackedMsg, end, &pack_nb_harq_indication_body_value) && - pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); +static uint8_t pack_nb_harq_indication(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t *config) { + nfapi_nb_harq_indication_t *pNfapiMsg = (nfapi_nb_harq_indication_t *)msg; + return ( push16(pNfapiMsg->sfn_sf, ppWritePackedMsg, end) && + pack_tlv(NFAPI_NB_HARQ_INDICATION_BODY_TAG, &pNfapiMsg->nb_harq_indication_body, ppWritePackedMsg, end, &pack_nb_harq_indication_body_value) && + pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); } -static uint8_t pack_nrach_indication_rel13_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_nrach_indication_pdu_rel13_t* nrach_indication_fdd_rel13 = (nfapi_nrach_indication_pdu_rel13_t*)tlv; - - return ( push16(nrach_indication_fdd_rel13->rnti, ppWritePackedMsg, end) && - push8(nrach_indication_fdd_rel13->initial_sc, ppWritePackedMsg, end) && - push16(nrach_indication_fdd_rel13->timing_advance, ppWritePackedMsg, end) && - push8(nrach_indication_fdd_rel13->nrach_ce_level, ppWritePackedMsg, end)); +static uint8_t pack_nrach_indication_rel13_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_nrach_indication_pdu_rel13_t *nrach_indication_fdd_rel13 = (nfapi_nrach_indication_pdu_rel13_t *)tlv; + return ( push16(nrach_indication_fdd_rel13->rnti, ppWritePackedMsg, end) && + push8(nrach_indication_fdd_rel13->initial_sc, ppWritePackedMsg, end) && + push16(nrach_indication_fdd_rel13->timing_advance, ppWritePackedMsg, end) && + push8(nrach_indication_fdd_rel13->nrach_ce_level, ppWritePackedMsg, end)); } -static uint8_t pack_nrach_indication_body_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_nrach_indication_body_t* value = (nfapi_nrach_indication_body_t*)tlv; - - if( push8(value->number_of_initial_scs_detected, ppWritePackedMsg, end) == 0) - return 0; +static uint8_t pack_nrach_indication_body_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_nrach_indication_body_t *value = (nfapi_nrach_indication_body_t *)tlv; - uint16_t i = 0; - uint16_t total_number_of_initial_scs_detected = value->number_of_initial_scs_detected; - for(; i < total_number_of_initial_scs_detected; ++i) - { - nfapi_nrach_indication_pdu_t* pdu = &(value->nrach_pdu_list[i]); - - //uint8_t* instance_length_p = *ppWritePackedMsg; - //if(!push16(pdu->instance_length, ppWritePackedMsg, end)) - // return 0; + if( push8(value->number_of_initial_scs_detected, ppWritePackedMsg, end) == 0) + return 0; - if(!(pack_tlv(NFAPI_NRACH_INDICATION_REL13_TAG, &pdu->nrach_indication_rel13, ppWritePackedMsg, end, pack_nrach_indication_rel13_value))) - return 0; - - // calculate the instance length subtracting the size of the instance - // length feild - //uint16_t instance_length = *ppWritePackedMsg - instance_length_p - 2; - //push16(instance_length, &instance_length_p, end); - } + uint16_t i = 0; + uint16_t total_number_of_initial_scs_detected = value->number_of_initial_scs_detected; - return 1; + for(; i < total_number_of_initial_scs_detected; ++i) { + nfapi_nrach_indication_pdu_t *pdu = &(value->nrach_pdu_list[i]); + + //uint8_t* instance_length_p = *ppWritePackedMsg; + //if(!push16(pdu->instance_length, ppWritePackedMsg, end)) + // return 0; + + if(!(pack_tlv(NFAPI_NRACH_INDICATION_REL13_TAG, &pdu->nrach_indication_rel13, ppWritePackedMsg, end, pack_nrach_indication_rel13_value))) + return 0; + + // calculate the instance length subtracting the size of the instance + // length feild + //uint16_t instance_length = *ppWritePackedMsg - instance_length_p - 2; + //push16(instance_length, &instance_length_p, end); + } + + return 1; } -static uint8_t pack_nrach_indication(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) -{ - nfapi_nrach_indication_t *pNfapiMsg = (nfapi_nrach_indication_t*)msg; - - return ( push16(pNfapiMsg->sfn_sf, ppWritePackedMsg, end) && - pack_tlv(NFAPI_NRACH_INDICATION_BODY_TAG, &pNfapiMsg->nrach_indication_body, ppWritePackedMsg, end, &pack_nrach_indication_body_value) && - pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); +static uint8_t pack_nrach_indication(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t *config) { + nfapi_nrach_indication_t *pNfapiMsg = (nfapi_nrach_indication_t *)msg; + return ( push16(pNfapiMsg->sfn_sf, ppWritePackedMsg, end) && + pack_tlv(NFAPI_NRACH_INDICATION_BODY_TAG, &pNfapiMsg->nrach_indication_body, ppWritePackedMsg, end, &pack_nrach_indication_body_value) && + pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); } -static uint8_t pack_nr_dl_node_sync(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) -{ - nfapi_nr_dl_node_sync_t *pNfapiMsg = (nfapi_nr_dl_node_sync_t*)msg; - - return ( push32(pNfapiMsg->t1, ppWritePackedMsg, end) && - pushs32(pNfapiMsg->delta_sfn_slot, ppWritePackedMsg, end) && - pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); +static uint8_t pack_nr_dl_node_sync(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t *config) { + nfapi_nr_dl_node_sync_t *pNfapiMsg = (nfapi_nr_dl_node_sync_t *)msg; + return ( push32(pNfapiMsg->t1, ppWritePackedMsg, end) && + pushs32(pNfapiMsg->delta_sfn_slot, ppWritePackedMsg, end) && + pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); } -static uint8_t pack_dl_node_sync(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) -{ - nfapi_dl_node_sync_t *pNfapiMsg = (nfapi_dl_node_sync_t*)msg; - - return ( push32(pNfapiMsg->t1, ppWritePackedMsg, end) && - pushs32(pNfapiMsg->delta_sfn_sf, ppWritePackedMsg, end) && - pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); +static uint8_t pack_dl_node_sync(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t *config) { + nfapi_dl_node_sync_t *pNfapiMsg = (nfapi_dl_node_sync_t *)msg; + return ( push32(pNfapiMsg->t1, ppWritePackedMsg, end) && + pushs32(pNfapiMsg->delta_sfn_sf, ppWritePackedMsg, end) && + pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); } -static uint8_t pack_nr_ul_node_sync(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) -{ - nfapi_nr_ul_node_sync_t *pNfapiMsg = (nfapi_nr_ul_node_sync_t*)msg; - - return (push32(pNfapiMsg->t1, ppWritePackedMsg, end) && - push32(pNfapiMsg->t2, ppWritePackedMsg, end) && - push32(pNfapiMsg->t3, ppWritePackedMsg, end) && - pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); +static uint8_t pack_nr_ul_node_sync(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t *config) { + nfapi_nr_ul_node_sync_t *pNfapiMsg = (nfapi_nr_ul_node_sync_t *)msg; + return (push32(pNfapiMsg->t1, ppWritePackedMsg, end) && + push32(pNfapiMsg->t2, ppWritePackedMsg, end) && + push32(pNfapiMsg->t3, ppWritePackedMsg, end) && + pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); } -static uint8_t pack_ul_node_sync(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) -{ - nfapi_ul_node_sync_t *pNfapiMsg = (nfapi_ul_node_sync_t*)msg; - - return (push32(pNfapiMsg->t1, ppWritePackedMsg, end) && - push32(pNfapiMsg->t2, ppWritePackedMsg, end) && - push32(pNfapiMsg->t3, ppWritePackedMsg, end) && - pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); +static uint8_t pack_ul_node_sync(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t *config) { + nfapi_ul_node_sync_t *pNfapiMsg = (nfapi_ul_node_sync_t *)msg; + return (push32(pNfapiMsg->t1, ppWritePackedMsg, end) && + push32(pNfapiMsg->t2, ppWritePackedMsg, end) && + push32(pNfapiMsg->t3, ppWritePackedMsg, end) && + pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); } -static uint8_t pack_timing_info(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) -{ - nfapi_timing_info_t *pNfapiMsg = (nfapi_timing_info_t*)msg; - - return (push32(pNfapiMsg->last_sfn_sf, ppWritePackedMsg, end) && - push32(pNfapiMsg->time_since_last_timing_info, ppWritePackedMsg, end) && - push32(pNfapiMsg->dl_config_jitter, ppWritePackedMsg, end) && - push32(pNfapiMsg->tx_request_jitter, ppWritePackedMsg, end) && - push32(pNfapiMsg->ul_config_jitter, ppWritePackedMsg, end) && - push32(pNfapiMsg->hi_dci0_jitter, ppWritePackedMsg, end) && - pushs32(pNfapiMsg->dl_config_latest_delay, ppWritePackedMsg, end) && - pushs32(pNfapiMsg->tx_request_latest_delay, ppWritePackedMsg, end) && - pushs32(pNfapiMsg->ul_config_latest_delay, ppWritePackedMsg, end) && - pushs32(pNfapiMsg->hi_dci0_latest_delay, ppWritePackedMsg, end) && - pushs32(pNfapiMsg->dl_config_earliest_arrival, ppWritePackedMsg, end) && - pushs32(pNfapiMsg->tx_request_earliest_arrival, ppWritePackedMsg, end) && - pushs32(pNfapiMsg->ul_config_earliest_arrival, ppWritePackedMsg, end) && - pushs32(pNfapiMsg->hi_dci0_earliest_arrival, ppWritePackedMsg, end) && - pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); +static uint8_t pack_timing_info(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t *config) { + nfapi_timing_info_t *pNfapiMsg = (nfapi_timing_info_t *)msg; + return (push32(pNfapiMsg->last_sfn_sf, ppWritePackedMsg, end) && + push32(pNfapiMsg->time_since_last_timing_info, ppWritePackedMsg, end) && + push32(pNfapiMsg->dl_config_jitter, ppWritePackedMsg, end) && + push32(pNfapiMsg->tx_request_jitter, ppWritePackedMsg, end) && + push32(pNfapiMsg->ul_config_jitter, ppWritePackedMsg, end) && + push32(pNfapiMsg->hi_dci0_jitter, ppWritePackedMsg, end) && + pushs32(pNfapiMsg->dl_config_latest_delay, ppWritePackedMsg, end) && + pushs32(pNfapiMsg->tx_request_latest_delay, ppWritePackedMsg, end) && + pushs32(pNfapiMsg->ul_config_latest_delay, ppWritePackedMsg, end) && + pushs32(pNfapiMsg->hi_dci0_latest_delay, ppWritePackedMsg, end) && + pushs32(pNfapiMsg->dl_config_earliest_arrival, ppWritePackedMsg, end) && + pushs32(pNfapiMsg->tx_request_earliest_arrival, ppWritePackedMsg, end) && + pushs32(pNfapiMsg->ul_config_earliest_arrival, ppWritePackedMsg, end) && + pushs32(pNfapiMsg->hi_dci0_earliest_arrival, ppWritePackedMsg, end) && + pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); } -static uint8_t pack_nr_timing_info(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) -{ - nfapi_nr_timing_info_t *pNfapiMsg = (nfapi_nr_timing_info_t*)msg; - - return (push32(pNfapiMsg->last_sfn, ppWritePackedMsg, end) && - push32(pNfapiMsg->last_slot, ppWritePackedMsg, end) && - push32(pNfapiMsg->time_since_last_timing_info, ppWritePackedMsg, end) && - push32(pNfapiMsg->dl_tti_jitter, ppWritePackedMsg, end) && - push32(pNfapiMsg->tx_data_request_jitter, ppWritePackedMsg, end) && - push32(pNfapiMsg->ul_tti_jitter, ppWritePackedMsg, end) && - push32(pNfapiMsg->ul_dci_jitter, ppWritePackedMsg, end) && - pushs32(pNfapiMsg->dl_tti_latest_delay, ppWritePackedMsg, end) && - pushs32(pNfapiMsg->tx_data_request_latest_delay, ppWritePackedMsg, end) && - pushs32(pNfapiMsg->ul_tti_latest_delay, ppWritePackedMsg, end) && - pushs32(pNfapiMsg->ul_dci_latest_delay, ppWritePackedMsg, end) && - pushs32(pNfapiMsg->dl_tti_earliest_arrival, ppWritePackedMsg, end) && - pushs32(pNfapiMsg->tx_data_request_earliest_arrival, ppWritePackedMsg, end) && - pushs32(pNfapiMsg->ul_tti_earliest_arrival, ppWritePackedMsg, end) && - pushs32(pNfapiMsg->ul_dci_earliest_arrival, ppWritePackedMsg, end) && - pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); +static uint8_t pack_nr_timing_info(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t *config) { + nfapi_nr_timing_info_t *pNfapiMsg = (nfapi_nr_timing_info_t *)msg; + return (push32(pNfapiMsg->last_sfn, ppWritePackedMsg, end) && + push32(pNfapiMsg->last_slot, ppWritePackedMsg, end) && + push32(pNfapiMsg->time_since_last_timing_info, ppWritePackedMsg, end) && + push32(pNfapiMsg->dl_tti_jitter, ppWritePackedMsg, end) && + push32(pNfapiMsg->tx_data_request_jitter, ppWritePackedMsg, end) && + push32(pNfapiMsg->ul_tti_jitter, ppWritePackedMsg, end) && + push32(pNfapiMsg->ul_dci_jitter, ppWritePackedMsg, end) && + pushs32(pNfapiMsg->dl_tti_latest_delay, ppWritePackedMsg, end) && + pushs32(pNfapiMsg->tx_data_request_latest_delay, ppWritePackedMsg, end) && + pushs32(pNfapiMsg->ul_tti_latest_delay, ppWritePackedMsg, end) && + pushs32(pNfapiMsg->ul_dci_latest_delay, ppWritePackedMsg, end) && + pushs32(pNfapiMsg->dl_tti_earliest_arrival, ppWritePackedMsg, end) && + pushs32(pNfapiMsg->tx_data_request_earliest_arrival, ppWritePackedMsg, end) && + pushs32(pNfapiMsg->ul_tti_earliest_arrival, ppWritePackedMsg, end) && + pushs32(pNfapiMsg->ul_dci_earliest_arrival, ppWritePackedMsg, end) && + pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); } // Main pack function - public -int nfapi_nr_p7_message_pack(void *pMessageBuf, void *pPackedBuf, uint32_t packedBufLen, nfapi_p7_codec_config_t* config) -{ - nfapi_p7_message_header_t *pMessageHeader = pMessageBuf; - uint8_t *pWritePackedMessage = pPackedBuf; - uint8_t *pPackedLengthField = &pWritePackedMessage[4]; - uint8_t *end = pPackedBuf + packedBufLen; +int nfapi_nr_p7_message_pack(void *pMessageBuf, void *pPackedBuf, uint32_t packedBufLen, nfapi_p7_codec_config_t *config) { + nfapi_p7_message_header_t *pMessageHeader = pMessageBuf; + uint8_t *pWritePackedMessage = pPackedBuf; + uint8_t *pPackedLengthField = &pWritePackedMessage[4]; + uint8_t *end = pPackedBuf + packedBufLen; - if (pMessageBuf == NULL || pPackedBuf == NULL) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "P7 Pack supplied pointers are null\n"); - return -1; - } - /* - printf("\n P7 MESSAGE SENT: \n"); - for(int i=0; i< packedBufLen; i++){ - printf("%d", *(uint8_t *)(pMessageBuf + i)); - } - printf("\n"); - */ - // process the header - if(!(push16(pMessageHeader->phy_id, &pWritePackedMessage, end) && - push16(pMessageHeader->message_id, &pWritePackedMessage, end) && - push16(0/*pMessageHeader->message_length*/, &pWritePackedMessage, end) && - push16(pMessageHeader->m_segment_sequence, &pWritePackedMessage, end) && - push32(0/*pMessageHeader->checksum*/, &pWritePackedMessage, end) && - push32(pMessageHeader->transmit_timestamp, &pWritePackedMessage, end))) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "P7 Pack header failed\n"); - return -1; - } + if (pMessageBuf == NULL || pPackedBuf == NULL) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "P7 Pack supplied pointers are null\n"); + return -1; + } - if (pMessageHeader->message_id != NFAPI_TIMING_INFO) - { - //NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() message_id:0x%04x phy_id:%u m_segment_sequence:%u timestamp:%u\n", __FUNCTION__, pMessageHeader->message_id, pMessageHeader->phy_id, pMessageHeader->m_segment_sequence, pMessageHeader->transmit_timestamp); + /* + printf("\n P7 MESSAGE SENT: \n"); + for(int i=0; i< packedBufLen; i++){ + printf("%d", *(uint8_t *)(pMessageBuf + i)); + } + printf("\n"); + */ + // process the header + if(!(push16(pMessageHeader->phy_id, &pWritePackedMessage, end) && + push16(pMessageHeader->message_id, &pWritePackedMessage, end) && + push16(0/*pMessageHeader->message_length*/, &pWritePackedMessage, end) && + push16(pMessageHeader->m_segment_sequence, &pWritePackedMessage, end) && + push32(0/*pMessageHeader->checksum*/, &pWritePackedMessage, end) && + push32(pMessageHeader->transmit_timestamp, &pWritePackedMessage, end))) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "P7 Pack header failed\n"); + return -1; + } + + if (pMessageHeader->message_id != NFAPI_TIMING_INFO) { + //NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() message_id:0x%04x phy_id:%u m_segment_sequence:%u timestamp:%u\n", __FUNCTION__, pMessageHeader->message_id, pMessageHeader->phy_id, pMessageHeader->m_segment_sequence, pMessageHeader->transmit_timestamp); + } + + // look for the specific message + uint8_t result = 0; + + switch (pMessageHeader->message_id) { + case NFAPI_NR_PHY_MSG_TYPE_DL_TTI_REQUEST: + result = pack_dl_tti_request(pMessageHeader, &pWritePackedMessage, end, config); + break; + + case NFAPI_NR_PHY_MSG_TYPE_UL_TTI_REQUEST: + result = pack_ul_tti_request(pMessageHeader, &pWritePackedMessage, end, config); + break; + + case NFAPI_NR_PHY_MSG_TYPE_TX_DATA_REQUEST: + result = pack_tx_data_request(pMessageHeader, &pWritePackedMessage, end, config); + break; + + case NFAPI_NR_PHY_MSG_TYPE_UL_DCI_REQUEST: + result = pack_ul_dci_request(pMessageHeader, &pWritePackedMessage, end, config); + break; + + case NFAPI_UE_RELEASE_REQUEST: + result =pack_ue_release_request(pMessageHeader, &pWritePackedMessage, end, config); + break; + + case NFAPI_UE_RELEASE_RESPONSE: + result =pack_ue_release_response(pMessageHeader, &pWritePackedMessage, end, config); + break; + + case NFAPI_HARQ_INDICATION: + result = pack_harq_indication(pMessageHeader, &pWritePackedMessage, end, config); + break; + + case NFAPI_CRC_INDICATION: + result = pack_crc_indication(pMessageHeader, &pWritePackedMessage, end, config); + break; + + case NFAPI_RX_ULSCH_INDICATION: + //printf("RX ULSCH\n"); + result = pack_rx_ulsch_indication(pMessageHeader, &pWritePackedMessage, end, config); + break; + + case NFAPI_RACH_INDICATION: + result = pack_rach_indication(pMessageHeader, &pWritePackedMessage, end, config); + break; + + case NFAPI_SRS_INDICATION: + result = pack_srs_indication(pMessageHeader, &pWritePackedMessage, end, config); + break; + + case NFAPI_RX_SR_INDICATION: + result = pack_sr_indication(pMessageHeader, &pWritePackedMessage, end, config); + break; + + case NFAPI_RX_CQI_INDICATION: + result = pack_cqi_indication(pMessageHeader, &pWritePackedMessage, end, config); + break; + + case NFAPI_LBT_DL_CONFIG_REQUEST: + result = pack_lbt_dl_config_request(pMessageHeader, &pWritePackedMessage, end, config); + break; + + case NFAPI_LBT_DL_INDICATION: + result = pack_lbt_dl_indication(pMessageHeader, &pWritePackedMessage, end, config); + break; + + case NFAPI_NB_HARQ_INDICATION: + result = pack_nb_harq_indication(pMessageHeader, &pWritePackedMessage, end, config); + break; + + case NFAPI_NRACH_INDICATION: + result = pack_nrach_indication(pMessageHeader, &pWritePackedMessage, end, config); + break; + + case NFAPI_NR_PHY_MSG_TYPE_DL_NODE_SYNC: + result = pack_nr_dl_node_sync(pMessageHeader, &pWritePackedMessage, end, config); + break; + + case NFAPI_NR_PHY_MSG_TYPE_UL_NODE_SYNC: + result = pack_nr_ul_node_sync(pMessageHeader, &pWritePackedMessage, end, config); + break; + + case NFAPI_TIMING_INFO: + result = pack_nr_timing_info(pMessageHeader, &pWritePackedMessage, end, config); + break; + + default: { + if(pMessageHeader->message_id >= NFAPI_VENDOR_EXT_MSG_MIN && + pMessageHeader->message_id <= NFAPI_VENDOR_EXT_MSG_MAX) { + if(config && config->pack_p7_vendor_extension) { + result = (config->pack_p7_vendor_extension)(pMessageHeader, &pWritePackedMessage, end, config); + } else { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s VE NFAPI message ID %d. No ve ecoder provided\n", __FUNCTION__, pMessageHeader->message_id); } - // look for the specific message - uint8_t result = 0; - switch (pMessageHeader->message_id) - { - case NFAPI_NR_PHY_MSG_TYPE_DL_TTI_REQUEST: - result = pack_dl_tti_request(pMessageHeader, &pWritePackedMessage, end, config); - break; + } else { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s NFAPI Unknown message ID %d\n", __FUNCTION__, pMessageHeader->message_id); + } + } + break; + } - case NFAPI_NR_PHY_MSG_TYPE_UL_TTI_REQUEST: - result = pack_ul_tti_request(pMessageHeader, &pWritePackedMessage, end, config); - break; - case NFAPI_NR_PHY_MSG_TYPE_TX_DATA_REQUEST: - result = pack_tx_data_request(pMessageHeader, &pWritePackedMessage, end, config); - break; - case NFAPI_NR_PHY_MSG_TYPE_UL_DCI_REQUEST: - result = pack_ul_dci_request(pMessageHeader, &pWritePackedMessage, end, config); - break; - - case NFAPI_UE_RELEASE_REQUEST: - result =pack_ue_release_request(pMessageHeader, &pWritePackedMessage, end, config); - break; + if(result == 0) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "P7 Pack failed to pack message\n"); + return -1; + } - case NFAPI_UE_RELEASE_RESPONSE: - result =pack_ue_release_response(pMessageHeader, &pWritePackedMessage, end, config); - break; + // check for a valid message length + uintptr_t msgHead = (uintptr_t)pPackedBuf; + uintptr_t msgEnd = (uintptr_t)pWritePackedMessage; + uint32_t packedMsgLen = msgEnd - msgHead; + uint16_t packedMsgLen16; - case NFAPI_HARQ_INDICATION: - result = pack_harq_indication(pMessageHeader, &pWritePackedMessage, end, config); - break; + if (packedMsgLen > 0xFFFF || packedMsgLen > packedBufLen) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "Packed message length error %d, buffer supplied %d\n", packedMsgLen, packedBufLen); + return -1; + } else { + packedMsgLen16 = (uint16_t)packedMsgLen; + } - case NFAPI_CRC_INDICATION: - result = pack_crc_indication(pMessageHeader, &pWritePackedMessage, end, config); - break; + // Update the message length in the header + pMessageHeader->message_length = packedMsgLen16; - case NFAPI_RX_ULSCH_INDICATION: - //printf("RX ULSCH\n"); - result = pack_rx_ulsch_indication(pMessageHeader, &pWritePackedMessage, end, config); - break; + if(!push16(packedMsgLen16, &pPackedLengthField, end)) + return -1; - case NFAPI_RACH_INDICATION: - result = pack_rach_indication(pMessageHeader, &pWritePackedMessage, end, config); - break; + if(1) { + //quick test + if(pMessageHeader->message_length != packedMsgLen) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "nfapi packedMsgLen(%d) != message_length(%d) id %d\n", packedMsgLen, pMessageHeader->message_length, pMessageHeader->message_id); + } + } - case NFAPI_SRS_INDICATION: - result = pack_srs_indication(pMessageHeader, &pWritePackedMessage, end, config); - break; - - case NFAPI_RX_SR_INDICATION: - result = pack_sr_indication(pMessageHeader, &pWritePackedMessage, end, config); - break; - - case NFAPI_RX_CQI_INDICATION: - result = pack_cqi_indication(pMessageHeader, &pWritePackedMessage, end, config); - break; - - case NFAPI_LBT_DL_CONFIG_REQUEST: - result = pack_lbt_dl_config_request(pMessageHeader, &pWritePackedMessage, end, config); - break; - - case NFAPI_LBT_DL_INDICATION: - result = pack_lbt_dl_indication(pMessageHeader, &pWritePackedMessage, end, config); - break; - - case NFAPI_NB_HARQ_INDICATION: - result = pack_nb_harq_indication(pMessageHeader, &pWritePackedMessage, end, config); - break; - - case NFAPI_NRACH_INDICATION: - result = pack_nrach_indication(pMessageHeader, &pWritePackedMessage, end, config); - break; - - case NFAPI_NR_PHY_MSG_TYPE_DL_NODE_SYNC: - result = pack_nr_dl_node_sync(pMessageHeader, &pWritePackedMessage, end, config); - break; - - case NFAPI_NR_PHY_MSG_TYPE_UL_NODE_SYNC: - result = pack_nr_ul_node_sync(pMessageHeader, &pWritePackedMessage, end, config); - break; - - case NFAPI_TIMING_INFO: - result = pack_nr_timing_info(pMessageHeader, &pWritePackedMessage, end, config); - break; - - default: - { - if(pMessageHeader->message_id >= NFAPI_VENDOR_EXT_MSG_MIN && - pMessageHeader->message_id <= NFAPI_VENDOR_EXT_MSG_MAX) - { - if(config && config->pack_p7_vendor_extension) - { - result = (config->pack_p7_vendor_extension)(pMessageHeader, &pWritePackedMessage, end, config); - } - else - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s VE NFAPI message ID %d. No ve ecoder provided\n", __FUNCTION__, pMessageHeader->message_id); - } - } - else - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s NFAPI Unknown message ID %d\n", __FUNCTION__, pMessageHeader->message_id); - } - } - break; - } - - if(result == 0) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "P7 Pack failed to pack message\n"); - return -1; - } - - // check for a valid message length - uintptr_t msgHead = (uintptr_t)pPackedBuf; - uintptr_t msgEnd = (uintptr_t)pWritePackedMessage; - uint32_t packedMsgLen = msgEnd - msgHead; - uint16_t packedMsgLen16; - if (packedMsgLen > 0xFFFF || packedMsgLen > packedBufLen) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "Packed message length error %d, buffer supplied %d\n", packedMsgLen, packedBufLen); - return -1; - } - else - { - packedMsgLen16 = (uint16_t)packedMsgLen; - } - - // Update the message length in the header - pMessageHeader->message_length = packedMsgLen16; - - if(!push16(packedMsgLen16, &pPackedLengthField, end)) - return -1; - - if(1) - { - //quick test - if(pMessageHeader->message_length != packedMsgLen) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "nfapi packedMsgLen(%d) != message_length(%d) id %d\n", packedMsgLen, pMessageHeader->message_length, pMessageHeader->message_id); - } - } - - return (packedMsgLen); + return (packedMsgLen); } -int nfapi_p7_message_pack(void *pMessageBuf, void *pPackedBuf, uint32_t packedBufLen, nfapi_p7_codec_config_t* config) -{ - nfapi_p7_message_header_t *pMessageHeader = pMessageBuf; - uint8_t *pWritePackedMessage = pPackedBuf; - uint8_t *pPackedLengthField = &pWritePackedMessage[4]; - uint8_t *end = pPackedBuf + packedBufLen; +int nfapi_p7_message_pack(void *pMessageBuf, void *pPackedBuf, uint32_t packedBufLen, nfapi_p7_codec_config_t *config) { + nfapi_p7_message_header_t *pMessageHeader = pMessageBuf; + uint8_t *pWritePackedMessage = pPackedBuf; + uint8_t *pPackedLengthField = &pWritePackedMessage[4]; + uint8_t *end = pPackedBuf + packedBufLen; - if (pMessageBuf == NULL || pPackedBuf == NULL) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "P7 Pack supplied pointers are null\n"); - return -1; - } - /* - printf("\n P7 MESSAGE SENT: \n"); - for(int i=0; i< packedBufLen; i++){ - printf("%d", *(uint8_t *)(pMessageBuf + i)); - } - printf("\n"); - */ - // process the header - if(!(push16(pMessageHeader->phy_id, &pWritePackedMessage, end) && - push16(pMessageHeader->message_id, &pWritePackedMessage, end) && - push16(0/*pMessageHeader->message_length*/, &pWritePackedMessage, end) && - push16(pMessageHeader->m_segment_sequence, &pWritePackedMessage, end) && - push32(0/*pMessageHeader->checksum*/, &pWritePackedMessage, end) && - push32(pMessageHeader->transmit_timestamp, &pWritePackedMessage, end))) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "P7 Pack header failed\n"); - return -1; - } + if (pMessageBuf == NULL || pPackedBuf == NULL) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "P7 Pack supplied pointers are null\n"); + return -1; + } - if (pMessageHeader->message_id != NFAPI_TIMING_INFO) - { - //NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() message_id:0x%04x phy_id:%u m_segment_sequence:%u timestamp:%u\n", __FUNCTION__, pMessageHeader->message_id, pMessageHeader->phy_id, pMessageHeader->m_segment_sequence, pMessageHeader->transmit_timestamp); + /* + printf("\n P7 MESSAGE SENT: \n"); + for(int i=0; i< packedBufLen; i++){ + printf("%d", *(uint8_t *)(pMessageBuf + i)); + } + printf("\n"); + */ + // process the header + if(!(push16(pMessageHeader->phy_id, &pWritePackedMessage, end) && + push16(pMessageHeader->message_id, &pWritePackedMessage, end) && + push16(0/*pMessageHeader->message_length*/, &pWritePackedMessage, end) && + push16(pMessageHeader->m_segment_sequence, &pWritePackedMessage, end) && + push32(0/*pMessageHeader->checksum*/, &pWritePackedMessage, end) && + push32(pMessageHeader->transmit_timestamp, &pWritePackedMessage, end))) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "P7 Pack header failed\n"); + return -1; + } + + if (pMessageHeader->message_id != NFAPI_TIMING_INFO) { + //NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() message_id:0x%04x phy_id:%u m_segment_sequence:%u timestamp:%u\n", __FUNCTION__, pMessageHeader->message_id, pMessageHeader->phy_id, pMessageHeader->m_segment_sequence, pMessageHeader->transmit_timestamp); + } + + // look for the specific message + uint8_t result = 0; + + switch (pMessageHeader->message_id) { + case NFAPI_DL_CONFIG_REQUEST: + //NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() NFAPI_DL_CONFIG_REQUEST\n", __FUNCTION__); + result = pack_dl_config_request(pMessageHeader, &pWritePackedMessage, end, config); + break; + + case NFAPI_UL_CONFIG_REQUEST: + result = pack_ul_config_request(pMessageHeader, &pWritePackedMessage, end, config); + break; + + case NFAPI_TX_REQUEST: + //NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() NFAPI_TX_REQUEST\n", __FUNCTION__); + result = pack_tx_request(pMessageHeader, &pWritePackedMessage, end, config); + break; + + case NFAPI_HI_DCI0_REQUEST: + result = pack_hi_dci0_request(pMessageHeader, &pWritePackedMessage, end, config); + break; + + case NFAPI_UE_RELEASE_REQUEST: + result =pack_ue_release_request(pMessageHeader, &pWritePackedMessage, end, config); + break; + + case NFAPI_UE_RELEASE_RESPONSE: + result =pack_ue_release_response(pMessageHeader, &pWritePackedMessage, end, config); + break; + + case NFAPI_HARQ_INDICATION: + result = pack_harq_indication(pMessageHeader, &pWritePackedMessage, end, config); + break; + + case NFAPI_CRC_INDICATION: + result = pack_crc_indication(pMessageHeader, &pWritePackedMessage, end, config); + break; + + case NFAPI_RX_ULSCH_INDICATION: + //printf("RX ULSCH\n"); + result = pack_rx_ulsch_indication(pMessageHeader, &pWritePackedMessage, end, config); + break; + + case NFAPI_RACH_INDICATION: + result = pack_rach_indication(pMessageHeader, &pWritePackedMessage, end, config); + break; + + case NFAPI_SRS_INDICATION: + result = pack_srs_indication(pMessageHeader, &pWritePackedMessage, end, config); + break; + + case NFAPI_RX_SR_INDICATION: + result = pack_sr_indication(pMessageHeader, &pWritePackedMessage, end, config); + break; + + case NFAPI_RX_CQI_INDICATION: + result = pack_cqi_indication(pMessageHeader, &pWritePackedMessage, end, config); + break; + + case NFAPI_LBT_DL_CONFIG_REQUEST: + result = pack_lbt_dl_config_request(pMessageHeader, &pWritePackedMessage, end, config); + break; + + case NFAPI_LBT_DL_INDICATION: + result = pack_lbt_dl_indication(pMessageHeader, &pWritePackedMessage, end, config); + break; + + case NFAPI_NB_HARQ_INDICATION: + result = pack_nb_harq_indication(pMessageHeader, &pWritePackedMessage, end, config); + break; + + case NFAPI_NRACH_INDICATION: + result = pack_nrach_indication(pMessageHeader, &pWritePackedMessage, end, config); + break; + + case NFAPI_DL_NODE_SYNC: + result = pack_dl_node_sync(pMessageHeader, &pWritePackedMessage, end, config); + break; + + case NFAPI_UL_NODE_SYNC: + result = pack_ul_node_sync(pMessageHeader, &pWritePackedMessage, end, config); + break; + + case NFAPI_TIMING_INFO: + result = pack_timing_info(pMessageHeader, &pWritePackedMessage, end, config); + break; + + default: { + if(pMessageHeader->message_id >= NFAPI_VENDOR_EXT_MSG_MIN && + pMessageHeader->message_id <= NFAPI_VENDOR_EXT_MSG_MAX) { + if(config && config->pack_p7_vendor_extension) { + result = (config->pack_p7_vendor_extension)(pMessageHeader, &pWritePackedMessage, end, config); + } else { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s VE NFAPI message ID %d. No ve ecoder provided\n", __FUNCTION__, pMessageHeader->message_id); } - // look for the specific message - uint8_t result = 0; - switch (pMessageHeader->message_id) - { - case NFAPI_DL_CONFIG_REQUEST: - //NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() NFAPI_DL_CONFIG_REQUEST\n", __FUNCTION__); - result = pack_dl_config_request(pMessageHeader, &pWritePackedMessage, end, config); - break; + } else { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s NFAPI Unknown message ID %d\n", __FUNCTION__, pMessageHeader->message_id); + } + } + break; + } - case NFAPI_UL_CONFIG_REQUEST: - result = pack_ul_config_request(pMessageHeader, &pWritePackedMessage, end, config); - break; - case NFAPI_TX_REQUEST: - //NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() NFAPI_TX_REQUEST\n", __FUNCTION__); - result = pack_tx_request(pMessageHeader, &pWritePackedMessage, end, config); - break; - case NFAPI_HI_DCI0_REQUEST: - result = pack_hi_dci0_request(pMessageHeader, &pWritePackedMessage, end, config); - break; - - case NFAPI_UE_RELEASE_REQUEST: - result =pack_ue_release_request(pMessageHeader, &pWritePackedMessage, end, config); - break; + if(result == 0) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "P7 Pack failed to pack message\n"); + return -1; + } - case NFAPI_UE_RELEASE_RESPONSE: - result =pack_ue_release_response(pMessageHeader, &pWritePackedMessage, end, config); - break; + // check for a valid message length + uintptr_t msgHead = (uintptr_t)pPackedBuf; + uintptr_t msgEnd = (uintptr_t)pWritePackedMessage; + uint32_t packedMsgLen = msgEnd - msgHead; + uint16_t packedMsgLen16; - case NFAPI_HARQ_INDICATION: - result = pack_harq_indication(pMessageHeader, &pWritePackedMessage, end, config); - break; + if (packedMsgLen > 0xFFFF || packedMsgLen > packedBufLen) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "Packed message length error %d, buffer supplied %d\n", packedMsgLen, packedBufLen); + return -1; + } else { + packedMsgLen16 = (uint16_t)packedMsgLen; + } - case NFAPI_CRC_INDICATION: - result = pack_crc_indication(pMessageHeader, &pWritePackedMessage, end, config); - break; + // Update the message length in the header + pMessageHeader->message_length = packedMsgLen16; - case NFAPI_RX_ULSCH_INDICATION: - //printf("RX ULSCH\n"); - result = pack_rx_ulsch_indication(pMessageHeader, &pWritePackedMessage, end, config); - break; + if(!push16(packedMsgLen16, &pPackedLengthField, end)) + return -1; - case NFAPI_RACH_INDICATION: - result = pack_rach_indication(pMessageHeader, &pWritePackedMessage, end, config); - break; + if(1) { + //quick test + if(pMessageHeader->message_length != packedMsgLen) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "nfapi packedMsgLen(%d) != message_length(%d) id %d\n", packedMsgLen, pMessageHeader->message_length, pMessageHeader->message_id); + } + } - case NFAPI_SRS_INDICATION: - result = pack_srs_indication(pMessageHeader, &pWritePackedMessage, end, config); - break; - - case NFAPI_RX_SR_INDICATION: - result = pack_sr_indication(pMessageHeader, &pWritePackedMessage, end, config); - break; - - case NFAPI_RX_CQI_INDICATION: - result = pack_cqi_indication(pMessageHeader, &pWritePackedMessage, end, config); - break; - - case NFAPI_LBT_DL_CONFIG_REQUEST: - result = pack_lbt_dl_config_request(pMessageHeader, &pWritePackedMessage, end, config); - break; - - case NFAPI_LBT_DL_INDICATION: - result = pack_lbt_dl_indication(pMessageHeader, &pWritePackedMessage, end, config); - break; - - case NFAPI_NB_HARQ_INDICATION: - result = pack_nb_harq_indication(pMessageHeader, &pWritePackedMessage, end, config); - break; - - case NFAPI_NRACH_INDICATION: - result = pack_nrach_indication(pMessageHeader, &pWritePackedMessage, end, config); - break; - - case NFAPI_DL_NODE_SYNC: - result = pack_dl_node_sync(pMessageHeader, &pWritePackedMessage, end, config); - break; - - case NFAPI_UL_NODE_SYNC: - result = pack_ul_node_sync(pMessageHeader, &pWritePackedMessage, end, config); - break; - - case NFAPI_TIMING_INFO: - result = pack_timing_info(pMessageHeader, &pWritePackedMessage, end, config); - break; - - default: - { - if(pMessageHeader->message_id >= NFAPI_VENDOR_EXT_MSG_MIN && - pMessageHeader->message_id <= NFAPI_VENDOR_EXT_MSG_MAX) - { - if(config && config->pack_p7_vendor_extension) - { - result = (config->pack_p7_vendor_extension)(pMessageHeader, &pWritePackedMessage, end, config); - } - else - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s VE NFAPI message ID %d. No ve ecoder provided\n", __FUNCTION__, pMessageHeader->message_id); - } - } - else - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s NFAPI Unknown message ID %d\n", __FUNCTION__, pMessageHeader->message_id); - } - } - break; - } - - if(result == 0) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "P7 Pack failed to pack message\n"); - return -1; - } - - // check for a valid message length - uintptr_t msgHead = (uintptr_t)pPackedBuf; - uintptr_t msgEnd = (uintptr_t)pWritePackedMessage; - uint32_t packedMsgLen = msgEnd - msgHead; - uint16_t packedMsgLen16; - if (packedMsgLen > 0xFFFF || packedMsgLen > packedBufLen) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "Packed message length error %d, buffer supplied %d\n", packedMsgLen, packedBufLen); - return -1; - } - else - { - packedMsgLen16 = (uint16_t)packedMsgLen; - } - - // Update the message length in the header - pMessageHeader->message_length = packedMsgLen16; - - if(!push16(packedMsgLen16, &pPackedLengthField, end)) - return -1; - - if(1) - { - //quick test - if(pMessageHeader->message_length != packedMsgLen) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "nfapi packedMsgLen(%d) != message_length(%d) id %d\n", packedMsgLen, pMessageHeader->message_length, pMessageHeader->message_id); - } - } - - return (packedMsgLen); + return (packedMsgLen); } // Unpack routines // NR: -static uint8_t unpack_dl_tti_csi_rs_pdu_rel15_value(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_nr_dl_tti_csi_rs_pdu_rel15_t* value = (nfapi_nr_dl_tti_csi_rs_pdu_rel15_t*)tlv; - - return( - pull16(ppReadPackedMsg, &value->bwp_size, end) && - pull16(ppReadPackedMsg, &value->bwp_start, end) && - - pull8(ppReadPackedMsg, &value->subcarrier_spacing, end) && - pull8(ppReadPackedMsg, &value->cyclic_prefix, end) && - - pull16(ppReadPackedMsg, &value->start_rb, end) && - pull16(ppReadPackedMsg, &value->nr_of_rbs, end) && - - pull8(ppReadPackedMsg, &value->csi_type, end) && - pull8(ppReadPackedMsg, &value->row, end) && - - pull16(ppReadPackedMsg, &value->freq_domain, end) && - pull8(ppReadPackedMsg, &value->symb_l0, end) && - - pull8(ppReadPackedMsg, &value->symb_l1, end) && - pull8(ppReadPackedMsg, &value->cdm_type, end) && - - pull8(ppReadPackedMsg, &value->freq_density, end) && - pull16(ppReadPackedMsg, &value->scramb_id, end) && - - pull8(ppReadPackedMsg, &value->power_control_offset, end) && - pull8(ppReadPackedMsg, &value->power_control_offset_ss, end) - ); - +static uint8_t unpack_dl_tti_csi_rs_pdu_rel15_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_nr_dl_tti_csi_rs_pdu_rel15_t *value = (nfapi_nr_dl_tti_csi_rs_pdu_rel15_t *)tlv; + return( + pull16(ppReadPackedMsg, &value->bwp_size, end) && + pull16(ppReadPackedMsg, &value->bwp_start, end) && + pull8(ppReadPackedMsg, &value->subcarrier_spacing, end) && + pull8(ppReadPackedMsg, &value->cyclic_prefix, end) && + pull16(ppReadPackedMsg, &value->start_rb, end) && + pull16(ppReadPackedMsg, &value->nr_of_rbs, end) && + pull8(ppReadPackedMsg, &value->csi_type, end) && + pull8(ppReadPackedMsg, &value->row, end) && + pull16(ppReadPackedMsg, &value->freq_domain, end) && + pull8(ppReadPackedMsg, &value->symb_l0, end) && + pull8(ppReadPackedMsg, &value->symb_l1, end) && + pull8(ppReadPackedMsg, &value->cdm_type, end) && + pull8(ppReadPackedMsg, &value->freq_density, end) && + pull16(ppReadPackedMsg, &value->scramb_id, end) && + pull8(ppReadPackedMsg, &value->power_control_offset, end) && + pull8(ppReadPackedMsg, &value->power_control_offset_ss, end) + ); } -static uint8_t unpack_dl_tti_pdcch_pdu_rel15_value(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_nr_dl_tti_pdcch_pdu_rel15_t* value = (nfapi_nr_dl_tti_pdcch_pdu_rel15_t*)tlv; - - for(uint8_t i = 0; i < MAX_DCI_CORESET; ++i) - { - if(!pull16(ppReadPackedMsg, &value->dci_pdu[i].RNTI, end) && - pull16(ppReadPackedMsg, &value->dci_pdu[i].ScramblingId, end) && +static uint8_t unpack_dl_tti_pdcch_pdu_rel15_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_nr_dl_tti_pdcch_pdu_rel15_t *value = (nfapi_nr_dl_tti_pdcch_pdu_rel15_t *)tlv; - pull16(ppReadPackedMsg, &value->dci_pdu[i].ScramblingRNTI, end) && - pull8(ppReadPackedMsg, &value->dci_pdu[i].CceIndex, end) && - pull8(ppReadPackedMsg, &value->dci_pdu[i].AggregationLevel, end) && - pull8(ppReadPackedMsg, &value->dci_pdu[i].beta_PDCCH_1_0, end) && + for(uint8_t i = 0; i < MAX_DCI_CORESET; ++i) { + if(!pull16(ppReadPackedMsg, &value->dci_pdu[i].RNTI, end) && + pull16(ppReadPackedMsg, &value->dci_pdu[i].ScramblingId, end) && + pull16(ppReadPackedMsg, &value->dci_pdu[i].ScramblingRNTI, end) && + pull8(ppReadPackedMsg, &value->dci_pdu[i].CceIndex, end) && + pull8(ppReadPackedMsg, &value->dci_pdu[i].AggregationLevel, end) && + pull8(ppReadPackedMsg, &value->dci_pdu[i].beta_PDCCH_1_0, end) && + pull8(ppReadPackedMsg, &value->dci_pdu[i].powerControlOffsetSS, end) && + pull16(ppReadPackedMsg, &value->dci_pdu[i].PayloadSizeBits, end) && + pullarray8(ppReadPackedMsg, value->dci_pdu[i].Payload, DCI_PAYLOAD_BYTE_LEN, value->dci_pdu[i].PayloadSizeBits, end)); - pull8(ppReadPackedMsg, &value->dci_pdu[i].powerControlOffsetSS, end) && - pull16(ppReadPackedMsg, &value->dci_pdu[i].PayloadSizeBits, end) && - - pullarray8(ppReadPackedMsg, value->dci_pdu[i].Payload, DCI_PAYLOAD_BYTE_LEN, value->dci_pdu[i].PayloadSizeBits, end)); - - return 0; - } - - // TODO: resolve the packaging of array (currently sending a single element) - return( - pull16(ppReadPackedMsg, &value->BWPSize, end) && - pull16(ppReadPackedMsg, &value->BWPStart, end) && - pull8(ppReadPackedMsg, &value->SubcarrierSpacing, end) && - pull8(ppReadPackedMsg, &value->CyclicPrefix, end) && - - pull8(ppReadPackedMsg, &value->StartSymbolIndex, end) && - pull8(ppReadPackedMsg, &value->DurationSymbols, end) && - pullarray8(ppReadPackedMsg, value->FreqDomainResource, 6, 6, end) && - pull8(ppReadPackedMsg, &value->CceRegMappingType, end) && - - pull8(ppReadPackedMsg, &value->RegBundleSize, end) && - pull8(ppReadPackedMsg, &value->InterleaverSize, end) && - pull8(ppReadPackedMsg, &value->CoreSetType, end) && - pull16(ppReadPackedMsg, &value->ShiftIndex, end) && - - pull8(ppReadPackedMsg, &value->precoderGranularity, end) && - pull16(ppReadPackedMsg, &value->numDlDci, end)); + return 0; + } + // TODO: resolve the packaging of array (currently sending a single element) + return( + pull16(ppReadPackedMsg, &value->BWPSize, end) && + pull16(ppReadPackedMsg, &value->BWPStart, end) && + pull8(ppReadPackedMsg, &value->SubcarrierSpacing, end) && + pull8(ppReadPackedMsg, &value->CyclicPrefix, end) && + pull8(ppReadPackedMsg, &value->StartSymbolIndex, end) && + pull8(ppReadPackedMsg, &value->DurationSymbols, end) && + pullarray8(ppReadPackedMsg, value->FreqDomainResource, 6, 6, end) && + pull8(ppReadPackedMsg, &value->CceRegMappingType, end) && + pull8(ppReadPackedMsg, &value->RegBundleSize, end) && + pull8(ppReadPackedMsg, &value->InterleaverSize, end) && + pull8(ppReadPackedMsg, &value->CoreSetType, end) && + pull16(ppReadPackedMsg, &value->ShiftIndex, end) && + pull8(ppReadPackedMsg, &value->precoderGranularity, end) && + pull16(ppReadPackedMsg, &value->numDlDci, end)); } -static uint8_t unpack_dl_tti_pdsch_pdu_rel15_value(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_nr_dl_tti_pdsch_pdu_rel15_t* value = (nfapi_nr_dl_tti_pdsch_pdu_rel15_t*)tlv; - - // TODO: resolve the packaging of array (currently sending a single element) - return( - pull16(ppReadPackedMsg, &value->pduBitmap, end) && - pull16(ppReadPackedMsg, &value->rnti, end) && - pull16(ppReadPackedMsg, &value->pduIndex, end) && - pull16(ppReadPackedMsg, &value->BWPSize, end) && - - pull16(ppReadPackedMsg, &value->BWPStart, end) && - pull8(ppReadPackedMsg, &value->SubcarrierSpacing, end) && - pull8(ppReadPackedMsg, &value->CyclicPrefix, end) && - pull8(ppReadPackedMsg, &value->NrOfCodewords, end) && - - pullarray16(ppReadPackedMsg, value->targetCodeRate, 2, 1, end) && - pullarray8(ppReadPackedMsg, value->qamModOrder, 2, 1, end) && - pullarray8(ppReadPackedMsg, value->mcsIndex, 2, 1, end) && - pullarray8(ppReadPackedMsg, value->mcsTable, 2, 1, end) && - - pullarray8(ppReadPackedMsg, value->rvIndex, 2, 1, end) && - pullarray32(ppReadPackedMsg, value->TBSize, 2, 1, end) && - pull16(ppReadPackedMsg, &value->dataScramblingId, end) && - pull8(ppReadPackedMsg, &value->nrOfLayers, end) && - - pull8(ppReadPackedMsg, &value->transmissionScheme, end) && - pull8(ppReadPackedMsg, &value->refPoint, end) && - pull16(ppReadPackedMsg, &value->dlDmrsSymbPos, end) && - pull8(ppReadPackedMsg, &value->dmrsConfigType, end) && - - pull16(ppReadPackedMsg, &value->dlDmrsScramblingId, end) && - pull8(ppReadPackedMsg, &value->SCID, end) && - pull8(ppReadPackedMsg, &value->numDmrsCdmGrpsNoData, end) && - pull16(ppReadPackedMsg, &value->dmrsPorts, end) && - - pull8(ppReadPackedMsg, &value->resourceAlloc, end) && - pull16(ppReadPackedMsg, &value->rbStart, end) && - pull16(ppReadPackedMsg, &value->rbSize, end) && - - pull8(ppReadPackedMsg, &value->VRBtoPRBMapping, end) && - pull8(ppReadPackedMsg, &value->StartSymbolIndex, end) && - pull8(ppReadPackedMsg, &value->NrOfSymbols, end) && - pull8(ppReadPackedMsg, &value->PTRSPortIndex, end) && - - pull8(ppReadPackedMsg, &value->PTRSTimeDensity, end) && - pull8(ppReadPackedMsg, &value->PTRSFreqDensity, end) && - pull8(ppReadPackedMsg, &value->PTRSReOffset, end) - ); - +static uint8_t unpack_dl_tti_pdsch_pdu_rel15_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_nr_dl_tti_pdsch_pdu_rel15_t *value = (nfapi_nr_dl_tti_pdsch_pdu_rel15_t *)tlv; + // TODO: resolve the packaging of array (currently sending a single element) + return( + pull16(ppReadPackedMsg, &value->pduBitmap, end) && + pull16(ppReadPackedMsg, &value->rnti, end) && + pull16(ppReadPackedMsg, &value->pduIndex, end) && + pull16(ppReadPackedMsg, &value->BWPSize, end) && + pull16(ppReadPackedMsg, &value->BWPStart, end) && + pull8(ppReadPackedMsg, &value->SubcarrierSpacing, end) && + pull8(ppReadPackedMsg, &value->CyclicPrefix, end) && + pull8(ppReadPackedMsg, &value->NrOfCodewords, end) && + pullarray16(ppReadPackedMsg, value->targetCodeRate, 2, 1, end) && + pullarray8(ppReadPackedMsg, value->qamModOrder, 2, 1, end) && + pullarray8(ppReadPackedMsg, value->mcsIndex, 2, 1, end) && + pullarray8(ppReadPackedMsg, value->mcsTable, 2, 1, end) && + pullarray8(ppReadPackedMsg, value->rvIndex, 2, 1, end) && + pullarray32(ppReadPackedMsg, value->TBSize, 2, 1, end) && + pull16(ppReadPackedMsg, &value->dataScramblingId, end) && + pull8(ppReadPackedMsg, &value->nrOfLayers, end) && + pull8(ppReadPackedMsg, &value->transmissionScheme, end) && + pull8(ppReadPackedMsg, &value->refPoint, end) && + pull16(ppReadPackedMsg, &value->dlDmrsSymbPos, end) && + pull8(ppReadPackedMsg, &value->dmrsConfigType, end) && + pull16(ppReadPackedMsg, &value->dlDmrsScramblingId, end) && + pull8(ppReadPackedMsg, &value->SCID, end) && + pull8(ppReadPackedMsg, &value->numDmrsCdmGrpsNoData, end) && + pull16(ppReadPackedMsg, &value->dmrsPorts, end) && + pull8(ppReadPackedMsg, &value->resourceAlloc, end) && + pull16(ppReadPackedMsg, &value->rbStart, end) && + pull16(ppReadPackedMsg, &value->rbSize, end) && + pull8(ppReadPackedMsg, &value->VRBtoPRBMapping, end) && + pull8(ppReadPackedMsg, &value->StartSymbolIndex, end) && + pull8(ppReadPackedMsg, &value->NrOfSymbols, end) && + pull8(ppReadPackedMsg, &value->PTRSPortIndex, end) && + pull8(ppReadPackedMsg, &value->PTRSTimeDensity, end) && + pull8(ppReadPackedMsg, &value->PTRSFreqDensity, end) && + pull8(ppReadPackedMsg, &value->PTRSReOffset, end) + ); } -static uint8_t unpack_dl_tti_ssb_pdu_rel15_value(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_nr_dl_tti_ssb_pdu_rel15_t* value = (nfapi_nr_dl_tti_ssb_pdu_rel15_t*)tlv; - - return( - pull16(ppReadPackedMsg, &value->PhysCellId, end) && - pull8(ppReadPackedMsg, &value->BetaPss, end) && - pull8(ppReadPackedMsg, &value->SsbBlockIndex, end) && - pull8(ppReadPackedMsg, &value->SsbSubcarrierOffset, end) && - pull16(ppReadPackedMsg, &value->ssbOffsetPointA, end) && - pull8(ppReadPackedMsg, &value->bchPayloadFlag, end) && - pull32(ppReadPackedMsg, &value->bchPayload, end) - // TODO: pack precoding_and_beamforming too - ); - +static uint8_t unpack_dl_tti_ssb_pdu_rel15_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_nr_dl_tti_ssb_pdu_rel15_t *value = (nfapi_nr_dl_tti_ssb_pdu_rel15_t *)tlv; + return( + pull16(ppReadPackedMsg, &value->PhysCellId, end) && + pull8(ppReadPackedMsg, &value->BetaPss, end) && + pull8(ppReadPackedMsg, &value->SsbBlockIndex, end) && + pull8(ppReadPackedMsg, &value->SsbSubcarrierOffset, end) && + pull16(ppReadPackedMsg, &value->ssbOffsetPointA, end) && + pull8(ppReadPackedMsg, &value->bchPayloadFlag, end) && + pull32(ppReadPackedMsg, &value->bchPayload, end) + // TODO: pack precoding_and_beamforming too + ); } // LTE: -static uint8_t unpack_dl_config_dci_dl_pdu_rel8_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_dl_config_dci_dl_pdu_rel8_t* dci_dl_pdu_rel8 = (nfapi_dl_config_dci_dl_pdu_rel8_t*)tlv; - - return (pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->dci_format, end) && - pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->cce_idx, end) && - pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->aggregation_level, end) && - pull16(ppReadPackedMsg, &dci_dl_pdu_rel8->rnti, end) && - pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->resource_allocation_type, end) && - pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->virtual_resource_block_assignment_flag, end) && - pull32(ppReadPackedMsg, &dci_dl_pdu_rel8->resource_block_coding, end) && - pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->mcs_1, end) && - pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->redundancy_version_1, end) && - pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->new_data_indicator_1, end) && - pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->transport_block_to_codeword_swap_flag, end) && - pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->mcs_2, end) && - pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->redundancy_version_2, end) && - pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->new_data_indicator_2, end) && - pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->harq_process, end) && - pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->tpmi, end) && - pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->pmi, end) && - pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->precoding_information, end) && - pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->tpc, end) && - pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->downlink_assignment_index, end) && - pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->ngap, end) && - pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->transport_block_size_index, end) && - pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->downlink_power_offset, end) && - pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->allocate_prach_flag, end) && - pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->preamble_index, end) && - pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->prach_mask_index, end) && - pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->rnti_type, end) && - pull16(ppReadPackedMsg, &dci_dl_pdu_rel8->transmission_power, end)); - +static uint8_t unpack_dl_config_dci_dl_pdu_rel8_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_dl_config_dci_dl_pdu_rel8_t *dci_dl_pdu_rel8 = (nfapi_dl_config_dci_dl_pdu_rel8_t *)tlv; + return (pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->dci_format, end) && + pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->cce_idx, end) && + pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->aggregation_level, end) && + pull16(ppReadPackedMsg, &dci_dl_pdu_rel8->rnti, end) && + pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->resource_allocation_type, end) && + pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->virtual_resource_block_assignment_flag, end) && + pull32(ppReadPackedMsg, &dci_dl_pdu_rel8->resource_block_coding, end) && + pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->mcs_1, end) && + pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->redundancy_version_1, end) && + pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->new_data_indicator_1, end) && + pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->transport_block_to_codeword_swap_flag, end) && + pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->mcs_2, end) && + pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->redundancy_version_2, end) && + pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->new_data_indicator_2, end) && + pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->harq_process, end) && + pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->tpmi, end) && + pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->pmi, end) && + pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->precoding_information, end) && + pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->tpc, end) && + pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->downlink_assignment_index, end) && + pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->ngap, end) && + pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->transport_block_size_index, end) && + pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->downlink_power_offset, end) && + pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->allocate_prach_flag, end) && + pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->preamble_index, end) && + pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->prach_mask_index, end) && + pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->rnti_type, end) && + pull16(ppReadPackedMsg, &dci_dl_pdu_rel8->transmission_power, end)); } -static uint8_t unpack_dl_config_dci_dl_pdu_rel9_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_dl_config_dci_dl_pdu_rel9_t* dci_dl_pdu_rel9 = (nfapi_dl_config_dci_dl_pdu_rel9_t*)tlv; - - return ( pull8(ppReadPackedMsg, &dci_dl_pdu_rel9->mcch_flag, end) && - pull8(ppReadPackedMsg, &dci_dl_pdu_rel9->mcch_change_notification, end) && - pull8(ppReadPackedMsg, &dci_dl_pdu_rel9->scrambling_identity, end)); +static uint8_t unpack_dl_config_dci_dl_pdu_rel9_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_dl_config_dci_dl_pdu_rel9_t *dci_dl_pdu_rel9 = (nfapi_dl_config_dci_dl_pdu_rel9_t *)tlv; + return ( pull8(ppReadPackedMsg, &dci_dl_pdu_rel9->mcch_flag, end) && + pull8(ppReadPackedMsg, &dci_dl_pdu_rel9->mcch_change_notification, end) && + pull8(ppReadPackedMsg, &dci_dl_pdu_rel9->scrambling_identity, end)); } -static uint8_t unpack_dl_config_dci_dl_pdu_rel10_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_dl_config_dci_dl_pdu_rel10_t* dci_dl_pdu_rel10 = (nfapi_dl_config_dci_dl_pdu_rel10_t*)tlv; - - return (pull8(ppReadPackedMsg, &dci_dl_pdu_rel10->cross_carrier_scheduling_flag, end) && - pull8(ppReadPackedMsg, &dci_dl_pdu_rel10->carrier_indicator, end) && - pull8(ppReadPackedMsg, &dci_dl_pdu_rel10->srs_flag, end) && - pull8(ppReadPackedMsg, &dci_dl_pdu_rel10->srs_request, end) && - pull8(ppReadPackedMsg, &dci_dl_pdu_rel10->antenna_ports_scrambling_and_layers, end) && - pull8(ppReadPackedMsg, &dci_dl_pdu_rel10->total_dci_length_including_padding, end) && - pull8(ppReadPackedMsg, &dci_dl_pdu_rel10->n_dl_rb, end)); +static uint8_t unpack_dl_config_dci_dl_pdu_rel10_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_dl_config_dci_dl_pdu_rel10_t *dci_dl_pdu_rel10 = (nfapi_dl_config_dci_dl_pdu_rel10_t *)tlv; + return (pull8(ppReadPackedMsg, &dci_dl_pdu_rel10->cross_carrier_scheduling_flag, end) && + pull8(ppReadPackedMsg, &dci_dl_pdu_rel10->carrier_indicator, end) && + pull8(ppReadPackedMsg, &dci_dl_pdu_rel10->srs_flag, end) && + pull8(ppReadPackedMsg, &dci_dl_pdu_rel10->srs_request, end) && + pull8(ppReadPackedMsg, &dci_dl_pdu_rel10->antenna_ports_scrambling_and_layers, end) && + pull8(ppReadPackedMsg, &dci_dl_pdu_rel10->total_dci_length_including_padding, end) && + pull8(ppReadPackedMsg, &dci_dl_pdu_rel10->n_dl_rb, end)); } -static uint8_t unpack_dl_config_dci_dl_pdu_rel11_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_dl_config_dci_dl_pdu_rel11_t* dci_dl_pdu_rel11 = (nfapi_dl_config_dci_dl_pdu_rel11_t*)tlv; - - return (pull8(ppReadPackedMsg, &dci_dl_pdu_rel11->harq_ack_resource_offset, end) && - pull8(ppReadPackedMsg, &dci_dl_pdu_rel11->pdsch_re_mapping_quasi_co_location_indicator, end)); +static uint8_t unpack_dl_config_dci_dl_pdu_rel11_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_dl_config_dci_dl_pdu_rel11_t *dci_dl_pdu_rel11 = (nfapi_dl_config_dci_dl_pdu_rel11_t *)tlv; + return (pull8(ppReadPackedMsg, &dci_dl_pdu_rel11->harq_ack_resource_offset, end) && + pull8(ppReadPackedMsg, &dci_dl_pdu_rel11->pdsch_re_mapping_quasi_co_location_indicator, end)); } -static uint8_t unpack_dl_config_dci_dl_pdu_rel12_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_dl_config_dci_dl_pdu_rel12_t* dci_dl_pdu_rel12 = (nfapi_dl_config_dci_dl_pdu_rel12_t*)tlv; - - return (pull8(ppReadPackedMsg, &dci_dl_pdu_rel12->primary_cell_type, end) && - pull8(ppReadPackedMsg, &dci_dl_pdu_rel12->ul_dl_configuration_flag, end) && - pull8(ppReadPackedMsg, &dci_dl_pdu_rel12->number_ul_dl_configurations, end) && - pullarray8(ppReadPackedMsg, dci_dl_pdu_rel12->ul_dl_configuration_indication, NFAPI_MAX_UL_DL_CONFIGURATIONS, dci_dl_pdu_rel12->number_ul_dl_configurations, end)); +static uint8_t unpack_dl_config_dci_dl_pdu_rel12_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_dl_config_dci_dl_pdu_rel12_t *dci_dl_pdu_rel12 = (nfapi_dl_config_dci_dl_pdu_rel12_t *)tlv; + return (pull8(ppReadPackedMsg, &dci_dl_pdu_rel12->primary_cell_type, end) && + pull8(ppReadPackedMsg, &dci_dl_pdu_rel12->ul_dl_configuration_flag, end) && + pull8(ppReadPackedMsg, &dci_dl_pdu_rel12->number_ul_dl_configurations, end) && + pullarray8(ppReadPackedMsg, dci_dl_pdu_rel12->ul_dl_configuration_indication, NFAPI_MAX_UL_DL_CONFIGURATIONS, dci_dl_pdu_rel12->number_ul_dl_configurations, end)); } -static uint8_t unpack_tpm_value(uint8_t **ppReadPackedMsg, nfapi_dl_config_dci_dl_tpm_t *value, uint8_t *end) -{ - if(!(pull8(ppReadPackedMsg, &value->num_prb_per_subband, end) && - pull8(ppReadPackedMsg, &value->number_of_subbands, end) && - pull8(ppReadPackedMsg, &value->num_antennas, end))) - return 0; - - - uint8_t idx = 0; - for(idx = 0; idx < value->number_of_subbands; ++idx) - { - nfapi_dl_config_dci_dl_tpm_subband_info_t* subband_info = &(value->subband_info[idx]); - - if(!(pull8(ppReadPackedMsg, &subband_info->subband_index, end) && - pull8(ppReadPackedMsg, &subband_info->scheduled_ues, end))) - return 0; - - uint8_t antenna_idx = 0; - uint8_t scheduled_ue_idx = 0; - - for(antenna_idx = 0; antenna_idx < value->num_antennas; ++antenna_idx) - { - for(scheduled_ue_idx = 0; scheduled_ue_idx < subband_info->scheduled_ues; ++scheduled_ue_idx) - { - if(!pull16(ppReadPackedMsg, &(subband_info->precoding_value[antenna_idx][scheduled_ue_idx]), end)) - return 0; - } - } +static uint8_t unpack_tpm_value(uint8_t **ppReadPackedMsg, nfapi_dl_config_dci_dl_tpm_t *value, uint8_t *end) { + if(!(pull8(ppReadPackedMsg, &value->num_prb_per_subband, end) && + pull8(ppReadPackedMsg, &value->number_of_subbands, end) && + pull8(ppReadPackedMsg, &value->num_antennas, end))) + return 0; - } - - - return 1; - -} + uint8_t idx = 0; + for(idx = 0; idx < value->number_of_subbands; ++idx) { + nfapi_dl_config_dci_dl_tpm_subband_info_t *subband_info = &(value->subband_info[idx]); -static uint8_t unpack_dl_config_dci_dl_pdu_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_dl_config_dci_dl_pdu_rel13_t* dci_dl_pdu_rel13 = (nfapi_dl_config_dci_dl_pdu_rel13_t*)tlv; - - // If the length is greater than 5 then the TPM struct flag and possiably the TPM structure have been - // added - uint8_t tpm_struct_flag_present = dci_dl_pdu_rel13->tl.length > 5; - dci_dl_pdu_rel13->tpm_struct_flag = 0; - - return (pull8(ppReadPackedMsg, &dci_dl_pdu_rel13->laa_end_partial_sf_flag, end) && - pull8(ppReadPackedMsg, &dci_dl_pdu_rel13->laa_end_partial_sf_configuration, end) && - pull8(ppReadPackedMsg, &dci_dl_pdu_rel13->initial_lbt_sf, end) && - pull8(ppReadPackedMsg, &dci_dl_pdu_rel13->codebook_size_determination, end) && - pull8(ppReadPackedMsg, &dci_dl_pdu_rel13->drms_table_flag, end) && - ( (tpm_struct_flag_present == 1) ? pull8(ppReadPackedMsg, &dci_dl_pdu_rel13->tpm_struct_flag, end) : 1) && - ( (tpm_struct_flag_present == 1 && dci_dl_pdu_rel13->tpm_struct_flag == 1) ? unpack_tpm_value(ppReadPackedMsg, &dci_dl_pdu_rel13->tpm, end) : 1)); - -} - -static uint8_t unpack_dl_config_bch_pdu_rel8_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_dl_config_bch_pdu_rel8_t* bch_pdu_rel8 = (nfapi_dl_config_bch_pdu_rel8_t*)tlv; - - return ( pull16(ppReadPackedMsg, &bch_pdu_rel8->length, end) && - pull16(ppReadPackedMsg, (uint16_t *)&bch_pdu_rel8->pdu_index, end) && - pull16(ppReadPackedMsg, &bch_pdu_rel8->transmission_power, end)); -} - -static uint8_t unpack_dl_config_mch_pdu_rel8_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_dl_config_mch_pdu_rel8_t* mch_pdu_rel8 = (nfapi_dl_config_mch_pdu_rel8_t*)tlv; - - return (pull16(ppReadPackedMsg, &mch_pdu_rel8->length, end) && - pull16(ppReadPackedMsg, (uint16_t *)&mch_pdu_rel8->pdu_index, end) && - pull16(ppReadPackedMsg, &mch_pdu_rel8->rnti, end) && - pull8(ppReadPackedMsg, &mch_pdu_rel8->resource_allocation_type, end) && - pull32(ppReadPackedMsg, &mch_pdu_rel8->resource_block_coding, end) && - pull8(ppReadPackedMsg, &mch_pdu_rel8->modulation, end) && - pull16(ppReadPackedMsg, &mch_pdu_rel8->transmission_power, end) && - pull16(ppReadPackedMsg, &mch_pdu_rel8->mbsfn_area_id, end)); -} - -static uint8_t unpack_dl_config_dlsch_pdu_rel8_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_dl_config_dlsch_pdu_rel8_t* dlsch_pdu_rel8 = (nfapi_dl_config_dlsch_pdu_rel8_t*)tlv; - - if (!(pull16(ppReadPackedMsg, &dlsch_pdu_rel8->length, end) && - pull16(ppReadPackedMsg, (uint16_t *)&dlsch_pdu_rel8->pdu_index, end) && - pull16(ppReadPackedMsg, &dlsch_pdu_rel8->rnti, end) && - pull8(ppReadPackedMsg, &dlsch_pdu_rel8->resource_allocation_type, end) && - pull8(ppReadPackedMsg, &dlsch_pdu_rel8->virtual_resource_block_assignment_flag, end) && - pull32(ppReadPackedMsg, &dlsch_pdu_rel8->resource_block_coding, end) && - pull8(ppReadPackedMsg, &dlsch_pdu_rel8->modulation, end) && - pull8(ppReadPackedMsg, &dlsch_pdu_rel8->redundancy_version, end) && - pull8(ppReadPackedMsg, &dlsch_pdu_rel8->transport_blocks, end) && - pull8(ppReadPackedMsg, &dlsch_pdu_rel8->transport_block_to_codeword_swap_flag, end) && - pull8(ppReadPackedMsg, &dlsch_pdu_rel8->transmission_scheme, end) && - pull8(ppReadPackedMsg, &dlsch_pdu_rel8->number_of_layers, end) && - pull8(ppReadPackedMsg, &dlsch_pdu_rel8->number_of_subbands, end) && - pullarray8(ppReadPackedMsg, dlsch_pdu_rel8->codebook_index, NFAPI_MAX_NUM_SUBBANDS, dlsch_pdu_rel8->number_of_subbands, end) && - pull8(ppReadPackedMsg, &dlsch_pdu_rel8->ue_category_capacity, end) && - pull8(ppReadPackedMsg, &dlsch_pdu_rel8->pa, end) && - pull8(ppReadPackedMsg, &dlsch_pdu_rel8->delta_power_offset_index, end) && - pull8(ppReadPackedMsg, &dlsch_pdu_rel8->ngap, end) && - pull8(ppReadPackedMsg, &dlsch_pdu_rel8->nprb, end) && - pull8(ppReadPackedMsg, &dlsch_pdu_rel8->transmission_mode, end) && - pull8(ppReadPackedMsg, &dlsch_pdu_rel8->num_bf_prb_per_subband, end) && - pull8(ppReadPackedMsg, &dlsch_pdu_rel8->num_bf_vector, end))) - return 0; - - uint16_t j = 0; - for(j = 0; j < dlsch_pdu_rel8->num_bf_vector; ++j) - { - if(!(pull8(ppReadPackedMsg, &dlsch_pdu_rel8->bf_vector[j].subband_index, end) && - pull8(ppReadPackedMsg, &dlsch_pdu_rel8->bf_vector[j].num_antennas, end) && - pullarray16(ppReadPackedMsg, dlsch_pdu_rel8->bf_vector[j].bf_value, NFAPI_MAX_NUM_ANTENNAS, dlsch_pdu_rel8->bf_vector[j].num_antennas, end))) - return 0; - } - return 1; -} -static uint8_t unpack_dl_config_dlsch_pdu_rel9_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_dl_config_dlsch_pdu_rel9_t* dlsch_pdu_rel9 = (nfapi_dl_config_dlsch_pdu_rel9_t*)tlv; - return ( pull8(ppReadPackedMsg, &dlsch_pdu_rel9->nscid, end) ); -} -static uint8_t unpack_dl_config_dlsch_pdu_rel10_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_dl_config_dlsch_pdu_rel10_t* dlsch_pdu_rel10 = (nfapi_dl_config_dlsch_pdu_rel10_t*)tlv; - - return ( pull8(ppReadPackedMsg, &dlsch_pdu_rel10->csi_rs_flag, end) && - pull8(ppReadPackedMsg, &dlsch_pdu_rel10->csi_rs_resource_config_r10, end) && - pull16(ppReadPackedMsg, &dlsch_pdu_rel10->csi_rs_zero_tx_power_resource_config_bitmap_r10, end) && - pull8(ppReadPackedMsg, &dlsch_pdu_rel10->csi_rs_number_nzp_configuration, end) && - pullarray8(ppReadPackedMsg, dlsch_pdu_rel10->csi_rs_resource_config, NFAPI_MAX_CSI_RS_RESOURCE_CONFIG, dlsch_pdu_rel10->csi_rs_number_nzp_configuration, end) && - pull8(ppReadPackedMsg, &dlsch_pdu_rel10->pdsch_start, end)) ; -} -static uint8_t unpack_dl_config_dlsch_pdu_rel11_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_dl_config_dlsch_pdu_rel11_t* dlsch_pdu_rel11 = (nfapi_dl_config_dlsch_pdu_rel11_t*)tlv; - - return ( pull8(ppReadPackedMsg, &dlsch_pdu_rel11->drms_config_flag, end) && - pull16(ppReadPackedMsg, &dlsch_pdu_rel11->drms_scrambling, end) && - pull8(ppReadPackedMsg, &dlsch_pdu_rel11->csi_config_flag, end) && - pull16(ppReadPackedMsg, &dlsch_pdu_rel11->csi_scrambling, end) && - pull8(ppReadPackedMsg, &dlsch_pdu_rel11->pdsch_re_mapping_flag, end) && - pull8(ppReadPackedMsg, &dlsch_pdu_rel11->pdsch_re_mapping_atenna_ports, end) && - pull8(ppReadPackedMsg, &dlsch_pdu_rel11->pdsch_re_mapping_freq_shift, end)); -} -static uint8_t unpack_dl_config_dlsch_pdu_rel12_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_dl_config_dlsch_pdu_rel12_t* dlsch_pdu_rel12 = (nfapi_dl_config_dlsch_pdu_rel12_t*)tlv; - - return ( pull8(ppReadPackedMsg, &dlsch_pdu_rel12->altcqi_table_r12, end) && - pull8(ppReadPackedMsg, &dlsch_pdu_rel12->maxlayers, end) && - pull8(ppReadPackedMsg, &dlsch_pdu_rel12->n_dl_harq, end)); -} -static uint8_t unpack_dl_config_dlsch_pdu_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_dl_config_dlsch_pdu_rel13_t* dlsch_pdu_rel13 = (nfapi_dl_config_dlsch_pdu_rel13_t*)tlv; - - return ( pull8(ppReadPackedMsg, &dlsch_pdu_rel13->dwpts_symbols, end) && - pull8(ppReadPackedMsg, &dlsch_pdu_rel13->initial_lbt_sf, end) && - pull8(ppReadPackedMsg, &dlsch_pdu_rel13->ue_type, end) && - pull8(ppReadPackedMsg, &dlsch_pdu_rel13->pdsch_payload_type, end) && - pull16(ppReadPackedMsg, &dlsch_pdu_rel13->initial_transmission_sf_io, end) && - pull8(ppReadPackedMsg, &dlsch_pdu_rel13->drms_table_flag, end)); -} - -static uint8_t unpack_dl_config_pch_pdu_rel8_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_dl_config_pch_pdu_rel8_t* pch_pdu_rel8 = (nfapi_dl_config_pch_pdu_rel8_t*)tlv; - - return ( pull16(ppReadPackedMsg, &pch_pdu_rel8->length, end) && - pull16(ppReadPackedMsg, (uint16_t *)&pch_pdu_rel8->pdu_index, end) && - pull16(ppReadPackedMsg, &pch_pdu_rel8->p_rnti, end) && - pull8(ppReadPackedMsg, &pch_pdu_rel8->resource_allocation_type, end) && - pull8(ppReadPackedMsg, &pch_pdu_rel8->virtual_resource_block_assignment_flag, end) && - pull32(ppReadPackedMsg, &pch_pdu_rel8->resource_block_coding, end) && - pull8(ppReadPackedMsg, &pch_pdu_rel8->mcs, end) && - pull8(ppReadPackedMsg, &pch_pdu_rel8->redundancy_version, end) && - pull8(ppReadPackedMsg, &pch_pdu_rel8->number_of_transport_blocks, end) && - pull8(ppReadPackedMsg, &pch_pdu_rel8->transport_block_to_codeword_swap_flag, end) && - pull8(ppReadPackedMsg, &pch_pdu_rel8->transmission_scheme, end) && - pull8(ppReadPackedMsg, &pch_pdu_rel8->number_of_layers, end) && - pull8(ppReadPackedMsg, &pch_pdu_rel8->codebook_index, end) && - pull8(ppReadPackedMsg, &pch_pdu_rel8->ue_category_capacity, end) && - pull8(ppReadPackedMsg, &pch_pdu_rel8->pa, end) && - pull16(ppReadPackedMsg, &pch_pdu_rel8->transmission_power, end) && - pull8(ppReadPackedMsg, &pch_pdu_rel8->nprb, end) && - pull8(ppReadPackedMsg, &pch_pdu_rel8->ngap, end)); -} -static uint8_t unpack_dl_config_pch_pdu_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_dl_config_pch_pdu_rel13_t* pch_pdu_rel13 = (nfapi_dl_config_pch_pdu_rel13_t*)tlv; - - return ( pull8(ppReadPackedMsg, &pch_pdu_rel13->ue_mode, end) && - pull16(ppReadPackedMsg, &pch_pdu_rel13->initial_transmission_sf_io, end)); -} - -static uint8_t unpack_dl_config_prs_pdu_rel9_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_dl_config_prs_pdu_rel9_t* prs_pdu_rel9 = (nfapi_dl_config_prs_pdu_rel9_t*)tlv; - - return ( pull16(ppReadPackedMsg, &prs_pdu_rel9->transmission_power, end) && - pull8(ppReadPackedMsg, &prs_pdu_rel9->prs_bandwidth, end) && - pull8(ppReadPackedMsg, &prs_pdu_rel9->prs_cyclic_prefix_type, end) && - pull8(ppReadPackedMsg, &prs_pdu_rel9->prs_muting, end)); -} - -static uint8_t unpack_dl_config_csi_rs_pdu_rel10_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_dl_config_csi_rs_pdu_rel10_t* csi_rs_pdu_rel10 = (nfapi_dl_config_csi_rs_pdu_rel10_t*)tlv; - - return ( pull8(ppReadPackedMsg, &csi_rs_pdu_rel10->csi_rs_antenna_port_count_r10, end) && - pull8(ppReadPackedMsg, &csi_rs_pdu_rel10->csi_rs_resource_config_r10, end) && - pull16(ppReadPackedMsg, &csi_rs_pdu_rel10->transmission_power, end) && - pull16(ppReadPackedMsg, &csi_rs_pdu_rel10->csi_rs_zero_tx_power_resource_config_bitmap_r10, end) && - pull8(ppReadPackedMsg, &csi_rs_pdu_rel10->csi_rs_number_of_nzp_configuration, end) && - pullarray8(ppReadPackedMsg, csi_rs_pdu_rel10->csi_rs_resource_config, NFAPI_MAX_CSI_RS_RESOURCE_CONFIG, csi_rs_pdu_rel10->csi_rs_number_of_nzp_configuration, end)); -} - -static uint8_t unpack_dl_config_csi_rs_pdu_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_dl_config_csi_rs_pdu_rel13_t* csi_rs_pdu_rel13 = (nfapi_dl_config_csi_rs_pdu_rel13_t*)tlv; - - if (!(pull8(ppReadPackedMsg, &csi_rs_pdu_rel13->csi_rs_class, end) && - pull8(ppReadPackedMsg, &csi_rs_pdu_rel13->cdm_type, end) && - pull8(ppReadPackedMsg, &csi_rs_pdu_rel13->num_bf_vector, end))) - return 0; - - - uint16_t idx =0; - for(idx = 0; idx < csi_rs_pdu_rel13->num_bf_vector; ++idx) - { - if(!(pull8(ppReadPackedMsg, &csi_rs_pdu_rel13->bf_vector[idx].csi_rs_resource_index, end))) - return 0; - NFAPI_TRACE(NFAPI_TRACE_ERROR, "FIXME : HOW TO DECODE BF VALUE \n"); - //pullarray16(ppReadPackedMsg, &csi_rs_pdu_rel13->bf_vector[idx].bf_vector, ??); - } - return 1; -} - -static uint8_t unpack_dl_config_epdcch_params_rel11_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_dl_config_epdcch_parameters_rel11_t* epdcch_params_rel11 = (nfapi_dl_config_epdcch_parameters_rel11_t*)tlv; - - return (pull8(ppReadPackedMsg, &epdcch_params_rel11->epdcch_resource_assignment_flag, end) && - pull16(ppReadPackedMsg, &epdcch_params_rel11->epdcch_id, end) && - pull8(ppReadPackedMsg, &epdcch_params_rel11->epdcch_start_symbol, end) && - pull8(ppReadPackedMsg, &epdcch_params_rel11->epdcch_num_prb, end) && - pullarray8(ppReadPackedMsg, epdcch_params_rel11->epdcch_prb_index, NFAPI_MAX_EPDCCH_PRB, epdcch_params_rel11->epdcch_num_prb, end) && - pull8(ppReadPackedMsg, &epdcch_params_rel11->bf_vector.subband_index, end) && - pull8(ppReadPackedMsg, &epdcch_params_rel11->bf_vector.num_antennas, end) && - pullarray16(ppReadPackedMsg, epdcch_params_rel11->bf_vector.bf_value, NFAPI_MAX_NUM_ANTENNAS, epdcch_params_rel11->bf_vector.num_antennas, end)); -} - -static uint8_t unpack_dl_config_epdcch_params_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_dl_config_epdcch_parameters_rel13_t* epdcch_params_rel13 = (nfapi_dl_config_epdcch_parameters_rel13_t*)tlv; - - return ( pull8(ppReadPackedMsg, &epdcch_params_rel13->dwpts_symbols, end) && - pull8(ppReadPackedMsg, &epdcch_params_rel13->initial_lbt_sf, end)); -} - -static uint8_t unpack_dl_config_mpdcch_pdu_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_dl_config_mpdcch_pdu_rel13_t* mpdcch_params_rel13 = (nfapi_dl_config_mpdcch_pdu_rel13_t*)tlv; - - - return ( pull8(ppReadPackedMsg, &mpdcch_params_rel13->mpdcch_narrow_band, end) && - pull8(ppReadPackedMsg, &mpdcch_params_rel13->number_of_prb_pairs, end) && - pull8(ppReadPackedMsg, &mpdcch_params_rel13->resource_block_assignment, end) && - pull8(ppReadPackedMsg, &mpdcch_params_rel13->mpdcch_tansmission_type, end) && - pull8(ppReadPackedMsg, &mpdcch_params_rel13->start_symbol, end) && - pull8(ppReadPackedMsg, &mpdcch_params_rel13->ecce_index, end) && - pull8(ppReadPackedMsg, &mpdcch_params_rel13->aggregation_level, end) && - pull8(ppReadPackedMsg, &mpdcch_params_rel13->rnti_type, end) && - pull16(ppReadPackedMsg, &mpdcch_params_rel13->rnti, end) && - pull8(ppReadPackedMsg, &mpdcch_params_rel13->ce_mode, end) && - pull16(ppReadPackedMsg, &mpdcch_params_rel13->drms_scrambling_init, end) && - pull16(ppReadPackedMsg, &mpdcch_params_rel13->initial_transmission_sf_io, end) && - pull16(ppReadPackedMsg, &mpdcch_params_rel13->transmission_power, end) && - pull8(ppReadPackedMsg, &mpdcch_params_rel13->dci_format, end) && - pull16(ppReadPackedMsg, &mpdcch_params_rel13->resource_block_coding, end) && - pull8(ppReadPackedMsg, &mpdcch_params_rel13->mcs, end) && - pull8(ppReadPackedMsg, &mpdcch_params_rel13->pdsch_reptition_levels, end) && - pull8(ppReadPackedMsg, &mpdcch_params_rel13->redundancy_version, end) && - pull8(ppReadPackedMsg, &mpdcch_params_rel13->new_data_indicator, end) && - pull8(ppReadPackedMsg, &mpdcch_params_rel13->harq_process, end) && - pull8(ppReadPackedMsg, &mpdcch_params_rel13->tpmi_length, end) && - pull8(ppReadPackedMsg, &mpdcch_params_rel13->tpmi, end) && - pull8(ppReadPackedMsg, &mpdcch_params_rel13->pmi_flag, end) && - pull8(ppReadPackedMsg, &mpdcch_params_rel13->pmi, end) && - pull8(ppReadPackedMsg, &mpdcch_params_rel13->harq_resource_offset, end) && - pull8(ppReadPackedMsg, &mpdcch_params_rel13->dci_subframe_repetition_number, end) && - pull8(ppReadPackedMsg, &mpdcch_params_rel13->tpc, end) && - pull8(ppReadPackedMsg, &mpdcch_params_rel13->downlink_assignment_index_length, end) && - pull8(ppReadPackedMsg, &mpdcch_params_rel13->downlink_assignment_index, end) && - pull8(ppReadPackedMsg, &mpdcch_params_rel13->allocate_prach_flag, end) && - pull8(ppReadPackedMsg, &mpdcch_params_rel13->preamble_index, end) && - pull8(ppReadPackedMsg, &mpdcch_params_rel13->prach_mask_index, end) && - pull8(ppReadPackedMsg, &mpdcch_params_rel13->starting_ce_level, end) && - pull8(ppReadPackedMsg, &mpdcch_params_rel13->srs_request, end) && - pull8(ppReadPackedMsg, &mpdcch_params_rel13->antenna_ports_and_scrambling_identity_flag, end) && - pull8(ppReadPackedMsg, &mpdcch_params_rel13->antenna_ports_and_scrambling_identity, end) && - pull8(ppReadPackedMsg, &mpdcch_params_rel13->frequency_hopping_enabled_flag, end) && - pull8(ppReadPackedMsg, &mpdcch_params_rel13->paging_direct_indication_differentiation_flag, end) && - pull8(ppReadPackedMsg, &mpdcch_params_rel13->direct_indication, end) && - pull8(ppReadPackedMsg, &mpdcch_params_rel13->total_dci_length_including_padding, end) && - pull8(ppReadPackedMsg, &mpdcch_params_rel13->number_of_tx_antenna_ports, end) && - pullarray16(ppReadPackedMsg, mpdcch_params_rel13->precoding_value, NFAPI_MAX_TX_PHYSICAL_ANTENNA_PORTS, mpdcch_params_rel13->number_of_tx_antenna_ports, end)); -} - - -static uint8_t unpack_dl_config_nbch_pdu_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_dl_config_nbch_pdu_rel13_t* nbch_params_rel13 = (nfapi_dl_config_nbch_pdu_rel13_t*)tlv; - - return ( pull16(ppReadPackedMsg, &nbch_params_rel13->length, end) && - pull16(ppReadPackedMsg, (uint16_t *)&nbch_params_rel13->pdu_index, end) && - pull16(ppReadPackedMsg, &nbch_params_rel13->transmission_power, end) && - pull16(ppReadPackedMsg, &nbch_params_rel13->hyper_sfn_2_lsbs, end)); -} - -static uint8_t unpack_dl_config_npdcch_pdu_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_dl_config_npdcch_pdu_rel13_t* npdcch_params_rel13 = (nfapi_dl_config_npdcch_pdu_rel13_t*)tlv; - - return ( pull16(ppReadPackedMsg, &npdcch_params_rel13->length, end) && - pull16(ppReadPackedMsg, (uint16_t *)&npdcch_params_rel13->pdu_index, end) && - pull8(ppReadPackedMsg, &npdcch_params_rel13->ncce_index, end) && - pull8(ppReadPackedMsg, &npdcch_params_rel13->aggregation_level, end) && - pull8(ppReadPackedMsg, &npdcch_params_rel13->start_symbol, end) && - pull8(ppReadPackedMsg, &npdcch_params_rel13->rnti_type, end) && - pull16(ppReadPackedMsg, &npdcch_params_rel13->rnti, end) && - pull8(ppReadPackedMsg, &npdcch_params_rel13->scrambling_reinitialization_batch_index, end) && - pull8(ppReadPackedMsg, &npdcch_params_rel13->nrs_antenna_ports_assumed_by_the_ue, end) && - pull8(ppReadPackedMsg, &npdcch_params_rel13->dci_format, end) && - pull8(ppReadPackedMsg, &npdcch_params_rel13->scheduling_delay, end) && - pull8(ppReadPackedMsg, &npdcch_params_rel13->resource_assignment, end) && - pull8(ppReadPackedMsg, &npdcch_params_rel13->repetition_number, end) && - pull8(ppReadPackedMsg, &npdcch_params_rel13->mcs, end) && - pull8(ppReadPackedMsg, &npdcch_params_rel13->new_data_indicator, end) && - pull8(ppReadPackedMsg, &npdcch_params_rel13->harq_ack_resource, end) && - pull8(ppReadPackedMsg, &npdcch_params_rel13->npdcch_order_indication, end) && - pull8(ppReadPackedMsg, &npdcch_params_rel13->starting_number_of_nprach_repetitions, end) && - pull8(ppReadPackedMsg, &npdcch_params_rel13->subcarrier_indication_of_nprach, end) && - pull8(ppReadPackedMsg, &npdcch_params_rel13->paging_direct_indication_differentation_flag, end) && - pull8(ppReadPackedMsg, &npdcch_params_rel13->direct_indication, end) && - pull8(ppReadPackedMsg, &npdcch_params_rel13->dci_subframe_repetition_number, end) && - pull8(ppReadPackedMsg, &npdcch_params_rel13->total_dci_length_including_padding, end)); -} - -static uint8_t unpack_dl_config_ndlsch_pdu_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_dl_config_ndlsch_pdu_rel13_t* ndlsch_params_rel13 = (nfapi_dl_config_ndlsch_pdu_rel13_t*)tlv; - - return ( pull16(ppReadPackedMsg, &ndlsch_params_rel13->length, end) && - pull16(ppReadPackedMsg, (uint16_t *)&ndlsch_params_rel13->pdu_index, end) && - pull8(ppReadPackedMsg, &ndlsch_params_rel13->start_symbol, end) && - pull8(ppReadPackedMsg, &ndlsch_params_rel13->rnti_type, end) && - pull16(ppReadPackedMsg, &ndlsch_params_rel13->rnti, end) && - pull16(ppReadPackedMsg, &ndlsch_params_rel13->resource_assignment, end) && - pull16(ppReadPackedMsg, &ndlsch_params_rel13->repetition_number, end) && - pull8(ppReadPackedMsg, &ndlsch_params_rel13->modulation, end) && - pull8(ppReadPackedMsg, &ndlsch_params_rel13->number_of_subframes_for_resource_assignment, end) && - pull8(ppReadPackedMsg, &ndlsch_params_rel13->scrambling_sequence_initialization_cinit, end) && - pull16(ppReadPackedMsg, &ndlsch_params_rel13->sf_idx, end) && - pull8(ppReadPackedMsg, &ndlsch_params_rel13->nrs_antenna_ports_assumed_by_the_ue, end)); -} - - -static uint8_t unpack_dl_tti_request_body_value(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg) -{ - nfapi_nr_dl_tti_request_pdu_t* value = (nfapi_nr_dl_tti_request_pdu_t*)msg; - - if(!(pull32(ppReadPackedMsg, &value->PDUSize, end) && - pull16(ppReadPackedMsg, &value->PDUType, end) )) - return 0; - - - // first match the pdu type, then call the respective function - switch(value->PDUType) - { - case NFAPI_NR_DL_TTI_CSI_RS_PDU_TYPE: - { - if(!(unpack_dl_tti_csi_rs_pdu_rel15_value(&value->csi_rs_pdu.csi_rs_pdu_rel15,ppReadPackedMsg,end))) - return 0; - } - break; - - case NFAPI_NR_DL_TTI_PDCCH_PDU_TYPE: - { - if(!(unpack_dl_tti_pdcch_pdu_rel15_value(&value->pdcch_pdu.pdcch_pdu_rel15,ppReadPackedMsg,end))) - return 0; - } - break; - case NFAPI_NR_DL_TTI_PDSCH_PDU_TYPE: - { - if(!(unpack_dl_tti_pdsch_pdu_rel15_value(&value->pdsch_pdu.pdsch_pdu_rel15,ppReadPackedMsg,end))) - return 0; - } - break; - case NFAPI_NR_DL_TTI_SSB_PDU_TYPE: - { - if(!(unpack_dl_tti_ssb_pdu_rel15_value(&value->ssb_pdu.ssb_pdu_rel15,ppReadPackedMsg,end))) - return 0; - } - break; - - default: - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "FIXME : Invalid DL_TTI pdu type %d \n", value->PDUType ); - } - break; - } - - return 1; -} - - - - -static uint8_t unpack_dl_config_request_body_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) -{ - nfapi_dl_config_request_body_t* value = (nfapi_dl_config_request_body_t*)tlv; - - if(!(pull8(ppReadPackedMsg, &value->number_pdcch_ofdm_symbols, end) && - pull8(ppReadPackedMsg, &value->number_dci, end) && - pull16(ppReadPackedMsg, &value->number_pdu, end) && - pull8(ppReadPackedMsg, &value->number_pdsch_rnti, end) && - pull16(ppReadPackedMsg, &value->transmission_power_pcfich, end))) - return 0; - - if(value->number_pdu > NFAPI_DL_CONFIG_MAX_PDU) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s number of dl config pdu's exceed maxium (count:%d max:%d)\n", __FUNCTION__, value->number_pdu, NFAPI_DL_CONFIG_MAX_PDU); - return 0; - } - - if(value->number_pdu) - { - value->dl_config_pdu_list = (nfapi_dl_config_request_pdu_t*)nfapi_p7_allocate(sizeof(nfapi_dl_config_request_pdu_t) * value->number_pdu, config); - if(value->dl_config_pdu_list == NULL) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s failed to allocate dl config pdu list (count:%d)\n", __FUNCTION__, value->number_pdu); - return 0; - } - } - else - { - value->dl_config_pdu_list = 0; - } - - uint16_t i; - uint16_t total_number_of_pdus = value->number_pdu; - for(i = 0; i < total_number_of_pdus; ++i) - { - nfapi_dl_config_request_pdu_t* pdu = &(value->dl_config_pdu_list[i]); - - if(!(pull8(ppReadPackedMsg, &pdu->pdu_type, end) && - pull8(ppReadPackedMsg, &pdu->pdu_size, end))) - return 0; - - uint8_t *packedPduEnd = (*ppReadPackedMsg) + pdu->pdu_size - 2; - - if(packedPduEnd > end) - { - // pdu end of beyond buffer end - return 0; - } - - switch(pdu->pdu_type) - { - case NFAPI_DL_CONFIG_DCI_DL_PDU_TYPE: - { - unpack_tlv_t unpack_fns[] = - { - { NFAPI_DL_CONFIG_REQUEST_DCI_DL_PDU_REL8_TAG, &pdu->dci_dl_pdu.dci_dl_pdu_rel8, &unpack_dl_config_dci_dl_pdu_rel8_value}, - { NFAPI_DL_CONFIG_REQUEST_DCI_DL_PDU_REL9_TAG, &pdu->dci_dl_pdu.dci_dl_pdu_rel9, &unpack_dl_config_dci_dl_pdu_rel9_value}, - { NFAPI_DL_CONFIG_REQUEST_DCI_DL_PDU_REL10_TAG, &pdu->dci_dl_pdu.dci_dl_pdu_rel10, &unpack_dl_config_dci_dl_pdu_rel10_value}, - { NFAPI_DL_CONFIG_REQUEST_DCI_DL_PDU_REL11_TAG, &pdu->dci_dl_pdu.dci_dl_pdu_rel11, &unpack_dl_config_dci_dl_pdu_rel11_value}, - { NFAPI_DL_CONFIG_REQUEST_DCI_DL_PDU_REL12_TAG, &pdu->dci_dl_pdu.dci_dl_pdu_rel12, &unpack_dl_config_dci_dl_pdu_rel12_value}, - { NFAPI_DL_CONFIG_REQUEST_DCI_DL_PDU_REL13_TAG, &pdu->dci_dl_pdu.dci_dl_pdu_rel13, &unpack_dl_config_dci_dl_pdu_rel13_value}, - }; - - unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); - } - break; - case NFAPI_DL_CONFIG_BCH_PDU_TYPE: - { - unpack_tlv_t unpack_fns[] = - { - { NFAPI_DL_CONFIG_REQUEST_BCH_PDU_REL8_TAG, &pdu->bch_pdu.bch_pdu_rel8, &unpack_dl_config_bch_pdu_rel8_value}, - }; - - unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); - } - break; - case NFAPI_DL_CONFIG_MCH_PDU_TYPE: - { - unpack_tlv_t unpack_fns[] = - { - { NFAPI_DL_CONFIG_REQUEST_MCH_PDU_REL8_TAG, &pdu->mch_pdu.mch_pdu_rel8, &unpack_dl_config_mch_pdu_rel8_value}, - }; - - unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); - } - break; - case NFAPI_DL_CONFIG_DLSCH_PDU_TYPE: - { - unpack_tlv_t unpack_fns[] = - { - { NFAPI_DL_CONFIG_REQUEST_DLSCH_PDU_REL8_TAG, &pdu->dlsch_pdu.dlsch_pdu_rel8, &unpack_dl_config_dlsch_pdu_rel8_value}, - { NFAPI_DL_CONFIG_REQUEST_DLSCH_PDU_REL9_TAG, &pdu->dlsch_pdu.dlsch_pdu_rel9, &unpack_dl_config_dlsch_pdu_rel9_value}, - { NFAPI_DL_CONFIG_REQUEST_DLSCH_PDU_REL10_TAG, &pdu->dlsch_pdu.dlsch_pdu_rel10, &unpack_dl_config_dlsch_pdu_rel10_value}, - { NFAPI_DL_CONFIG_REQUEST_DLSCH_PDU_REL11_TAG, &pdu->dlsch_pdu.dlsch_pdu_rel11, &unpack_dl_config_dlsch_pdu_rel11_value}, - { NFAPI_DL_CONFIG_REQUEST_DLSCH_PDU_REL12_TAG, &pdu->dlsch_pdu.dlsch_pdu_rel12, &unpack_dl_config_dlsch_pdu_rel12_value}, - { NFAPI_DL_CONFIG_REQUEST_DLSCH_PDU_REL13_TAG, &pdu->dlsch_pdu.dlsch_pdu_rel13, &unpack_dl_config_dlsch_pdu_rel13_value}, - }; - - unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); - } - break; - case NFAPI_DL_CONFIG_PCH_PDU_TYPE: - { - unpack_tlv_t unpack_fns[] = - { - { NFAPI_DL_CONFIG_REQUEST_PCH_PDU_REL8_TAG, &pdu->pch_pdu.pch_pdu_rel8, &unpack_dl_config_pch_pdu_rel8_value}, - { NFAPI_DL_CONFIG_REQUEST_PCH_PDU_REL13_TAG, &pdu->pch_pdu.pch_pdu_rel13, &unpack_dl_config_pch_pdu_rel13_value}, - }; - - unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); - } - break; - case NFAPI_DL_CONFIG_PRS_PDU_TYPE: - { - unpack_tlv_t unpack_fns[] = - { - { NFAPI_DL_CONFIG_REQUEST_PRS_PDU_REL9_TAG, &pdu->prs_pdu.prs_pdu_rel9, &unpack_dl_config_prs_pdu_rel9_value}, - }; - - unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); - } - break; - case NFAPI_DL_CONFIG_CSI_RS_PDU_TYPE: - { - unpack_tlv_t unpack_fns[] = - { - { NFAPI_DL_CONFIG_REQUEST_CSI_RS_PDU_REL10_TAG, &pdu->csi_rs_pdu.csi_rs_pdu_rel10, &unpack_dl_config_csi_rs_pdu_rel10_value}, - { NFAPI_DL_CONFIG_REQUEST_CSI_RS_PDU_REL13_TAG, &pdu->csi_rs_pdu.csi_rs_pdu_rel13, &unpack_dl_config_csi_rs_pdu_rel13_value}, - }; - - unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); - } - break; - case NFAPI_DL_CONFIG_EPDCCH_DL_PDU_TYPE: - { - unpack_tlv_t unpack_fns[] = - { - { NFAPI_DL_CONFIG_REQUEST_EPDCCH_PDU_REL8_TAG, &pdu->epdcch_pdu.epdcch_pdu_rel8, &unpack_dl_config_dci_dl_pdu_rel8_value}, - { NFAPI_DL_CONFIG_REQUEST_EPDCCH_PDU_REL9_TAG, &pdu->epdcch_pdu.epdcch_pdu_rel9, &unpack_dl_config_dci_dl_pdu_rel9_value}, - { NFAPI_DL_CONFIG_REQUEST_EPDCCH_PDU_REL10_TAG, &pdu->epdcch_pdu.epdcch_pdu_rel10, &unpack_dl_config_dci_dl_pdu_rel10_value}, - { NFAPI_DL_CONFIG_REQUEST_EPDCCH_PDU_REL11_TAG, &pdu->epdcch_pdu.epdcch_pdu_rel11, &unpack_dl_config_dci_dl_pdu_rel11_value}, - { NFAPI_DL_CONFIG_REQUEST_EPDCCH_PDU_REL12_TAG, &pdu->epdcch_pdu.epdcch_pdu_rel12, &unpack_dl_config_dci_dl_pdu_rel12_value}, - { NFAPI_DL_CONFIG_REQUEST_EPDCCH_PDU_REL13_TAG, &pdu->epdcch_pdu.epdcch_pdu_rel13, &unpack_dl_config_dci_dl_pdu_rel13_value}, - { NFAPI_DL_CONFIG_REQUEST_EPDCCH_PARAM_REL11_TAG, &pdu->epdcch_pdu.epdcch_params_rel11, &unpack_dl_config_epdcch_params_rel11_value}, - { NFAPI_DL_CONFIG_REQUEST_EPDCCH_PARAM_REL13_TAG, &pdu->epdcch_pdu.epdcch_params_rel13, &unpack_dl_config_epdcch_params_rel13_value}, - }; - - unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); - } - break; - case NFAPI_DL_CONFIG_MPDCCH_PDU_TYPE: - { - unpack_tlv_t unpack_fns[] = - { - { NFAPI_DL_CONFIG_REQUEST_MPDCCH_PDU_REL13_TAG, &pdu->mpdcch_pdu.mpdcch_pdu_rel13, &unpack_dl_config_mpdcch_pdu_rel13_value}, - }; - - unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); - } - break; - case NFAPI_DL_CONFIG_NBCH_PDU_TYPE: - { - unpack_tlv_t unpack_fns[] = - { - { NFAPI_DL_CONFIG_REQUEST_NBCH_PDU_REL13_TAG, &pdu->nbch_pdu.nbch_pdu_rel13, &unpack_dl_config_nbch_pdu_rel13_value}, - }; - - unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); - } - break; - case NFAPI_DL_CONFIG_NPDCCH_PDU_TYPE: - { - unpack_tlv_t unpack_fns[] = - { - { NFAPI_DL_CONFIG_REQUEST_NPDCCH_PDU_REL13_TAG, &pdu->npdcch_pdu.npdcch_pdu_rel13, &unpack_dl_config_npdcch_pdu_rel13_value}, - }; - - unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); - - } - break; - case NFAPI_DL_CONFIG_NDLSCH_PDU_TYPE: - { - unpack_tlv_t unpack_fns[] = - { - { NFAPI_DL_CONFIG_REQUEST_NDLSCH_PDU_REL13_TAG, &pdu->ndlsch_pdu.ndlsch_pdu_rel13, &unpack_dl_config_ndlsch_pdu_rel13_value}, - }; - - unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); - - } - break; - default: - // Need to log an error - break; - } - } - - return 1; -} - - -static uint8_t unpack_dl_tti_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config) -{ - nfapi_nr_dl_tti_request_t *pNfapiMsg = (nfapi_nr_dl_tti_request_t*)msg; - - if (!(pull16(ppReadPackedMsg,&pNfapiMsg->SFN, end) && - pull16(ppReadPackedMsg, &pNfapiMsg->Slot, end) && - pull8(ppReadPackedMsg, &pNfapiMsg->dl_tti_request_body.nGroup, end) && - pull8(ppReadPackedMsg, &pNfapiMsg->dl_tti_request_body.nPDUs, end) && - pullarray8(ppReadPackedMsg,pNfapiMsg->dl_tti_request_body.nUe ,256,pNfapiMsg->dl_tti_request_body.nGroup, end) - //pusharray8(pNfapiMsg->PduIdx[0] ,256,256, ppWritePackedMsg, end) - )) - return 0; - - int arr[12]; - for(int i=0;idl_tti_request_body.nGroup;i++) - { - for(int j=0;jdl_tti_request_body.nUe[i];j++) - { - arr[j] = pNfapiMsg->dl_tti_request_body.PduIdx[i][j]; - } - if(!(pullarrays32(ppReadPackedMsg,arr,12,pNfapiMsg->dl_tti_request_body.nUe[i], end))) - return 0; - } - - for(int i=0;idl_tti_request_body.nPDUs;i++) - { - if(!unpack_dl_tti_request_body_value(ppReadPackedMsg, end, &pNfapiMsg->dl_tti_request_body.dl_tti_pdu_list[i])) - return 0; - } - -return 1; -} - - -static uint8_t unpack_ul_tti_request_prach_pdu(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_nr_prach_pdu_t* prach_pdu = (nfapi_nr_prach_pdu_t*)tlv; - - return( - pull16(ppReadPackedMsg, &prach_pdu->phys_cell_id, end) && - pull8(ppReadPackedMsg, &prach_pdu->num_prach_ocas, end) && - pull8(ppReadPackedMsg, &prach_pdu->prach_format, end) && - pull8(ppReadPackedMsg, &prach_pdu->num_ra, end) && - pull8(ppReadPackedMsg, &prach_pdu->prach_start_symbol, end) && - pull16(ppReadPackedMsg, &prach_pdu->num_cs, end) - // TODO: ignoring beamforming tlv for now - ); -} - - -static uint8_t unpack_ul_tti_request_pucch_pdu(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_nr_pucch_pdu_t* pucch_pdu = (nfapi_nr_pucch_pdu_t*)tlv; - - return( - pull16(ppReadPackedMsg, &pucch_pdu->rnti, end) && - pull32(ppReadPackedMsg, &pucch_pdu->handle, end) && - pull16(ppReadPackedMsg, &pucch_pdu->bwp_size, end) && - pull16(ppReadPackedMsg, &pucch_pdu->bwp_start, end) && - pull8(ppReadPackedMsg, &pucch_pdu->subcarrier_spacing, end) && - pull8(ppReadPackedMsg, &pucch_pdu->cyclic_prefix, end) && - pull8(ppReadPackedMsg, &pucch_pdu->format_type, end) && - pull8(ppReadPackedMsg, &pucch_pdu->multi_slot_tx_indicator, end) && - pull16(ppReadPackedMsg, &pucch_pdu->prb_start, end) && - pull16(ppReadPackedMsg, &pucch_pdu->prb_size, end) && - pull8(ppReadPackedMsg, &pucch_pdu->start_symbol_index, end) && - pull8(ppReadPackedMsg, &pucch_pdu->nr_of_symbols, end) && - pull8(ppReadPackedMsg, &pucch_pdu->freq_hop_flag, end) && - pull16(ppReadPackedMsg, &pucch_pdu->second_hop_prb, end) && - pull8(ppReadPackedMsg, &pucch_pdu->group_hop_flag, end) && - pull8(ppReadPackedMsg, &pucch_pdu->sequence_hop_flag, end) && - pull16(ppReadPackedMsg, &pucch_pdu->hopping_id, end) && - pull16(ppReadPackedMsg, &pucch_pdu->initial_cyclic_shift, end) && - pull16(ppReadPackedMsg, &pucch_pdu->data_scrambling_id, end) && - pull8(ppReadPackedMsg, &pucch_pdu->time_domain_occ_idx, end) && - pull8(ppReadPackedMsg, &pucch_pdu->pre_dft_occ_idx, end) && - pull8(ppReadPackedMsg, &pucch_pdu->pre_dft_occ_len, end) && - pull8(ppReadPackedMsg, &pucch_pdu->add_dmrs_flag, end) && - pull16(ppReadPackedMsg, &pucch_pdu->dmrs_scrambling_id, end) && - pull8(ppReadPackedMsg, &pucch_pdu->dmrs_cyclic_shift, end) && - pull8(ppReadPackedMsg, &pucch_pdu->sr_flag, end) && - pull8(ppReadPackedMsg, &pucch_pdu->bit_len_harq, end) && - pull16(ppReadPackedMsg, &pucch_pdu->bit_len_csi_part1, end) && - pull16(ppReadPackedMsg, &pucch_pdu->bit_len_csi_part2, end) - // TODO: ignoring beamforming tlv for now - ); -} - - -static uint8_t unpack_ul_tti_request_pusch_pdu(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_nr_pusch_pdu_t* pusch_pdu = (nfapi_nr_pusch_pdu_t*)tlv; - - if (!( - pull16(ppReadPackedMsg, &pusch_pdu->pdu_bit_map, end) && - pull16(ppReadPackedMsg, &pusch_pdu->rnti, end) && - pull32(ppReadPackedMsg, &pusch_pdu->handle, end) && - pull16(ppReadPackedMsg, &pusch_pdu->bwp_size, end) && - pull16(ppReadPackedMsg, &pusch_pdu->bwp_start, end) && - pull8(ppReadPackedMsg, &pusch_pdu->subcarrier_spacing, end) && - pull8(ppReadPackedMsg, &pusch_pdu->cyclic_prefix, end) && - pull16(ppReadPackedMsg, &pusch_pdu->target_code_rate, end) && - pull8(ppReadPackedMsg, &pusch_pdu->qam_mod_order, end) && - pull8(ppReadPackedMsg, &pusch_pdu->mcs_index, end) && - pull8(ppReadPackedMsg, &pusch_pdu->mcs_table, end) && - pull8(ppReadPackedMsg, &pusch_pdu->transform_precoding, end) && - pull16(ppReadPackedMsg, &pusch_pdu->data_scrambling_id, end) && - pull8(ppReadPackedMsg, &pusch_pdu->nrOfLayers, end) && - pull16(ppReadPackedMsg, &pusch_pdu->ul_dmrs_symb_pos, end) && - pull8(ppReadPackedMsg, &pusch_pdu->dmrs_config_type, end) && - pull16(ppReadPackedMsg, &pusch_pdu->ul_dmrs_scrambling_id, end) && - pull8(ppReadPackedMsg, &pusch_pdu->scid, end) && - pull8(ppReadPackedMsg, &pusch_pdu->num_dmrs_cdm_grps_no_data, end) && - pull16(ppReadPackedMsg, &pusch_pdu->dmrs_ports, end) && - pull8(ppReadPackedMsg, &pusch_pdu->resource_alloc, end) && - pull8(ppReadPackedMsg, &pusch_pdu->resource_alloc,end) && - pull16(ppReadPackedMsg, &pusch_pdu->dmrs_ports, end) && - pull16(ppReadPackedMsg, &pusch_pdu->rb_start, end) && - pull16(ppReadPackedMsg, &pusch_pdu->rb_size, end) && - pull8(ppReadPackedMsg, &pusch_pdu->vrb_to_prb_mapping, end) && - pull8(ppReadPackedMsg, &pusch_pdu->frequency_hopping, end) && - pull16(ppReadPackedMsg, &pusch_pdu->tx_direct_current_location, end) && - pull8(ppReadPackedMsg, &pusch_pdu->uplink_frequency_shift_7p5khz, end) && - pull8(ppReadPackedMsg, &pusch_pdu->start_symbol_index, end) && - pull8(ppReadPackedMsg, &pusch_pdu->nr_of_symbols, end) - // TODO: ignoring beamforming tlv for now - )) - return 0; - - - //Pack Optional Data only included if indicated in pduBitmap - switch(pusch_pdu->pdu_bit_map){ - case PUSCH_PDU_BITMAP_PUSCH_DATA: - { - // pack optional TLVs - return( - pull8(ppReadPackedMsg, &pusch_pdu->pusch_data.rv_index, end) && - pull8(ppReadPackedMsg, &pusch_pdu->pusch_data.harq_process_id, end) && - pull32(ppReadPackedMsg, &pusch_pdu->pusch_data.tb_size, end) && - pull16(ppReadPackedMsg, &pusch_pdu->pusch_data.num_cb, end) && - pullarray8(ppReadPackedMsg, pusch_pdu->pusch_data.cb_present_and_position,1,1,end) - ); - } - break; - - case PUSCH_PDU_BITMAP_PUSCH_UCI: - { - return( - pull16(ppReadPackedMsg, &pusch_pdu->pusch_uci.harq_ack_bit_length, end) && - pull16(ppReadPackedMsg, &pusch_pdu->pusch_uci.csi_part1_bit_length, end) && - pull16(ppReadPackedMsg, &pusch_pdu->pusch_uci.csi_part2_bit_length, end) && - pull8(ppReadPackedMsg, &pusch_pdu->pusch_uci.alpha_scaling, end) && - pull8(ppReadPackedMsg, &pusch_pdu->pusch_uci.beta_offset_harq_ack, end) && - pull8(ppReadPackedMsg, &pusch_pdu->pusch_uci.beta_offset_csi1, end) && - pull8(ppReadPackedMsg, &pusch_pdu->pusch_uci.beta_offset_csi2, end) - ); - } - break; - - case PUSCH_PDU_BITMAP_PUSCH_PTRS: - { - return( - pull8(ppReadPackedMsg, &pusch_pdu->pusch_ptrs.num_ptrs_ports, end) && - pull8(ppReadPackedMsg, &pusch_pdu->pusch_ptrs.ptrs_ports_list->ptrs_dmrs_port, end) && -+ pull16(ppReadPackedMsg, &pusch_pdu->pusch_ptrs.ptrs_ports_list->ptrs_port_index, end) && -+ pull8(ppReadPackedMsg, &pusch_pdu->pusch_ptrs.ptrs_ports_list->ptrs_re_offset, end) && - pull8(ppReadPackedMsg, &pusch_pdu->pusch_ptrs.ptrs_time_density, end) && - pull8(ppReadPackedMsg, &pusch_pdu->pusch_ptrs.ptrs_freq_density, end) && - pull8(ppReadPackedMsg, &pusch_pdu->pusch_ptrs.ul_ptrs_power, end) - ); - } - break; - - case PUSCH_PDU_BITMAP_DFTS_OFDM: - { - return( - pull8(ppReadPackedMsg, &pusch_pdu->dfts_ofdm.low_papr_group_number, end) && - pull16(ppReadPackedMsg, &pusch_pdu->dfts_ofdm.low_papr_sequence_number, end) && - pull8(ppReadPackedMsg, &pusch_pdu->dfts_ofdm.ul_ptrs_sample_density, end) && - pull8(ppReadPackedMsg, &pusch_pdu->dfts_ofdm.ul_ptrs_time_density_transform_precoding, end) - ); - } - break; - - default: - { - NFAPI_TRACE(NFAPI_TRACE_INFO, "Invalid pdu bitmap %d \n", pusch_pdu->pdu_bit_map ); - } - } - - return 1; -} - - -static uint8_t unpack_ul_tti_request_srs_pdu(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_nr_srs_pdu_t* srs_pdu = (nfapi_nr_srs_pdu_t*)tlv; - - return( - pull16(ppReadPackedMsg, &srs_pdu->rnti, end) && - pull32(ppReadPackedMsg, &srs_pdu->handle, end) && - pull16(ppReadPackedMsg, &srs_pdu->bwp_size, end) && - pull16(ppReadPackedMsg, &srs_pdu->bwp_start, end) && - pull8(ppReadPackedMsg, &srs_pdu->subcarrier_spacing, end) && - pull8(ppReadPackedMsg, &srs_pdu->cyclic_prefix, end) && - pull8(ppReadPackedMsg, &srs_pdu->num_ant_ports, end) && - pull8(ppReadPackedMsg, &srs_pdu->num_symbols, end) && - pull8(ppReadPackedMsg, &srs_pdu->num_repetitions, end) && - pull8(ppReadPackedMsg, &srs_pdu->time_start_position, end) && - pull8(ppReadPackedMsg, &srs_pdu->config_index, end) && - pull16(ppReadPackedMsg, &srs_pdu->sequence_id, end) && - pull8(ppReadPackedMsg, &srs_pdu->bandwidth_index, end) && - pull8(ppReadPackedMsg, &srs_pdu->comb_size, end) && - pull8(ppReadPackedMsg, &srs_pdu->comb_offset, end) && - pull8(ppReadPackedMsg, &srs_pdu->cyclic_shift, end) && - pull8(ppReadPackedMsg, &srs_pdu->frequency_position, end) && - pull8(ppReadPackedMsg, &srs_pdu->frequency_shift, end) && - pull8(ppReadPackedMsg, &srs_pdu->frequency_hopping, end) && - pull8(ppReadPackedMsg, &srs_pdu->group_or_sequence_hopping, end) && - pull8(ppReadPackedMsg, &srs_pdu->resource_type, end) && - pull16(ppReadPackedMsg, &srs_pdu->t_srs, end) && - pull16(ppReadPackedMsg, &srs_pdu->t_offset, end) - // TODO: ignoring beamforming tlv for now - ); -} - - -static uint8_t unpack_ul_tti_pdu_list_value(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg) -{ - nfapi_nr_ul_tti_request_number_of_pdus_t* pNfapiMsg = (nfapi_nr_ul_tti_request_number_of_pdus_t*)msg; - - if(!(pull16(ppReadPackedMsg, &pNfapiMsg->pdu_size, end) && - pull16(ppReadPackedMsg, &pNfapiMsg->pdu_type, end) )) - return 0; - - - // first natch the pdu type, then call the respective function - switch(pNfapiMsg->pdu_type) - { - - case NFAPI_NR_UL_CONFIG_PRACH_PDU_TYPE: - { - if(!unpack_ul_tti_request_prach_pdu(&pNfapiMsg->prach_pdu, ppReadPackedMsg, end)) - return 0; - } - break; - - case NFAPI_NR_UL_CONFIG_PUCCH_PDU_TYPE: - { - if(!unpack_ul_tti_request_pucch_pdu(&pNfapiMsg->pucch_pdu, ppReadPackedMsg, end)) - return 0; - } - break; - - case NFAPI_NR_UL_CONFIG_PUSCH_PDU_TYPE: - { - if(!unpack_ul_tti_request_pusch_pdu(&pNfapiMsg->pusch_pdu, ppReadPackedMsg, end)) - return 0; - } - break; - - case NFAPI_NR_UL_CONFIG_SRS_PDU_TYPE: - { - if(!unpack_ul_tti_request_srs_pdu(&pNfapiMsg->srs_pdu, ppReadPackedMsg, end)) - return 0; - } - break; - - default: - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "FIXME : Invalid UL_TTI pdu type %d \n", pNfapiMsg->pdu_type ); - } - break; - - - } - - return 1; -} - - -static uint8_t unpack_ul_tti_groups_list_value(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg) -{ - nfapi_nr_ul_tti_request_number_of_groups_t* pNfapiMsg = (nfapi_nr_ul_tti_request_number_of_groups_t*)msg; - - if(!pull8(ppReadPackedMsg, &pNfapiMsg->n_ue, end)) + if(!(pull8(ppReadPackedMsg, &subband_info->subband_index, end) && + pull8(ppReadPackedMsg, &subband_info->scheduled_ues, end))) return 0; - for (int i = 0; i < pNfapiMsg->n_ue; i++) - { - if(!pull8(ppReadPackedMsg, &pNfapiMsg->ue_list[i].pdu_idx ,end) ) - return 0; - } - return 1; + + uint8_t antenna_idx = 0; + uint8_t scheduled_ue_idx = 0; + + for(antenna_idx = 0; antenna_idx < value->num_antennas; ++antenna_idx) { + for(scheduled_ue_idx = 0; scheduled_ue_idx < subband_info->scheduled_ues; ++scheduled_ue_idx) { + if(!pull16(ppReadPackedMsg, &(subband_info->precoding_value[antenna_idx][scheduled_ue_idx]), end)) + return 0; + } + } + } + + return 1; } -static uint8_t unpack_ul_tti_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config) -{ - nfapi_nr_ul_tti_request_t *pNfapiMsg = (nfapi_nr_ul_tti_request_t*)msg; +static uint8_t unpack_dl_config_dci_dl_pdu_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_dl_config_dci_dl_pdu_rel13_t *dci_dl_pdu_rel13 = (nfapi_dl_config_dci_dl_pdu_rel13_t *)tlv; + // If the length is greater than 5 then the TPM struct flag and possiably the TPM structure have been + // added + uint8_t tpm_struct_flag_present = dci_dl_pdu_rel13->tl.length > 5; + dci_dl_pdu_rel13->tpm_struct_flag = 0; + return (pull8(ppReadPackedMsg, &dci_dl_pdu_rel13->laa_end_partial_sf_flag, end) && + pull8(ppReadPackedMsg, &dci_dl_pdu_rel13->laa_end_partial_sf_configuration, end) && + pull8(ppReadPackedMsg, &dci_dl_pdu_rel13->initial_lbt_sf, end) && + pull8(ppReadPackedMsg, &dci_dl_pdu_rel13->codebook_size_determination, end) && + pull8(ppReadPackedMsg, &dci_dl_pdu_rel13->drms_table_flag, end) && + ( (tpm_struct_flag_present == 1) ? pull8(ppReadPackedMsg, &dci_dl_pdu_rel13->tpm_struct_flag, end) : 1) && + ( (tpm_struct_flag_present == 1 && dci_dl_pdu_rel13->tpm_struct_flag == 1) ? unpack_tpm_value(ppReadPackedMsg, &dci_dl_pdu_rel13->tpm, end) : 1)); +} - if (!( - pull16(ppReadPackedMsg, &pNfapiMsg->SFN, end) && - pull16(ppReadPackedMsg, &pNfapiMsg->Slot, end) && - pull8(ppReadPackedMsg, &pNfapiMsg->n_pdus, end) && - pull8(ppReadPackedMsg, &pNfapiMsg->n_group, end) && - pull8(ppReadPackedMsg, &pNfapiMsg->rach_present, end) && - pull8(ppReadPackedMsg, &pNfapiMsg->n_ulcch, end) && - pull8(ppReadPackedMsg, &pNfapiMsg->n_ulsch, end) )) - return 0; +static uint8_t unpack_dl_config_bch_pdu_rel8_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_dl_config_bch_pdu_rel8_t *bch_pdu_rel8 = (nfapi_dl_config_bch_pdu_rel8_t *)tlv; + return ( pull16(ppReadPackedMsg, &bch_pdu_rel8->length, end) && + pull16(ppReadPackedMsg, (uint16_t *)&bch_pdu_rel8->pdu_index, end) && + pull16(ppReadPackedMsg, &bch_pdu_rel8->transmission_power, end)); +} - for(int i=0; i< pNfapiMsg->n_pdus; i++) - { - if (!unpack_ul_tti_pdu_list_value(ppReadPackedMsg, end, &pNfapiMsg->pdus_list[i])) - return 0; - } +static uint8_t unpack_dl_config_mch_pdu_rel8_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_dl_config_mch_pdu_rel8_t *mch_pdu_rel8 = (nfapi_dl_config_mch_pdu_rel8_t *)tlv; + return (pull16(ppReadPackedMsg, &mch_pdu_rel8->length, end) && + pull16(ppReadPackedMsg, (uint16_t *)&mch_pdu_rel8->pdu_index, end) && + pull16(ppReadPackedMsg, &mch_pdu_rel8->rnti, end) && + pull8(ppReadPackedMsg, &mch_pdu_rel8->resource_allocation_type, end) && + pull32(ppReadPackedMsg, &mch_pdu_rel8->resource_block_coding, end) && + pull8(ppReadPackedMsg, &mch_pdu_rel8->modulation, end) && + pull16(ppReadPackedMsg, &mch_pdu_rel8->transmission_power, end) && + pull16(ppReadPackedMsg, &mch_pdu_rel8->mbsfn_area_id, end)); +} - for(int i=0; i< pNfapiMsg->n_group; i++) - { - if (!unpack_ul_tti_groups_list_value(ppReadPackedMsg, end, &pNfapiMsg->groups_list[i])) - return 0; - } +static uint8_t unpack_dl_config_dlsch_pdu_rel8_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_dl_config_dlsch_pdu_rel8_t *dlsch_pdu_rel8 = (nfapi_dl_config_dlsch_pdu_rel8_t *)tlv; - return 1; + if (!(pull16(ppReadPackedMsg, &dlsch_pdu_rel8->length, end) && + pull16(ppReadPackedMsg, (uint16_t *)&dlsch_pdu_rel8->pdu_index, end) && + pull16(ppReadPackedMsg, &dlsch_pdu_rel8->rnti, end) && + pull8(ppReadPackedMsg, &dlsch_pdu_rel8->resource_allocation_type, end) && + pull8(ppReadPackedMsg, &dlsch_pdu_rel8->virtual_resource_block_assignment_flag, end) && + pull32(ppReadPackedMsg, &dlsch_pdu_rel8->resource_block_coding, end) && + pull8(ppReadPackedMsg, &dlsch_pdu_rel8->modulation, end) && + pull8(ppReadPackedMsg, &dlsch_pdu_rel8->redundancy_version, end) && + pull8(ppReadPackedMsg, &dlsch_pdu_rel8->transport_blocks, end) && + pull8(ppReadPackedMsg, &dlsch_pdu_rel8->transport_block_to_codeword_swap_flag, end) && + pull8(ppReadPackedMsg, &dlsch_pdu_rel8->transmission_scheme, end) && + pull8(ppReadPackedMsg, &dlsch_pdu_rel8->number_of_layers, end) && + pull8(ppReadPackedMsg, &dlsch_pdu_rel8->number_of_subbands, end) && + pullarray8(ppReadPackedMsg, dlsch_pdu_rel8->codebook_index, NFAPI_MAX_NUM_SUBBANDS, dlsch_pdu_rel8->number_of_subbands, end) && + pull8(ppReadPackedMsg, &dlsch_pdu_rel8->ue_category_capacity, end) && + pull8(ppReadPackedMsg, &dlsch_pdu_rel8->pa, end) && + pull8(ppReadPackedMsg, &dlsch_pdu_rel8->delta_power_offset_index, end) && + pull8(ppReadPackedMsg, &dlsch_pdu_rel8->ngap, end) && + pull8(ppReadPackedMsg, &dlsch_pdu_rel8->nprb, end) && + pull8(ppReadPackedMsg, &dlsch_pdu_rel8->transmission_mode, end) && + pull8(ppReadPackedMsg, &dlsch_pdu_rel8->num_bf_prb_per_subband, end) && + pull8(ppReadPackedMsg, &dlsch_pdu_rel8->num_bf_vector, end))) + return 0; + + uint16_t j = 0; + + for(j = 0; j < dlsch_pdu_rel8->num_bf_vector; ++j) { + if(!(pull8(ppReadPackedMsg, &dlsch_pdu_rel8->bf_vector[j].subband_index, end) && + pull8(ppReadPackedMsg, &dlsch_pdu_rel8->bf_vector[j].num_antennas, end) && + pullarray16(ppReadPackedMsg, dlsch_pdu_rel8->bf_vector[j].bf_value, NFAPI_MAX_NUM_ANTENNAS, dlsch_pdu_rel8->bf_vector[j].num_antennas, end))) + return 0; + } + + return 1; +} +static uint8_t unpack_dl_config_dlsch_pdu_rel9_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_dl_config_dlsch_pdu_rel9_t *dlsch_pdu_rel9 = (nfapi_dl_config_dlsch_pdu_rel9_t *)tlv; + return ( pull8(ppReadPackedMsg, &dlsch_pdu_rel9->nscid, end) ); +} +static uint8_t unpack_dl_config_dlsch_pdu_rel10_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_dl_config_dlsch_pdu_rel10_t *dlsch_pdu_rel10 = (nfapi_dl_config_dlsch_pdu_rel10_t *)tlv; + return ( pull8(ppReadPackedMsg, &dlsch_pdu_rel10->csi_rs_flag, end) && + pull8(ppReadPackedMsg, &dlsch_pdu_rel10->csi_rs_resource_config_r10, end) && + pull16(ppReadPackedMsg, &dlsch_pdu_rel10->csi_rs_zero_tx_power_resource_config_bitmap_r10, end) && + pull8(ppReadPackedMsg, &dlsch_pdu_rel10->csi_rs_number_nzp_configuration, end) && + pullarray8(ppReadPackedMsg, dlsch_pdu_rel10->csi_rs_resource_config, NFAPI_MAX_CSI_RS_RESOURCE_CONFIG, dlsch_pdu_rel10->csi_rs_number_nzp_configuration, end) && + pull8(ppReadPackedMsg, &dlsch_pdu_rel10->pdsch_start, end)) ; +} +static uint8_t unpack_dl_config_dlsch_pdu_rel11_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_dl_config_dlsch_pdu_rel11_t *dlsch_pdu_rel11 = (nfapi_dl_config_dlsch_pdu_rel11_t *)tlv; + return ( pull8(ppReadPackedMsg, &dlsch_pdu_rel11->drms_config_flag, end) && + pull16(ppReadPackedMsg, &dlsch_pdu_rel11->drms_scrambling, end) && + pull8(ppReadPackedMsg, &dlsch_pdu_rel11->csi_config_flag, end) && + pull16(ppReadPackedMsg, &dlsch_pdu_rel11->csi_scrambling, end) && + pull8(ppReadPackedMsg, &dlsch_pdu_rel11->pdsch_re_mapping_flag, end) && + pull8(ppReadPackedMsg, &dlsch_pdu_rel11->pdsch_re_mapping_atenna_ports, end) && + pull8(ppReadPackedMsg, &dlsch_pdu_rel11->pdsch_re_mapping_freq_shift, end)); +} +static uint8_t unpack_dl_config_dlsch_pdu_rel12_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_dl_config_dlsch_pdu_rel12_t *dlsch_pdu_rel12 = (nfapi_dl_config_dlsch_pdu_rel12_t *)tlv; + return ( pull8(ppReadPackedMsg, &dlsch_pdu_rel12->altcqi_table_r12, end) && + pull8(ppReadPackedMsg, &dlsch_pdu_rel12->maxlayers, end) && + pull8(ppReadPackedMsg, &dlsch_pdu_rel12->n_dl_harq, end)); +} +static uint8_t unpack_dl_config_dlsch_pdu_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_dl_config_dlsch_pdu_rel13_t *dlsch_pdu_rel13 = (nfapi_dl_config_dlsch_pdu_rel13_t *)tlv; + return ( pull8(ppReadPackedMsg, &dlsch_pdu_rel13->dwpts_symbols, end) && + pull8(ppReadPackedMsg, &dlsch_pdu_rel13->initial_lbt_sf, end) && + pull8(ppReadPackedMsg, &dlsch_pdu_rel13->ue_type, end) && + pull8(ppReadPackedMsg, &dlsch_pdu_rel13->pdsch_payload_type, end) && + pull16(ppReadPackedMsg, &dlsch_pdu_rel13->initial_transmission_sf_io, end) && + pull8(ppReadPackedMsg, &dlsch_pdu_rel13->drms_table_flag, end)); +} + +static uint8_t unpack_dl_config_pch_pdu_rel8_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_dl_config_pch_pdu_rel8_t *pch_pdu_rel8 = (nfapi_dl_config_pch_pdu_rel8_t *)tlv; + return ( pull16(ppReadPackedMsg, &pch_pdu_rel8->length, end) && + pull16(ppReadPackedMsg, (uint16_t *)&pch_pdu_rel8->pdu_index, end) && + pull16(ppReadPackedMsg, &pch_pdu_rel8->p_rnti, end) && + pull8(ppReadPackedMsg, &pch_pdu_rel8->resource_allocation_type, end) && + pull8(ppReadPackedMsg, &pch_pdu_rel8->virtual_resource_block_assignment_flag, end) && + pull32(ppReadPackedMsg, &pch_pdu_rel8->resource_block_coding, end) && + pull8(ppReadPackedMsg, &pch_pdu_rel8->mcs, end) && + pull8(ppReadPackedMsg, &pch_pdu_rel8->redundancy_version, end) && + pull8(ppReadPackedMsg, &pch_pdu_rel8->number_of_transport_blocks, end) && + pull8(ppReadPackedMsg, &pch_pdu_rel8->transport_block_to_codeword_swap_flag, end) && + pull8(ppReadPackedMsg, &pch_pdu_rel8->transmission_scheme, end) && + pull8(ppReadPackedMsg, &pch_pdu_rel8->number_of_layers, end) && + pull8(ppReadPackedMsg, &pch_pdu_rel8->codebook_index, end) && + pull8(ppReadPackedMsg, &pch_pdu_rel8->ue_category_capacity, end) && + pull8(ppReadPackedMsg, &pch_pdu_rel8->pa, end) && + pull16(ppReadPackedMsg, &pch_pdu_rel8->transmission_power, end) && + pull8(ppReadPackedMsg, &pch_pdu_rel8->nprb, end) && + pull8(ppReadPackedMsg, &pch_pdu_rel8->ngap, end)); +} +static uint8_t unpack_dl_config_pch_pdu_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_dl_config_pch_pdu_rel13_t *pch_pdu_rel13 = (nfapi_dl_config_pch_pdu_rel13_t *)tlv; + return ( pull8(ppReadPackedMsg, &pch_pdu_rel13->ue_mode, end) && + pull16(ppReadPackedMsg, &pch_pdu_rel13->initial_transmission_sf_io, end)); +} + +static uint8_t unpack_dl_config_prs_pdu_rel9_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_dl_config_prs_pdu_rel9_t *prs_pdu_rel9 = (nfapi_dl_config_prs_pdu_rel9_t *)tlv; + return ( pull16(ppReadPackedMsg, &prs_pdu_rel9->transmission_power, end) && + pull8(ppReadPackedMsg, &prs_pdu_rel9->prs_bandwidth, end) && + pull8(ppReadPackedMsg, &prs_pdu_rel9->prs_cyclic_prefix_type, end) && + pull8(ppReadPackedMsg, &prs_pdu_rel9->prs_muting, end)); +} + +static uint8_t unpack_dl_config_csi_rs_pdu_rel10_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_dl_config_csi_rs_pdu_rel10_t *csi_rs_pdu_rel10 = (nfapi_dl_config_csi_rs_pdu_rel10_t *)tlv; + return ( pull8(ppReadPackedMsg, &csi_rs_pdu_rel10->csi_rs_antenna_port_count_r10, end) && + pull8(ppReadPackedMsg, &csi_rs_pdu_rel10->csi_rs_resource_config_r10, end) && + pull16(ppReadPackedMsg, &csi_rs_pdu_rel10->transmission_power, end) && + pull16(ppReadPackedMsg, &csi_rs_pdu_rel10->csi_rs_zero_tx_power_resource_config_bitmap_r10, end) && + pull8(ppReadPackedMsg, &csi_rs_pdu_rel10->csi_rs_number_of_nzp_configuration, end) && + pullarray8(ppReadPackedMsg, csi_rs_pdu_rel10->csi_rs_resource_config, NFAPI_MAX_CSI_RS_RESOURCE_CONFIG, csi_rs_pdu_rel10->csi_rs_number_of_nzp_configuration, end)); +} + +static uint8_t unpack_dl_config_csi_rs_pdu_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_dl_config_csi_rs_pdu_rel13_t *csi_rs_pdu_rel13 = (nfapi_dl_config_csi_rs_pdu_rel13_t *)tlv; + + if (!(pull8(ppReadPackedMsg, &csi_rs_pdu_rel13->csi_rs_class, end) && + pull8(ppReadPackedMsg, &csi_rs_pdu_rel13->cdm_type, end) && + pull8(ppReadPackedMsg, &csi_rs_pdu_rel13->num_bf_vector, end))) + return 0; + + uint16_t idx =0; + + for(idx = 0; idx < csi_rs_pdu_rel13->num_bf_vector; ++idx) { + if(!(pull8(ppReadPackedMsg, &csi_rs_pdu_rel13->bf_vector[idx].csi_rs_resource_index, end))) + return 0; + + NFAPI_TRACE(NFAPI_TRACE_ERROR, "FIXME : HOW TO DECODE BF VALUE \n"); + //pullarray16(ppReadPackedMsg, &csi_rs_pdu_rel13->bf_vector[idx].bf_vector, ??); + } + + return 1; +} + +static uint8_t unpack_dl_config_epdcch_params_rel11_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_dl_config_epdcch_parameters_rel11_t *epdcch_params_rel11 = (nfapi_dl_config_epdcch_parameters_rel11_t *)tlv; + return (pull8(ppReadPackedMsg, &epdcch_params_rel11->epdcch_resource_assignment_flag, end) && + pull16(ppReadPackedMsg, &epdcch_params_rel11->epdcch_id, end) && + pull8(ppReadPackedMsg, &epdcch_params_rel11->epdcch_start_symbol, end) && + pull8(ppReadPackedMsg, &epdcch_params_rel11->epdcch_num_prb, end) && + pullarray8(ppReadPackedMsg, epdcch_params_rel11->epdcch_prb_index, NFAPI_MAX_EPDCCH_PRB, epdcch_params_rel11->epdcch_num_prb, end) && + pull8(ppReadPackedMsg, &epdcch_params_rel11->bf_vector.subband_index, end) && + pull8(ppReadPackedMsg, &epdcch_params_rel11->bf_vector.num_antennas, end) && + pullarray16(ppReadPackedMsg, epdcch_params_rel11->bf_vector.bf_value, NFAPI_MAX_NUM_ANTENNAS, epdcch_params_rel11->bf_vector.num_antennas, end)); +} + +static uint8_t unpack_dl_config_epdcch_params_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_dl_config_epdcch_parameters_rel13_t *epdcch_params_rel13 = (nfapi_dl_config_epdcch_parameters_rel13_t *)tlv; + return ( pull8(ppReadPackedMsg, &epdcch_params_rel13->dwpts_symbols, end) && + pull8(ppReadPackedMsg, &epdcch_params_rel13->initial_lbt_sf, end)); +} + +static uint8_t unpack_dl_config_mpdcch_pdu_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_dl_config_mpdcch_pdu_rel13_t *mpdcch_params_rel13 = (nfapi_dl_config_mpdcch_pdu_rel13_t *)tlv; + return ( pull8(ppReadPackedMsg, &mpdcch_params_rel13->mpdcch_narrow_band, end) && + pull8(ppReadPackedMsg, &mpdcch_params_rel13->number_of_prb_pairs, end) && + pull8(ppReadPackedMsg, &mpdcch_params_rel13->resource_block_assignment, end) && + pull8(ppReadPackedMsg, &mpdcch_params_rel13->mpdcch_tansmission_type, end) && + pull8(ppReadPackedMsg, &mpdcch_params_rel13->start_symbol, end) && + pull8(ppReadPackedMsg, &mpdcch_params_rel13->ecce_index, end) && + pull8(ppReadPackedMsg, &mpdcch_params_rel13->aggregation_level, end) && + pull8(ppReadPackedMsg, &mpdcch_params_rel13->rnti_type, end) && + pull16(ppReadPackedMsg, &mpdcch_params_rel13->rnti, end) && + pull8(ppReadPackedMsg, &mpdcch_params_rel13->ce_mode, end) && + pull16(ppReadPackedMsg, &mpdcch_params_rel13->drms_scrambling_init, end) && + pull16(ppReadPackedMsg, &mpdcch_params_rel13->initial_transmission_sf_io, end) && + pull16(ppReadPackedMsg, &mpdcch_params_rel13->transmission_power, end) && + pull8(ppReadPackedMsg, &mpdcch_params_rel13->dci_format, end) && + pull16(ppReadPackedMsg, &mpdcch_params_rel13->resource_block_coding, end) && + pull8(ppReadPackedMsg, &mpdcch_params_rel13->mcs, end) && + pull8(ppReadPackedMsg, &mpdcch_params_rel13->pdsch_reptition_levels, end) && + pull8(ppReadPackedMsg, &mpdcch_params_rel13->redundancy_version, end) && + pull8(ppReadPackedMsg, &mpdcch_params_rel13->new_data_indicator, end) && + pull8(ppReadPackedMsg, &mpdcch_params_rel13->harq_process, end) && + pull8(ppReadPackedMsg, &mpdcch_params_rel13->tpmi_length, end) && + pull8(ppReadPackedMsg, &mpdcch_params_rel13->tpmi, end) && + pull8(ppReadPackedMsg, &mpdcch_params_rel13->pmi_flag, end) && + pull8(ppReadPackedMsg, &mpdcch_params_rel13->pmi, end) && + pull8(ppReadPackedMsg, &mpdcch_params_rel13->harq_resource_offset, end) && + pull8(ppReadPackedMsg, &mpdcch_params_rel13->dci_subframe_repetition_number, end) && + pull8(ppReadPackedMsg, &mpdcch_params_rel13->tpc, end) && + pull8(ppReadPackedMsg, &mpdcch_params_rel13->downlink_assignment_index_length, end) && + pull8(ppReadPackedMsg, &mpdcch_params_rel13->downlink_assignment_index, end) && + pull8(ppReadPackedMsg, &mpdcch_params_rel13->allocate_prach_flag, end) && + pull8(ppReadPackedMsg, &mpdcch_params_rel13->preamble_index, end) && + pull8(ppReadPackedMsg, &mpdcch_params_rel13->prach_mask_index, end) && + pull8(ppReadPackedMsg, &mpdcch_params_rel13->starting_ce_level, end) && + pull8(ppReadPackedMsg, &mpdcch_params_rel13->srs_request, end) && + pull8(ppReadPackedMsg, &mpdcch_params_rel13->antenna_ports_and_scrambling_identity_flag, end) && + pull8(ppReadPackedMsg, &mpdcch_params_rel13->antenna_ports_and_scrambling_identity, end) && + pull8(ppReadPackedMsg, &mpdcch_params_rel13->frequency_hopping_enabled_flag, end) && + pull8(ppReadPackedMsg, &mpdcch_params_rel13->paging_direct_indication_differentiation_flag, end) && + pull8(ppReadPackedMsg, &mpdcch_params_rel13->direct_indication, end) && + pull8(ppReadPackedMsg, &mpdcch_params_rel13->total_dci_length_including_padding, end) && + pull8(ppReadPackedMsg, &mpdcch_params_rel13->number_of_tx_antenna_ports, end) && + pullarray16(ppReadPackedMsg, mpdcch_params_rel13->precoding_value, NFAPI_MAX_TX_PHYSICAL_ANTENNA_PORTS, mpdcch_params_rel13->number_of_tx_antenna_ports, end)); +} + + +static uint8_t unpack_dl_config_nbch_pdu_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_dl_config_nbch_pdu_rel13_t *nbch_params_rel13 = (nfapi_dl_config_nbch_pdu_rel13_t *)tlv; + return ( pull16(ppReadPackedMsg, &nbch_params_rel13->length, end) && + pull16(ppReadPackedMsg, (uint16_t *)&nbch_params_rel13->pdu_index, end) && + pull16(ppReadPackedMsg, &nbch_params_rel13->transmission_power, end) && + pull16(ppReadPackedMsg, &nbch_params_rel13->hyper_sfn_2_lsbs, end)); +} + +static uint8_t unpack_dl_config_npdcch_pdu_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_dl_config_npdcch_pdu_rel13_t *npdcch_params_rel13 = (nfapi_dl_config_npdcch_pdu_rel13_t *)tlv; + return ( pull16(ppReadPackedMsg, &npdcch_params_rel13->length, end) && + pull16(ppReadPackedMsg, (uint16_t *)&npdcch_params_rel13->pdu_index, end) && + pull8(ppReadPackedMsg, &npdcch_params_rel13->ncce_index, end) && + pull8(ppReadPackedMsg, &npdcch_params_rel13->aggregation_level, end) && + pull8(ppReadPackedMsg, &npdcch_params_rel13->start_symbol, end) && + pull8(ppReadPackedMsg, &npdcch_params_rel13->rnti_type, end) && + pull16(ppReadPackedMsg, &npdcch_params_rel13->rnti, end) && + pull8(ppReadPackedMsg, &npdcch_params_rel13->scrambling_reinitialization_batch_index, end) && + pull8(ppReadPackedMsg, &npdcch_params_rel13->nrs_antenna_ports_assumed_by_the_ue, end) && + pull8(ppReadPackedMsg, &npdcch_params_rel13->dci_format, end) && + pull8(ppReadPackedMsg, &npdcch_params_rel13->scheduling_delay, end) && + pull8(ppReadPackedMsg, &npdcch_params_rel13->resource_assignment, end) && + pull8(ppReadPackedMsg, &npdcch_params_rel13->repetition_number, end) && + pull8(ppReadPackedMsg, &npdcch_params_rel13->mcs, end) && + pull8(ppReadPackedMsg, &npdcch_params_rel13->new_data_indicator, end) && + pull8(ppReadPackedMsg, &npdcch_params_rel13->harq_ack_resource, end) && + pull8(ppReadPackedMsg, &npdcch_params_rel13->npdcch_order_indication, end) && + pull8(ppReadPackedMsg, &npdcch_params_rel13->starting_number_of_nprach_repetitions, end) && + pull8(ppReadPackedMsg, &npdcch_params_rel13->subcarrier_indication_of_nprach, end) && + pull8(ppReadPackedMsg, &npdcch_params_rel13->paging_direct_indication_differentation_flag, end) && + pull8(ppReadPackedMsg, &npdcch_params_rel13->direct_indication, end) && + pull8(ppReadPackedMsg, &npdcch_params_rel13->dci_subframe_repetition_number, end) && + pull8(ppReadPackedMsg, &npdcch_params_rel13->total_dci_length_including_padding, end)); +} + +static uint8_t unpack_dl_config_ndlsch_pdu_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_dl_config_ndlsch_pdu_rel13_t *ndlsch_params_rel13 = (nfapi_dl_config_ndlsch_pdu_rel13_t *)tlv; + return ( pull16(ppReadPackedMsg, &ndlsch_params_rel13->length, end) && + pull16(ppReadPackedMsg, (uint16_t *)&ndlsch_params_rel13->pdu_index, end) && + pull8(ppReadPackedMsg, &ndlsch_params_rel13->start_symbol, end) && + pull8(ppReadPackedMsg, &ndlsch_params_rel13->rnti_type, end) && + pull16(ppReadPackedMsg, &ndlsch_params_rel13->rnti, end) && + pull16(ppReadPackedMsg, &ndlsch_params_rel13->resource_assignment, end) && + pull16(ppReadPackedMsg, &ndlsch_params_rel13->repetition_number, end) && + pull8(ppReadPackedMsg, &ndlsch_params_rel13->modulation, end) && + pull8(ppReadPackedMsg, &ndlsch_params_rel13->number_of_subframes_for_resource_assignment, end) && + pull8(ppReadPackedMsg, &ndlsch_params_rel13->scrambling_sequence_initialization_cinit, end) && + pull16(ppReadPackedMsg, &ndlsch_params_rel13->sf_idx, end) && + pull8(ppReadPackedMsg, &ndlsch_params_rel13->nrs_antenna_ports_assumed_by_the_ue, end)); +} + + +static uint8_t unpack_dl_tti_request_body_value(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg) { + nfapi_nr_dl_tti_request_pdu_t *value = (nfapi_nr_dl_tti_request_pdu_t *)msg; + + if(!(pull32(ppReadPackedMsg, &value->PDUSize, end) && + pull16(ppReadPackedMsg, &value->PDUType, end) )) + return 0; + + // first match the pdu type, then call the respective function + switch(value->PDUType) { + case NFAPI_NR_DL_TTI_CSI_RS_PDU_TYPE: { + if(!(unpack_dl_tti_csi_rs_pdu_rel15_value(&value->csi_rs_pdu.csi_rs_pdu_rel15,ppReadPackedMsg,end))) + return 0; + } + break; + + case NFAPI_NR_DL_TTI_PDCCH_PDU_TYPE: { + if(!(unpack_dl_tti_pdcch_pdu_rel15_value(&value->pdcch_pdu.pdcch_pdu_rel15,ppReadPackedMsg,end))) + return 0; + } + break; + + case NFAPI_NR_DL_TTI_PDSCH_PDU_TYPE: { + if(!(unpack_dl_tti_pdsch_pdu_rel15_value(&value->pdsch_pdu.pdsch_pdu_rel15,ppReadPackedMsg,end))) + return 0; + } + break; + + case NFAPI_NR_DL_TTI_SSB_PDU_TYPE: { + if(!(unpack_dl_tti_ssb_pdu_rel15_value(&value->ssb_pdu.ssb_pdu_rel15,ppReadPackedMsg,end))) + return 0; + } + break; + + default: { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "FIXME : Invalid DL_TTI pdu type %d \n", value->PDUType ); + } + break; + } + + return 1; } -static uint8_t unpack_dl_config_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config) -{ - nfapi_dl_config_request_t *pNfapiMsg = (nfapi_dl_config_request_t*)msg; - unpack_p7_tlv_t unpack_fns[] = - { - { NFAPI_DL_CONFIG_REQUEST_BODY_TAG, &pNfapiMsg->dl_config_request_body, &unpack_dl_config_request_body_value}, - }; +static uint8_t unpack_dl_config_request_body_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end, nfapi_p7_codec_config_t *config) { + nfapi_dl_config_request_body_t *value = (nfapi_dl_config_request_body_t *)tlv; - return ( pull16(ppReadPackedMsg, &pNfapiMsg->sfn_sf, end) && - unpack_p7_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); + if(!(pull8(ppReadPackedMsg, &value->number_pdcch_ofdm_symbols, end) && + pull8(ppReadPackedMsg, &value->number_dci, end) && + pull16(ppReadPackedMsg, &value->number_pdu, end) && + pull8(ppReadPackedMsg, &value->number_pdsch_rnti, end) && + pull16(ppReadPackedMsg, &value->transmission_power_pcfich, end))) + return 0; + + if(value->number_pdu > NFAPI_DL_CONFIG_MAX_PDU) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s number of dl config pdu's exceed maxium (count:%d max:%d)\n", __FUNCTION__, value->number_pdu, NFAPI_DL_CONFIG_MAX_PDU); + return 0; + } + + if(value->number_pdu) { + value->dl_config_pdu_list = (nfapi_dl_config_request_pdu_t *)nfapi_p7_allocate(sizeof(nfapi_dl_config_request_pdu_t) * value->number_pdu, config); + + if(value->dl_config_pdu_list == NULL) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s failed to allocate dl config pdu list (count:%d)\n", __FUNCTION__, value->number_pdu); + return 0; + } + } else { + value->dl_config_pdu_list = 0; + } + + uint16_t i; + uint16_t total_number_of_pdus = value->number_pdu; + + for(i = 0; i < total_number_of_pdus; ++i) { + nfapi_dl_config_request_pdu_t *pdu = &(value->dl_config_pdu_list[i]); + + if(!(pull8(ppReadPackedMsg, &pdu->pdu_type, end) && + pull8(ppReadPackedMsg, &pdu->pdu_size, end))) + return 0; + + uint8_t *packedPduEnd = (*ppReadPackedMsg) + pdu->pdu_size - 2; + + if(packedPduEnd > end) { + // pdu end of beyond buffer end + return 0; + } + + switch(pdu->pdu_type) { + case NFAPI_DL_CONFIG_DCI_DL_PDU_TYPE: { + unpack_tlv_t unpack_fns[] = { + { NFAPI_DL_CONFIG_REQUEST_DCI_DL_PDU_REL8_TAG, &pdu->dci_dl_pdu.dci_dl_pdu_rel8, &unpack_dl_config_dci_dl_pdu_rel8_value}, + { NFAPI_DL_CONFIG_REQUEST_DCI_DL_PDU_REL9_TAG, &pdu->dci_dl_pdu.dci_dl_pdu_rel9, &unpack_dl_config_dci_dl_pdu_rel9_value}, + { NFAPI_DL_CONFIG_REQUEST_DCI_DL_PDU_REL10_TAG, &pdu->dci_dl_pdu.dci_dl_pdu_rel10, &unpack_dl_config_dci_dl_pdu_rel10_value}, + { NFAPI_DL_CONFIG_REQUEST_DCI_DL_PDU_REL11_TAG, &pdu->dci_dl_pdu.dci_dl_pdu_rel11, &unpack_dl_config_dci_dl_pdu_rel11_value}, + { NFAPI_DL_CONFIG_REQUEST_DCI_DL_PDU_REL12_TAG, &pdu->dci_dl_pdu.dci_dl_pdu_rel12, &unpack_dl_config_dci_dl_pdu_rel12_value}, + { NFAPI_DL_CONFIG_REQUEST_DCI_DL_PDU_REL13_TAG, &pdu->dci_dl_pdu.dci_dl_pdu_rel13, &unpack_dl_config_dci_dl_pdu_rel13_value}, + }; + unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); + } + break; + + case NFAPI_DL_CONFIG_BCH_PDU_TYPE: { + unpack_tlv_t unpack_fns[] = { + { NFAPI_DL_CONFIG_REQUEST_BCH_PDU_REL8_TAG, &pdu->bch_pdu.bch_pdu_rel8, &unpack_dl_config_bch_pdu_rel8_value}, + }; + unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); + } + break; + + case NFAPI_DL_CONFIG_MCH_PDU_TYPE: { + unpack_tlv_t unpack_fns[] = { + { NFAPI_DL_CONFIG_REQUEST_MCH_PDU_REL8_TAG, &pdu->mch_pdu.mch_pdu_rel8, &unpack_dl_config_mch_pdu_rel8_value}, + }; + unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); + } + break; + + case NFAPI_DL_CONFIG_DLSCH_PDU_TYPE: { + unpack_tlv_t unpack_fns[] = { + { NFAPI_DL_CONFIG_REQUEST_DLSCH_PDU_REL8_TAG, &pdu->dlsch_pdu.dlsch_pdu_rel8, &unpack_dl_config_dlsch_pdu_rel8_value}, + { NFAPI_DL_CONFIG_REQUEST_DLSCH_PDU_REL9_TAG, &pdu->dlsch_pdu.dlsch_pdu_rel9, &unpack_dl_config_dlsch_pdu_rel9_value}, + { NFAPI_DL_CONFIG_REQUEST_DLSCH_PDU_REL10_TAG, &pdu->dlsch_pdu.dlsch_pdu_rel10, &unpack_dl_config_dlsch_pdu_rel10_value}, + { NFAPI_DL_CONFIG_REQUEST_DLSCH_PDU_REL11_TAG, &pdu->dlsch_pdu.dlsch_pdu_rel11, &unpack_dl_config_dlsch_pdu_rel11_value}, + { NFAPI_DL_CONFIG_REQUEST_DLSCH_PDU_REL12_TAG, &pdu->dlsch_pdu.dlsch_pdu_rel12, &unpack_dl_config_dlsch_pdu_rel12_value}, + { NFAPI_DL_CONFIG_REQUEST_DLSCH_PDU_REL13_TAG, &pdu->dlsch_pdu.dlsch_pdu_rel13, &unpack_dl_config_dlsch_pdu_rel13_value}, + }; + unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); + } + break; + + case NFAPI_DL_CONFIG_PCH_PDU_TYPE: { + unpack_tlv_t unpack_fns[] = { + { NFAPI_DL_CONFIG_REQUEST_PCH_PDU_REL8_TAG, &pdu->pch_pdu.pch_pdu_rel8, &unpack_dl_config_pch_pdu_rel8_value}, + { NFAPI_DL_CONFIG_REQUEST_PCH_PDU_REL13_TAG, &pdu->pch_pdu.pch_pdu_rel13, &unpack_dl_config_pch_pdu_rel13_value}, + }; + unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); + } + break; + + case NFAPI_DL_CONFIG_PRS_PDU_TYPE: { + unpack_tlv_t unpack_fns[] = { + { NFAPI_DL_CONFIG_REQUEST_PRS_PDU_REL9_TAG, &pdu->prs_pdu.prs_pdu_rel9, &unpack_dl_config_prs_pdu_rel9_value}, + }; + unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); + } + break; + + case NFAPI_DL_CONFIG_CSI_RS_PDU_TYPE: { + unpack_tlv_t unpack_fns[] = { + { NFAPI_DL_CONFIG_REQUEST_CSI_RS_PDU_REL10_TAG, &pdu->csi_rs_pdu.csi_rs_pdu_rel10, &unpack_dl_config_csi_rs_pdu_rel10_value}, + { NFAPI_DL_CONFIG_REQUEST_CSI_RS_PDU_REL13_TAG, &pdu->csi_rs_pdu.csi_rs_pdu_rel13, &unpack_dl_config_csi_rs_pdu_rel13_value}, + }; + unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); + } + break; + + case NFAPI_DL_CONFIG_EPDCCH_DL_PDU_TYPE: { + unpack_tlv_t unpack_fns[] = { + { NFAPI_DL_CONFIG_REQUEST_EPDCCH_PDU_REL8_TAG, &pdu->epdcch_pdu.epdcch_pdu_rel8, &unpack_dl_config_dci_dl_pdu_rel8_value}, + { NFAPI_DL_CONFIG_REQUEST_EPDCCH_PDU_REL9_TAG, &pdu->epdcch_pdu.epdcch_pdu_rel9, &unpack_dl_config_dci_dl_pdu_rel9_value}, + { NFAPI_DL_CONFIG_REQUEST_EPDCCH_PDU_REL10_TAG, &pdu->epdcch_pdu.epdcch_pdu_rel10, &unpack_dl_config_dci_dl_pdu_rel10_value}, + { NFAPI_DL_CONFIG_REQUEST_EPDCCH_PDU_REL11_TAG, &pdu->epdcch_pdu.epdcch_pdu_rel11, &unpack_dl_config_dci_dl_pdu_rel11_value}, + { NFAPI_DL_CONFIG_REQUEST_EPDCCH_PDU_REL12_TAG, &pdu->epdcch_pdu.epdcch_pdu_rel12, &unpack_dl_config_dci_dl_pdu_rel12_value}, + { NFAPI_DL_CONFIG_REQUEST_EPDCCH_PDU_REL13_TAG, &pdu->epdcch_pdu.epdcch_pdu_rel13, &unpack_dl_config_dci_dl_pdu_rel13_value}, + { NFAPI_DL_CONFIG_REQUEST_EPDCCH_PARAM_REL11_TAG, &pdu->epdcch_pdu.epdcch_params_rel11, &unpack_dl_config_epdcch_params_rel11_value}, + { NFAPI_DL_CONFIG_REQUEST_EPDCCH_PARAM_REL13_TAG, &pdu->epdcch_pdu.epdcch_params_rel13, &unpack_dl_config_epdcch_params_rel13_value}, + }; + unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); + } + break; + + case NFAPI_DL_CONFIG_MPDCCH_PDU_TYPE: { + unpack_tlv_t unpack_fns[] = { + { NFAPI_DL_CONFIG_REQUEST_MPDCCH_PDU_REL13_TAG, &pdu->mpdcch_pdu.mpdcch_pdu_rel13, &unpack_dl_config_mpdcch_pdu_rel13_value}, + }; + unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); + } + break; + + case NFAPI_DL_CONFIG_NBCH_PDU_TYPE: { + unpack_tlv_t unpack_fns[] = { + { NFAPI_DL_CONFIG_REQUEST_NBCH_PDU_REL13_TAG, &pdu->nbch_pdu.nbch_pdu_rel13, &unpack_dl_config_nbch_pdu_rel13_value}, + }; + unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); + } + break; + + case NFAPI_DL_CONFIG_NPDCCH_PDU_TYPE: { + unpack_tlv_t unpack_fns[] = { + { NFAPI_DL_CONFIG_REQUEST_NPDCCH_PDU_REL13_TAG, &pdu->npdcch_pdu.npdcch_pdu_rel13, &unpack_dl_config_npdcch_pdu_rel13_value}, + }; + unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); + } + break; + + case NFAPI_DL_CONFIG_NDLSCH_PDU_TYPE: { + unpack_tlv_t unpack_fns[] = { + { NFAPI_DL_CONFIG_REQUEST_NDLSCH_PDU_REL13_TAG, &pdu->ndlsch_pdu.ndlsch_pdu_rel13, &unpack_dl_config_ndlsch_pdu_rel13_value}, + }; + unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); + } + break; + + default: + // Need to log an error + break; + } + } + + return 1; } -static uint8_t unpack_ul_config_ulsch_pdu_rel8_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ +static uint8_t unpack_dl_tti_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t *config) { + nfapi_nr_dl_tti_request_t *pNfapiMsg = (nfapi_nr_dl_tti_request_t *)msg; - - nfapi_ul_config_ulsch_pdu_rel8_t* ulsch_pdu_rel8 = (nfapi_ul_config_ulsch_pdu_rel8_t*)tlv; - - return (pull32(ppReadPackedMsg, &ulsch_pdu_rel8->handle, end) && - pull16(ppReadPackedMsg, &ulsch_pdu_rel8->size, end) && - pull16(ppReadPackedMsg, &ulsch_pdu_rel8->rnti, end) && - pull8(ppReadPackedMsg, &ulsch_pdu_rel8->resource_block_start, end) && - pull8(ppReadPackedMsg, &ulsch_pdu_rel8->number_of_resource_blocks, end) && - pull8(ppReadPackedMsg, &ulsch_pdu_rel8->modulation_type, end) && - pull8(ppReadPackedMsg, &ulsch_pdu_rel8->cyclic_shift_2_for_drms, end) && - pull8(ppReadPackedMsg, &ulsch_pdu_rel8->frequency_hopping_enabled_flag, end) && - pull8(ppReadPackedMsg, &ulsch_pdu_rel8->frequency_hopping_bits, end) && - pull8(ppReadPackedMsg, &ulsch_pdu_rel8->new_data_indication, end) && - pull8(ppReadPackedMsg, &ulsch_pdu_rel8->redundancy_version, end) && - pull8(ppReadPackedMsg, &ulsch_pdu_rel8->harq_process_number, end) && - pull8(ppReadPackedMsg, &ulsch_pdu_rel8->ul_tx_mode, end) && - pull8(ppReadPackedMsg, &ulsch_pdu_rel8->current_tx_nb, end) && - pull8(ppReadPackedMsg, &ulsch_pdu_rel8->n_srs, end )); + if (!(pull16(ppReadPackedMsg,&pNfapiMsg->SFN, end) && + pull16(ppReadPackedMsg, &pNfapiMsg->Slot, end) && + pull8(ppReadPackedMsg, &pNfapiMsg->dl_tti_request_body.nGroup, end) && + pull8(ppReadPackedMsg, &pNfapiMsg->dl_tti_request_body.nPDUs, end) && + pullarray8(ppReadPackedMsg,pNfapiMsg->dl_tti_request_body.nUe,256,pNfapiMsg->dl_tti_request_body.nGroup, end) + //pusharray8(pNfapiMsg->PduIdx[0] ,256,256, ppWritePackedMsg, end) + )) + return 0; + + int arr[12]; + + for(int i=0; idl_tti_request_body.nGroup; i++) { + for(int j=0; jdl_tti_request_body.nUe[i]; j++) { + arr[j] = pNfapiMsg->dl_tti_request_body.PduIdx[i][j]; + } + + if(!(pullarrays32(ppReadPackedMsg,arr,12,pNfapiMsg->dl_tti_request_body.nUe[i], end))) + return 0; + } + + for(int i=0; idl_tti_request_body.nPDUs; i++) { + if(!unpack_dl_tti_request_body_value(ppReadPackedMsg, end, &pNfapiMsg->dl_tti_request_body.dl_tti_pdu_list[i])) + return 0; + } + + return 1; } -static uint8_t unpack_ul_config_ulsch_pdu_rel10_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_ul_config_ulsch_pdu_rel10_t* ulsch_pdu_rel10 = (nfapi_ul_config_ulsch_pdu_rel10_t*)tlv; - - return (pull8(ppReadPackedMsg, &ulsch_pdu_rel10->resource_allocation_type, end) && - pull32(ppReadPackedMsg, &ulsch_pdu_rel10->resource_block_coding, end) && - pull8(ppReadPackedMsg, &ulsch_pdu_rel10->transport_blocks, end) && - pull8(ppReadPackedMsg, &ulsch_pdu_rel10->transmission_scheme, end) && - pull8(ppReadPackedMsg, &ulsch_pdu_rel10->number_of_layers, end) & - pull8(ppReadPackedMsg, &ulsch_pdu_rel10->codebook_index, end) && - pull8(ppReadPackedMsg, &ulsch_pdu_rel10->disable_sequence_hopping_flag, end)); -} -static uint8_t unpack_ul_config_ulsch_pdu_rel11_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_ul_config_ulsch_pdu_rel11_t* ulsch_pdu_rel11 = (nfapi_ul_config_ulsch_pdu_rel11_t*)tlv; - - return ( pull8(ppReadPackedMsg, &ulsch_pdu_rel11->virtual_cell_id_enabled_flag, end) && - pull16(ppReadPackedMsg, &ulsch_pdu_rel11->npusch_identity, end) && - pull8(ppReadPackedMsg, &ulsch_pdu_rel11->dmrs_config_flag, end) && - pull16(ppReadPackedMsg, &ulsch_pdu_rel11->ndmrs_csh_identity, end)); -} -static uint8_t unpack_ul_config_ulsch_pdu_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_ul_config_ulsch_pdu_rel13_t* ulsch_pdu_rel13 = (nfapi_ul_config_ulsch_pdu_rel13_t*)tlv; - - return (pull8(ppReadPackedMsg, &ulsch_pdu_rel13->ue_type, end) && - pull16(ppReadPackedMsg, &ulsch_pdu_rel13->total_number_of_repetitions, end) && - pull16(ppReadPackedMsg, &ulsch_pdu_rel13->repetition_number, end) && - pull16(ppReadPackedMsg, &ulsch_pdu_rel13->initial_transmission_sf_io, end) && - pull8(ppReadPackedMsg, &ulsch_pdu_rel13->empty_symbols_due_to_re_tunning, end)); -} -static uint8_t unpack_ul_config_cqi_ri_info_rel8_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_ul_config_cqi_ri_information_rel8_t* cqi_ri_info_rel8 = (nfapi_ul_config_cqi_ri_information_rel8_t*)tlv; - - return (pull8(ppReadPackedMsg, &cqi_ri_info_rel8->dl_cqi_pmi_size_rank_1, end) && - pull8(ppReadPackedMsg, &cqi_ri_info_rel8->dl_cqi_pmi_size_rank_greater_1, end) && - pull8(ppReadPackedMsg, &cqi_ri_info_rel8->ri_size, end) && - pull8(ppReadPackedMsg, &cqi_ri_info_rel8->delta_offset_cqi, end) && - pull8(ppReadPackedMsg, &cqi_ri_info_rel8->delta_offset_ri, end)); + +static uint8_t unpack_ul_tti_request_prach_pdu(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_nr_prach_pdu_t *prach_pdu = (nfapi_nr_prach_pdu_t *)tlv; + return( + pull16(ppReadPackedMsg, &prach_pdu->phys_cell_id, end) && + pull8(ppReadPackedMsg, &prach_pdu->num_prach_ocas, end) && + pull8(ppReadPackedMsg, &prach_pdu->prach_format, end) && + pull8(ppReadPackedMsg, &prach_pdu->num_ra, end) && + pull8(ppReadPackedMsg, &prach_pdu->prach_start_symbol, end) && + pull16(ppReadPackedMsg, &prach_pdu->num_cs, end) + // TODO: ignoring beamforming tlv for now + ); } -static uint8_t unpack_ul_config_cqi_ri_info_rel9_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_ul_config_cqi_ri_information_rel9_t* cqi_ri_info_rel9 = (nfapi_ul_config_cqi_ri_information_rel9_t*)tlv; - - if(!(pull8(ppReadPackedMsg, &cqi_ri_info_rel9->report_type, end) && - pull8(ppReadPackedMsg, &cqi_ri_info_rel9->delta_offset_cqi, end) && - pull8(ppReadPackedMsg, &cqi_ri_info_rel9->delta_offset_ri, end))) - return 0; - switch(cqi_ri_info_rel9->report_type) - { - case NFAPI_CSI_REPORT_TYPE_PERIODIC: - { - if(!(pull8(ppReadPackedMsg, &cqi_ri_info_rel9->periodic_cqi_pmi_ri_report.dl_cqi_pmi_ri_size, end) && - pull8(ppReadPackedMsg, &cqi_ri_info_rel9->periodic_cqi_pmi_ri_report.control_type, end))) - return 0; - } - break; - case NFAPI_CSI_REPORT_TYPE_APERIODIC: - { - if(pull8(ppReadPackedMsg, &cqi_ri_info_rel9->aperiodic_cqi_pmi_ri_report.number_of_cc, end) ==0) - return 0; - - uint8_t i; - for(i = 0; i < cqi_ri_info_rel9->aperiodic_cqi_pmi_ri_report.number_of_cc; ++i) - { - if(pull8(ppReadPackedMsg, &cqi_ri_info_rel9->aperiodic_cqi_pmi_ri_report.cc[i].ri_size, end) == 0) - return 0; +static uint8_t unpack_ul_tti_request_pucch_pdu(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_nr_pucch_pdu_t *pucch_pdu = (nfapi_nr_pucch_pdu_t *)tlv; + return( + pull16(ppReadPackedMsg, &pucch_pdu->rnti, end) && + pull32(ppReadPackedMsg, &pucch_pdu->handle, end) && + pull16(ppReadPackedMsg, &pucch_pdu->bwp_size, end) && + pull16(ppReadPackedMsg, &pucch_pdu->bwp_start, end) && + pull8(ppReadPackedMsg, &pucch_pdu->subcarrier_spacing, end) && + pull8(ppReadPackedMsg, &pucch_pdu->cyclic_prefix, end) && + pull8(ppReadPackedMsg, &pucch_pdu->format_type, end) && + pull8(ppReadPackedMsg, &pucch_pdu->multi_slot_tx_indicator, end) && + pull16(ppReadPackedMsg, &pucch_pdu->prb_start, end) && + pull16(ppReadPackedMsg, &pucch_pdu->prb_size, end) && + pull8(ppReadPackedMsg, &pucch_pdu->start_symbol_index, end) && + pull8(ppReadPackedMsg, &pucch_pdu->nr_of_symbols, end) && + pull8(ppReadPackedMsg, &pucch_pdu->freq_hop_flag, end) && + pull16(ppReadPackedMsg, &pucch_pdu->second_hop_prb, end) && + pull8(ppReadPackedMsg, &pucch_pdu->group_hop_flag, end) && + pull8(ppReadPackedMsg, &pucch_pdu->sequence_hop_flag, end) && + pull16(ppReadPackedMsg, &pucch_pdu->hopping_id, end) && + pull16(ppReadPackedMsg, &pucch_pdu->initial_cyclic_shift, end) && + pull16(ppReadPackedMsg, &pucch_pdu->data_scrambling_id, end) && + pull8(ppReadPackedMsg, &pucch_pdu->time_domain_occ_idx, end) && + pull8(ppReadPackedMsg, &pucch_pdu->pre_dft_occ_idx, end) && + pull8(ppReadPackedMsg, &pucch_pdu->pre_dft_occ_len, end) && + pull8(ppReadPackedMsg, &pucch_pdu->add_dmrs_flag, end) && + pull16(ppReadPackedMsg, &pucch_pdu->dmrs_scrambling_id, end) && + pull8(ppReadPackedMsg, &pucch_pdu->dmrs_cyclic_shift, end) && + pull8(ppReadPackedMsg, &pucch_pdu->sr_flag, end) && + pull8(ppReadPackedMsg, &pucch_pdu->bit_len_harq, end) && + pull16(ppReadPackedMsg, &pucch_pdu->bit_len_csi_part1, end) && + pull16(ppReadPackedMsg, &pucch_pdu->bit_len_csi_part2, end) + // TODO: ignoring beamforming tlv for now + ); +} - uint8_t j; - for(j = 0; j < 8; ++j) - { - if(pull8(ppReadPackedMsg, &cqi_ri_info_rel9->aperiodic_cqi_pmi_ri_report.cc[i].dl_cqi_pmi_size[j], end) == 0) - return 0; - } - } - } - break; - default: - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "FIXME : Invalid report type %d \n", cqi_ri_info_rel9->report_type ); - return 0; - } - break; - }; - return 1; + +static uint8_t unpack_ul_tti_request_pusch_pdu(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_nr_pusch_pdu_t *pusch_pdu = (nfapi_nr_pusch_pdu_t *)tlv; + + if (!( + pull16(ppReadPackedMsg, &pusch_pdu->pdu_bit_map, end) && + pull16(ppReadPackedMsg, &pusch_pdu->rnti, end) && + pull32(ppReadPackedMsg, &pusch_pdu->handle, end) && + pull16(ppReadPackedMsg, &pusch_pdu->bwp_size, end) && + pull16(ppReadPackedMsg, &pusch_pdu->bwp_start, end) && + pull8(ppReadPackedMsg, &pusch_pdu->subcarrier_spacing, end) && + pull8(ppReadPackedMsg, &pusch_pdu->cyclic_prefix, end) && + pull16(ppReadPackedMsg, &pusch_pdu->target_code_rate, end) && + pull8(ppReadPackedMsg, &pusch_pdu->qam_mod_order, end) && + pull8(ppReadPackedMsg, &pusch_pdu->mcs_index, end) && + pull8(ppReadPackedMsg, &pusch_pdu->mcs_table, end) && + pull8(ppReadPackedMsg, &pusch_pdu->transform_precoding, end) && + pull16(ppReadPackedMsg, &pusch_pdu->data_scrambling_id, end) && + pull8(ppReadPackedMsg, &pusch_pdu->nrOfLayers, end) && + pull16(ppReadPackedMsg, &pusch_pdu->ul_dmrs_symb_pos, end) && + pull8(ppReadPackedMsg, &pusch_pdu->dmrs_config_type, end) && + pull16(ppReadPackedMsg, &pusch_pdu->ul_dmrs_scrambling_id, end) && + pull8(ppReadPackedMsg, &pusch_pdu->scid, end) && + pull8(ppReadPackedMsg, &pusch_pdu->num_dmrs_cdm_grps_no_data, end) && + pull16(ppReadPackedMsg, &pusch_pdu->dmrs_ports, end) && + pull8(ppReadPackedMsg, &pusch_pdu->resource_alloc, end) && + pull8(ppReadPackedMsg, &pusch_pdu->resource_alloc,end) && + pull16(ppReadPackedMsg, &pusch_pdu->dmrs_ports, end) && + pull16(ppReadPackedMsg, &pusch_pdu->rb_start, end) && + pull16(ppReadPackedMsg, &pusch_pdu->rb_size, end) && + pull8(ppReadPackedMsg, &pusch_pdu->vrb_to_prb_mapping, end) && + pull8(ppReadPackedMsg, &pusch_pdu->frequency_hopping, end) && + pull16(ppReadPackedMsg, &pusch_pdu->tx_direct_current_location, end) && + pull8(ppReadPackedMsg, &pusch_pdu->uplink_frequency_shift_7p5khz, end) && + pull8(ppReadPackedMsg, &pusch_pdu->start_symbol_index, end) && + pull8(ppReadPackedMsg, &pusch_pdu->nr_of_symbols, end) + // TODO: ignoring beamforming tlv for now + )) + return 0; + + //Pack Optional Data only included if indicated in pduBitmap + switch(pusch_pdu->pdu_bit_map) { + case PUSCH_PDU_BITMAP_PUSCH_DATA: { + // pack optional TLVs + return( + pull8(ppReadPackedMsg, &pusch_pdu->pusch_data.rv_index, end) && + pull8(ppReadPackedMsg, &pusch_pdu->pusch_data.harq_process_id, end) && + pull32(ppReadPackedMsg, &pusch_pdu->pusch_data.tb_size, end) && + pull16(ppReadPackedMsg, &pusch_pdu->pusch_data.num_cb, end) && + pullarray8(ppReadPackedMsg, pusch_pdu->pusch_data.cb_present_and_position,1,1,end) + ); + } + break; + + case PUSCH_PDU_BITMAP_PUSCH_UCI: { + return( + pull16(ppReadPackedMsg, &pusch_pdu->pusch_uci.harq_ack_bit_length, end) && + pull16(ppReadPackedMsg, &pusch_pdu->pusch_uci.csi_part1_bit_length, end) && + pull16(ppReadPackedMsg, &pusch_pdu->pusch_uci.csi_part2_bit_length, end) && + pull8(ppReadPackedMsg, &pusch_pdu->pusch_uci.alpha_scaling, end) && + pull8(ppReadPackedMsg, &pusch_pdu->pusch_uci.beta_offset_harq_ack, end) && + pull8(ppReadPackedMsg, &pusch_pdu->pusch_uci.beta_offset_csi1, end) && + pull8(ppReadPackedMsg, &pusch_pdu->pusch_uci.beta_offset_csi2, end) + ); + } + break; + + case PUSCH_PDU_BITMAP_PUSCH_PTRS: { + return( + pull8(ppReadPackedMsg, &pusch_pdu->pusch_ptrs.num_ptrs_ports, end) && + pull8(ppReadPackedMsg, &pusch_pdu->pusch_ptrs.ptrs_ports_list->ptrs_dmrs_port, end) && + + pull16(ppReadPackedMsg, &pusch_pdu->pusch_ptrs.ptrs_ports_list->ptrs_port_index, end) && + + pull8(ppReadPackedMsg, &pusch_pdu->pusch_ptrs.ptrs_ports_list->ptrs_re_offset, end) && + pull8(ppReadPackedMsg, &pusch_pdu->pusch_ptrs.ptrs_time_density, end) && + pull8(ppReadPackedMsg, &pusch_pdu->pusch_ptrs.ptrs_freq_density, end) && + pull8(ppReadPackedMsg, &pusch_pdu->pusch_ptrs.ul_ptrs_power, end) + ); + } + break; + + case PUSCH_PDU_BITMAP_DFTS_OFDM: { + return( + pull8(ppReadPackedMsg, &pusch_pdu->dfts_ofdm.low_papr_group_number, end) && + pull16(ppReadPackedMsg, &pusch_pdu->dfts_ofdm.low_papr_sequence_number, end) && + pull8(ppReadPackedMsg, &pusch_pdu->dfts_ofdm.ul_ptrs_sample_density, end) && + pull8(ppReadPackedMsg, &pusch_pdu->dfts_ofdm.ul_ptrs_time_density_transform_precoding, end) + ); + } + break; + + default: { + NFAPI_TRACE(NFAPI_TRACE_INFO, "Invalid pdu bitmap %d \n", pusch_pdu->pdu_bit_map ); + } + } + + return 1; +} + + +static uint8_t unpack_ul_tti_request_srs_pdu(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_nr_srs_pdu_t *srs_pdu = (nfapi_nr_srs_pdu_t *)tlv; + return( + pull16(ppReadPackedMsg, &srs_pdu->rnti, end) && + pull32(ppReadPackedMsg, &srs_pdu->handle, end) && + pull16(ppReadPackedMsg, &srs_pdu->bwp_size, end) && + pull16(ppReadPackedMsg, &srs_pdu->bwp_start, end) && + pull8(ppReadPackedMsg, &srs_pdu->subcarrier_spacing, end) && + pull8(ppReadPackedMsg, &srs_pdu->cyclic_prefix, end) && + pull8(ppReadPackedMsg, &srs_pdu->num_ant_ports, end) && + pull8(ppReadPackedMsg, &srs_pdu->num_symbols, end) && + pull8(ppReadPackedMsg, &srs_pdu->num_repetitions, end) && + pull8(ppReadPackedMsg, &srs_pdu->time_start_position, end) && + pull8(ppReadPackedMsg, &srs_pdu->config_index, end) && + pull16(ppReadPackedMsg, &srs_pdu->sequence_id, end) && + pull8(ppReadPackedMsg, &srs_pdu->bandwidth_index, end) && + pull8(ppReadPackedMsg, &srs_pdu->comb_size, end) && + pull8(ppReadPackedMsg, &srs_pdu->comb_offset, end) && + pull8(ppReadPackedMsg, &srs_pdu->cyclic_shift, end) && + pull8(ppReadPackedMsg, &srs_pdu->frequency_position, end) && + pull8(ppReadPackedMsg, &srs_pdu->frequency_shift, end) && + pull8(ppReadPackedMsg, &srs_pdu->frequency_hopping, end) && + pull8(ppReadPackedMsg, &srs_pdu->group_or_sequence_hopping, end) && + pull8(ppReadPackedMsg, &srs_pdu->resource_type, end) && + pull16(ppReadPackedMsg, &srs_pdu->t_srs, end) && + pull16(ppReadPackedMsg, &srs_pdu->t_offset, end) + // TODO: ignoring beamforming tlv for now + ); +} + + +static uint8_t unpack_ul_tti_pdu_list_value(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg) { + nfapi_nr_ul_tti_request_number_of_pdus_t *pNfapiMsg = (nfapi_nr_ul_tti_request_number_of_pdus_t *)msg; + + if(!(pull16(ppReadPackedMsg, &pNfapiMsg->pdu_size, end) && + pull16(ppReadPackedMsg, &pNfapiMsg->pdu_type, end) )) + return 0; + + // first natch the pdu type, then call the respective function + switch(pNfapiMsg->pdu_type) { + case NFAPI_NR_UL_CONFIG_PRACH_PDU_TYPE: { + if(!unpack_ul_tti_request_prach_pdu(&pNfapiMsg->prach_pdu, ppReadPackedMsg, end)) + return 0; + } + break; + + case NFAPI_NR_UL_CONFIG_PUCCH_PDU_TYPE: { + if(!unpack_ul_tti_request_pucch_pdu(&pNfapiMsg->pucch_pdu, ppReadPackedMsg, end)) + return 0; + } + break; + + case NFAPI_NR_UL_CONFIG_PUSCH_PDU_TYPE: { + if(!unpack_ul_tti_request_pusch_pdu(&pNfapiMsg->pusch_pdu, ppReadPackedMsg, end)) + return 0; + } + break; + + case NFAPI_NR_UL_CONFIG_SRS_PDU_TYPE: { + if(!unpack_ul_tti_request_srs_pdu(&pNfapiMsg->srs_pdu, ppReadPackedMsg, end)) + return 0; + } + break; + + default: { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "FIXME : Invalid UL_TTI pdu type %d \n", pNfapiMsg->pdu_type ); + } + break; + } + + return 1; +} + + +static uint8_t unpack_ul_tti_groups_list_value(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg) { + nfapi_nr_ul_tti_request_number_of_groups_t *pNfapiMsg = (nfapi_nr_ul_tti_request_number_of_groups_t *)msg; + + if(!pull8(ppReadPackedMsg, &pNfapiMsg->n_ue, end)) + return 0; + + for (int i = 0; i < pNfapiMsg->n_ue; i++) { + if(!pull8(ppReadPackedMsg, &pNfapiMsg->ue_list[i].pdu_idx,end) ) + return 0; + } + + return 1; +} + + +static uint8_t unpack_ul_tti_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t *config) { + nfapi_nr_ul_tti_request_t *pNfapiMsg = (nfapi_nr_ul_tti_request_t *)msg; + + if (!( + pull16(ppReadPackedMsg, &pNfapiMsg->SFN, end) && + pull16(ppReadPackedMsg, &pNfapiMsg->Slot, end) && + pull8(ppReadPackedMsg, &pNfapiMsg->n_pdus, end) && + pull8(ppReadPackedMsg, &pNfapiMsg->n_group, end) && + pull8(ppReadPackedMsg, &pNfapiMsg->rach_present, end) && + pull8(ppReadPackedMsg, &pNfapiMsg->n_ulcch, end) && + pull8(ppReadPackedMsg, &pNfapiMsg->n_ulsch, end) )) + return 0; + + for(int i=0; i< pNfapiMsg->n_pdus; i++) { + if (!unpack_ul_tti_pdu_list_value(ppReadPackedMsg, end, &pNfapiMsg->pdus_list[i])) + return 0; + } + + for(int i=0; i< pNfapiMsg->n_group; i++) { + if (!unpack_ul_tti_groups_list_value(ppReadPackedMsg, end, &pNfapiMsg->groups_list[i])) + return 0; + } + + return 1; +} + + + +static uint8_t unpack_dl_config_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t *config) { + nfapi_dl_config_request_t *pNfapiMsg = (nfapi_dl_config_request_t *)msg; + unpack_p7_tlv_t unpack_fns[] = { + { NFAPI_DL_CONFIG_REQUEST_BODY_TAG, &pNfapiMsg->dl_config_request_body, &unpack_dl_config_request_body_value}, + }; + return ( pull16(ppReadPackedMsg, &pNfapiMsg->sfn_sf, end) && + unpack_p7_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); +} + +static uint8_t unpack_ul_config_ulsch_pdu_rel8_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_ul_config_ulsch_pdu_rel8_t *ulsch_pdu_rel8 = (nfapi_ul_config_ulsch_pdu_rel8_t *)tlv; + return (pull32(ppReadPackedMsg, &ulsch_pdu_rel8->handle, end) && + pull16(ppReadPackedMsg, &ulsch_pdu_rel8->size, end) && + pull16(ppReadPackedMsg, &ulsch_pdu_rel8->rnti, end) && + pull8(ppReadPackedMsg, &ulsch_pdu_rel8->resource_block_start, end) && + pull8(ppReadPackedMsg, &ulsch_pdu_rel8->number_of_resource_blocks, end) && + pull8(ppReadPackedMsg, &ulsch_pdu_rel8->modulation_type, end) && + pull8(ppReadPackedMsg, &ulsch_pdu_rel8->cyclic_shift_2_for_drms, end) && + pull8(ppReadPackedMsg, &ulsch_pdu_rel8->frequency_hopping_enabled_flag, end) && + pull8(ppReadPackedMsg, &ulsch_pdu_rel8->frequency_hopping_bits, end) && + pull8(ppReadPackedMsg, &ulsch_pdu_rel8->new_data_indication, end) && + pull8(ppReadPackedMsg, &ulsch_pdu_rel8->redundancy_version, end) && + pull8(ppReadPackedMsg, &ulsch_pdu_rel8->harq_process_number, end) && + pull8(ppReadPackedMsg, &ulsch_pdu_rel8->ul_tx_mode, end) && + pull8(ppReadPackedMsg, &ulsch_pdu_rel8->current_tx_nb, end) && + pull8(ppReadPackedMsg, &ulsch_pdu_rel8->n_srs, end )); +} + +static uint8_t unpack_ul_config_ulsch_pdu_rel10_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_ul_config_ulsch_pdu_rel10_t *ulsch_pdu_rel10 = (nfapi_ul_config_ulsch_pdu_rel10_t *)tlv; + return (pull8(ppReadPackedMsg, &ulsch_pdu_rel10->resource_allocation_type, end) && + pull32(ppReadPackedMsg, &ulsch_pdu_rel10->resource_block_coding, end) && + pull8(ppReadPackedMsg, &ulsch_pdu_rel10->transport_blocks, end) && + pull8(ppReadPackedMsg, &ulsch_pdu_rel10->transmission_scheme, end) && + pull8(ppReadPackedMsg, &ulsch_pdu_rel10->number_of_layers, end) & + pull8(ppReadPackedMsg, &ulsch_pdu_rel10->codebook_index, end) && + pull8(ppReadPackedMsg, &ulsch_pdu_rel10->disable_sequence_hopping_flag, end)); +} +static uint8_t unpack_ul_config_ulsch_pdu_rel11_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_ul_config_ulsch_pdu_rel11_t *ulsch_pdu_rel11 = (nfapi_ul_config_ulsch_pdu_rel11_t *)tlv; + return ( pull8(ppReadPackedMsg, &ulsch_pdu_rel11->virtual_cell_id_enabled_flag, end) && + pull16(ppReadPackedMsg, &ulsch_pdu_rel11->npusch_identity, end) && + pull8(ppReadPackedMsg, &ulsch_pdu_rel11->dmrs_config_flag, end) && + pull16(ppReadPackedMsg, &ulsch_pdu_rel11->ndmrs_csh_identity, end)); +} +static uint8_t unpack_ul_config_ulsch_pdu_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_ul_config_ulsch_pdu_rel13_t *ulsch_pdu_rel13 = (nfapi_ul_config_ulsch_pdu_rel13_t *)tlv; + return (pull8(ppReadPackedMsg, &ulsch_pdu_rel13->ue_type, end) && + pull16(ppReadPackedMsg, &ulsch_pdu_rel13->total_number_of_repetitions, end) && + pull16(ppReadPackedMsg, &ulsch_pdu_rel13->repetition_number, end) && + pull16(ppReadPackedMsg, &ulsch_pdu_rel13->initial_transmission_sf_io, end) && + pull8(ppReadPackedMsg, &ulsch_pdu_rel13->empty_symbols_due_to_re_tunning, end)); +} +static uint8_t unpack_ul_config_cqi_ri_info_rel8_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_ul_config_cqi_ri_information_rel8_t *cqi_ri_info_rel8 = (nfapi_ul_config_cqi_ri_information_rel8_t *)tlv; + return (pull8(ppReadPackedMsg, &cqi_ri_info_rel8->dl_cqi_pmi_size_rank_1, end) && + pull8(ppReadPackedMsg, &cqi_ri_info_rel8->dl_cqi_pmi_size_rank_greater_1, end) && + pull8(ppReadPackedMsg, &cqi_ri_info_rel8->ri_size, end) && + pull8(ppReadPackedMsg, &cqi_ri_info_rel8->delta_offset_cqi, end) && + pull8(ppReadPackedMsg, &cqi_ri_info_rel8->delta_offset_ri, end)); +} + +static uint8_t unpack_ul_config_cqi_ri_info_rel9_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_ul_config_cqi_ri_information_rel9_t *cqi_ri_info_rel9 = (nfapi_ul_config_cqi_ri_information_rel9_t *)tlv; + + if(!(pull8(ppReadPackedMsg, &cqi_ri_info_rel9->report_type, end) && + pull8(ppReadPackedMsg, &cqi_ri_info_rel9->delta_offset_cqi, end) && + pull8(ppReadPackedMsg, &cqi_ri_info_rel9->delta_offset_ri, end))) + return 0; + + switch(cqi_ri_info_rel9->report_type) { + case NFAPI_CSI_REPORT_TYPE_PERIODIC: { + if(!(pull8(ppReadPackedMsg, &cqi_ri_info_rel9->periodic_cqi_pmi_ri_report.dl_cqi_pmi_ri_size, end) && + pull8(ppReadPackedMsg, &cqi_ri_info_rel9->periodic_cqi_pmi_ri_report.control_type, end))) + return 0; + } + break; + + case NFAPI_CSI_REPORT_TYPE_APERIODIC: { + if(pull8(ppReadPackedMsg, &cqi_ri_info_rel9->aperiodic_cqi_pmi_ri_report.number_of_cc, end) ==0) + return 0; + + uint8_t i; + + for(i = 0; i < cqi_ri_info_rel9->aperiodic_cqi_pmi_ri_report.number_of_cc; ++i) { + if(pull8(ppReadPackedMsg, &cqi_ri_info_rel9->aperiodic_cqi_pmi_ri_report.cc[i].ri_size, end) == 0) + return 0; + + uint8_t j; + + for(j = 0; j < 8; ++j) { + if(pull8(ppReadPackedMsg, &cqi_ri_info_rel9->aperiodic_cqi_pmi_ri_report.cc[i].dl_cqi_pmi_size[j], end) == 0) + return 0; + } + } + } + break; + + default: { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "FIXME : Invalid report type %d \n", cqi_ri_info_rel9->report_type ); + return 0; + } + break; + }; + + return 1; } // NOTE : This function is a little unconventional as we uese the side to // determine the report type -static uint8_t unpack_ul_config_cqi_ri_info_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_ul_config_cqi_ri_information_rel13_t* cqi_ri_info_rel13 = (nfapi_ul_config_cqi_ri_information_rel13_t*)tlv; - if(cqi_ri_info_rel13->tl.length == 0) - { - cqi_ri_info_rel13->report_type = NFAPI_CSI_REPORT_TYPE_APERIODIC; - } - else - { - cqi_ri_info_rel13->report_type = NFAPI_CSI_REPORT_TYPE_PERIODIC; - if(pull16(ppReadPackedMsg, &cqi_ri_info_rel13->periodic_cqi_pmi_ri_report.dl_cqi_pmi_ri_size_2, end) == 0) - return 0; - } - return 1; +static uint8_t unpack_ul_config_cqi_ri_info_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_ul_config_cqi_ri_information_rel13_t *cqi_ri_info_rel13 = (nfapi_ul_config_cqi_ri_information_rel13_t *)tlv; + + if(cqi_ri_info_rel13->tl.length == 0) { + cqi_ri_info_rel13->report_type = NFAPI_CSI_REPORT_TYPE_APERIODIC; + } else { + cqi_ri_info_rel13->report_type = NFAPI_CSI_REPORT_TYPE_PERIODIC; + + if(pull16(ppReadPackedMsg, &cqi_ri_info_rel13->periodic_cqi_pmi_ri_report.dl_cqi_pmi_ri_size_2, end) == 0) + return 0; + } + + return 1; } -static uint8_t unpack_ul_config_cqi_init_tx_params_rel8_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_ul_config_initial_transmission_parameters_rel8_t* init_tx_params_rel8 = (nfapi_ul_config_initial_transmission_parameters_rel8_t*)tlv; - - return (pull8(ppReadPackedMsg, &init_tx_params_rel8->n_srs_initial, end) && - pull8(ppReadPackedMsg, &init_tx_params_rel8->initial_number_of_resource_blocks, end)); +static uint8_t unpack_ul_config_cqi_init_tx_params_rel8_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_ul_config_initial_transmission_parameters_rel8_t *init_tx_params_rel8 = (nfapi_ul_config_initial_transmission_parameters_rel8_t *)tlv; + return (pull8(ppReadPackedMsg, &init_tx_params_rel8->n_srs_initial, end) && + pull8(ppReadPackedMsg, &init_tx_params_rel8->initial_number_of_resource_blocks, end)); } -static uint8_t unpack_ul_config_ulsch_harq_info_rel10_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_ul_config_ulsch_harq_information_rel10_t* harq_info_rel10 = (nfapi_ul_config_ulsch_harq_information_rel10_t*)tlv; - - return (pull8(ppReadPackedMsg, &harq_info_rel10->harq_size, end) && - pull8(ppReadPackedMsg, &harq_info_rel10->delta_offset_harq, end) && - pull8(ppReadPackedMsg, &harq_info_rel10->ack_nack_mode, end)); +static uint8_t unpack_ul_config_ulsch_harq_info_rel10_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_ul_config_ulsch_harq_information_rel10_t *harq_info_rel10 = (nfapi_ul_config_ulsch_harq_information_rel10_t *)tlv; + return (pull8(ppReadPackedMsg, &harq_info_rel10->harq_size, end) && + pull8(ppReadPackedMsg, &harq_info_rel10->delta_offset_harq, end) && + pull8(ppReadPackedMsg, &harq_info_rel10->ack_nack_mode, end)); } -static uint8_t unpack_ul_config_ulsch_harq_info_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_ul_config_ulsch_harq_information_rel13_t* harq_info_rel13 = (nfapi_ul_config_ulsch_harq_information_rel13_t*)tlv; - - return (pull16(ppReadPackedMsg, &harq_info_rel13->harq_size_2, end) && - pull8(ppReadPackedMsg, &harq_info_rel13->delta_offset_harq_2, end)); +static uint8_t unpack_ul_config_ulsch_harq_info_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_ul_config_ulsch_harq_information_rel13_t *harq_info_rel13 = (nfapi_ul_config_ulsch_harq_information_rel13_t *)tlv; + return (pull16(ppReadPackedMsg, &harq_info_rel13->harq_size_2, end) && + pull8(ppReadPackedMsg, &harq_info_rel13->delta_offset_harq_2, end)); } -static uint8_t unpack_ul_config_ue_info_rel8_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_ul_config_ue_information_rel8_t* ue_info_rel8 = (nfapi_ul_config_ue_information_rel8_t*)tlv; - - return (pull32(ppReadPackedMsg, &ue_info_rel8->handle, end) && - pull16(ppReadPackedMsg, (uint16_t *)&ue_info_rel8->rnti, end)); +static uint8_t unpack_ul_config_ue_info_rel8_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_ul_config_ue_information_rel8_t *ue_info_rel8 = (nfapi_ul_config_ue_information_rel8_t *)tlv; + return (pull32(ppReadPackedMsg, &ue_info_rel8->handle, end) && + pull16(ppReadPackedMsg, (uint16_t *)&ue_info_rel8->rnti, end)); } -static uint8_t unpack_ul_config_ue_info_rel11_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_ul_config_ue_information_rel11_t* ue_info_rel11 = (nfapi_ul_config_ue_information_rel11_t*)tlv; - - return (pull8(ppReadPackedMsg, &ue_info_rel11->virtual_cell_id_enabled_flag, end) && - pull16(ppReadPackedMsg, &ue_info_rel11->npusch_identity, end)); +static uint8_t unpack_ul_config_ue_info_rel11_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_ul_config_ue_information_rel11_t *ue_info_rel11 = (nfapi_ul_config_ue_information_rel11_t *)tlv; + return (pull8(ppReadPackedMsg, &ue_info_rel11->virtual_cell_id_enabled_flag, end) && + pull16(ppReadPackedMsg, &ue_info_rel11->npusch_identity, end)); } -static uint8_t unpack_ul_config_ue_info_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_ul_config_ue_information_rel13_t* ue_info_rel13 = (nfapi_ul_config_ue_information_rel13_t*)tlv; - - return (pull8(ppReadPackedMsg, &ue_info_rel13->ue_type, end) && - pull8(ppReadPackedMsg, &ue_info_rel13->empty_symbols, end) && - pull16(ppReadPackedMsg, &ue_info_rel13->total_number_of_repetitions, end) && - pull16(ppReadPackedMsg, &ue_info_rel13->repetition_number, end)); +static uint8_t unpack_ul_config_ue_info_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_ul_config_ue_information_rel13_t *ue_info_rel13 = (nfapi_ul_config_ue_information_rel13_t *)tlv; + return (pull8(ppReadPackedMsg, &ue_info_rel13->ue_type, end) && + pull8(ppReadPackedMsg, &ue_info_rel13->empty_symbols, end) && + pull16(ppReadPackedMsg, &ue_info_rel13->total_number_of_repetitions, end) && + pull16(ppReadPackedMsg, &ue_info_rel13->repetition_number, end)); } -static uint8_t unpack_ul_config_cqi_info_rel8_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_ul_config_cqi_information_rel8_t* cqi_info_rel8 = (nfapi_ul_config_cqi_information_rel8_t*)tlv; - - return ( pull16(ppReadPackedMsg, &cqi_info_rel8->pucch_index, end) && - pull8(ppReadPackedMsg, &cqi_info_rel8->dl_cqi_pmi_size, end)); +static uint8_t unpack_ul_config_cqi_info_rel8_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_ul_config_cqi_information_rel8_t *cqi_info_rel8 = (nfapi_ul_config_cqi_information_rel8_t *)tlv; + return ( pull16(ppReadPackedMsg, &cqi_info_rel8->pucch_index, end) && + pull8(ppReadPackedMsg, &cqi_info_rel8->dl_cqi_pmi_size, end)); } -static uint8_t unpack_ul_config_cqi_info_rel10_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_ul_config_cqi_information_rel10_t* cqi_info_rel10 = (nfapi_ul_config_cqi_information_rel10_t*)tlv; - - return (pull8(ppReadPackedMsg, &cqi_info_rel10->number_of_pucch_resource, end) && - pull16(ppReadPackedMsg, &cqi_info_rel10->pucch_index_p1, end)); +static uint8_t unpack_ul_config_cqi_info_rel10_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_ul_config_cqi_information_rel10_t *cqi_info_rel10 = (nfapi_ul_config_cqi_information_rel10_t *)tlv; + return (pull8(ppReadPackedMsg, &cqi_info_rel10->number_of_pucch_resource, end) && + pull16(ppReadPackedMsg, &cqi_info_rel10->pucch_index_p1, end)); } -static uint8_t unpack_ul_config_cqi_info_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_ul_config_cqi_information_rel13_t* cqi_info_rel13 = (nfapi_ul_config_cqi_information_rel13_t*)tlv; - - return (pull8(ppReadPackedMsg, &cqi_info_rel13->csi_mode, end) && - pull16(ppReadPackedMsg, &cqi_info_rel13->dl_cqi_pmi_size_2, end) && - pull8(ppReadPackedMsg, &cqi_info_rel13->starting_prb, end) && - pull8(ppReadPackedMsg, &cqi_info_rel13->n_prb, end) && - pull8(ppReadPackedMsg, &cqi_info_rel13->cdm_index, end) && - pull8(ppReadPackedMsg, &cqi_info_rel13->n_srs, end)); -} - -static uint8_t unpack_ul_config_sr_info_rel8_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_ul_config_sr_information_rel8_t* sr_info_rel8 = (nfapi_ul_config_sr_information_rel8_t*)tlv; - - return ( pull16(ppReadPackedMsg, &sr_info_rel8->pucch_index, end)); +static uint8_t unpack_ul_config_cqi_info_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_ul_config_cqi_information_rel13_t *cqi_info_rel13 = (nfapi_ul_config_cqi_information_rel13_t *)tlv; + return (pull8(ppReadPackedMsg, &cqi_info_rel13->csi_mode, end) && + pull16(ppReadPackedMsg, &cqi_info_rel13->dl_cqi_pmi_size_2, end) && + pull8(ppReadPackedMsg, &cqi_info_rel13->starting_prb, end) && + pull8(ppReadPackedMsg, &cqi_info_rel13->n_prb, end) && + pull8(ppReadPackedMsg, &cqi_info_rel13->cdm_index, end) && + pull8(ppReadPackedMsg, &cqi_info_rel13->n_srs, end)); } -static uint8_t unpack_ul_config_sr_info_rel10_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_ul_config_sr_information_rel10_t* sr_info_rel10 = (nfapi_ul_config_sr_information_rel10_t*)tlv; - - return (pull8(ppReadPackedMsg, &sr_info_rel10->number_of_pucch_resources, end) && - pull16(ppReadPackedMsg, &sr_info_rel10->pucch_index_p1, end)); +static uint8_t unpack_ul_config_sr_info_rel8_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_ul_config_sr_information_rel8_t *sr_info_rel8 = (nfapi_ul_config_sr_information_rel8_t *)tlv; + return ( pull16(ppReadPackedMsg, &sr_info_rel8->pucch_index, end)); } -static uint8_t unpack_ul_config_harq_info_rel10_tdd_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_ul_config_harq_information_rel10_tdd_t* harq_info_tdd_rel10 = (nfapi_ul_config_harq_information_rel10_tdd_t*)tlv; - - return (pull8(ppReadPackedMsg, &harq_info_tdd_rel10->harq_size, end) && - pull8(ppReadPackedMsg, &harq_info_tdd_rel10->ack_nack_mode, end) && - pull8(ppReadPackedMsg, &harq_info_tdd_rel10->number_of_pucch_resources, end) && - pull16(ppReadPackedMsg, &harq_info_tdd_rel10->n_pucch_1_0, end) && - pull16(ppReadPackedMsg, &harq_info_tdd_rel10->n_pucch_1_1, end) && - pull16(ppReadPackedMsg, &harq_info_tdd_rel10->n_pucch_1_2, end) && - pull16(ppReadPackedMsg, &harq_info_tdd_rel10->n_pucch_1_3, end)); +static uint8_t unpack_ul_config_sr_info_rel10_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_ul_config_sr_information_rel10_t *sr_info_rel10 = (nfapi_ul_config_sr_information_rel10_t *)tlv; + return (pull8(ppReadPackedMsg, &sr_info_rel10->number_of_pucch_resources, end) && + pull16(ppReadPackedMsg, &sr_info_rel10->pucch_index_p1, end)); } -static uint8_t unpack_ul_config_harq_info_rel8_fdd_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_ul_config_harq_information_rel8_fdd_t* harq_info_fdd_rel8 = (nfapi_ul_config_harq_information_rel8_fdd_t*)tlv; - - return (pull16(ppReadPackedMsg, &harq_info_fdd_rel8->n_pucch_1_0, end) && - pull8(ppReadPackedMsg, &harq_info_fdd_rel8->harq_size, end)); +static uint8_t unpack_ul_config_harq_info_rel10_tdd_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_ul_config_harq_information_rel10_tdd_t *harq_info_tdd_rel10 = (nfapi_ul_config_harq_information_rel10_tdd_t *)tlv; + return (pull8(ppReadPackedMsg, &harq_info_tdd_rel10->harq_size, end) && + pull8(ppReadPackedMsg, &harq_info_tdd_rel10->ack_nack_mode, end) && + pull8(ppReadPackedMsg, &harq_info_tdd_rel10->number_of_pucch_resources, end) && + pull16(ppReadPackedMsg, &harq_info_tdd_rel10->n_pucch_1_0, end) && + pull16(ppReadPackedMsg, &harq_info_tdd_rel10->n_pucch_1_1, end) && + pull16(ppReadPackedMsg, &harq_info_tdd_rel10->n_pucch_1_2, end) && + pull16(ppReadPackedMsg, &harq_info_tdd_rel10->n_pucch_1_3, end)); } -static uint8_t unpack_ul_config_harq_info_rel9_fdd_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_ul_config_harq_information_rel9_fdd_t* harq_info_fdd_rel9 = (nfapi_ul_config_harq_information_rel9_fdd_t*)tlv; - - return (pull8(ppReadPackedMsg, &harq_info_fdd_rel9->harq_size, end) && - pull8(ppReadPackedMsg, &harq_info_fdd_rel9->ack_nack_mode, end) && - pull8(ppReadPackedMsg, &harq_info_fdd_rel9->number_of_pucch_resources, end) && - pull16(ppReadPackedMsg, &harq_info_fdd_rel9->n_pucch_1_0, end) && - pull16(ppReadPackedMsg, &harq_info_fdd_rel9->n_pucch_1_1, end) && - pull16(ppReadPackedMsg, &harq_info_fdd_rel9->n_pucch_1_2, end) && - pull16(ppReadPackedMsg, &harq_info_fdd_rel9->n_pucch_1_3, end)); +static uint8_t unpack_ul_config_harq_info_rel8_fdd_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_ul_config_harq_information_rel8_fdd_t *harq_info_fdd_rel8 = (nfapi_ul_config_harq_information_rel8_fdd_t *)tlv; + return (pull16(ppReadPackedMsg, &harq_info_fdd_rel8->n_pucch_1_0, end) && + pull8(ppReadPackedMsg, &harq_info_fdd_rel8->harq_size, end)); } -static uint8_t unpack_ul_config_harq_info_rel11_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_ul_config_harq_information_rel11_t* harq_info_rel11 = (nfapi_ul_config_harq_information_rel11_t*)tlv; - - return (pull8(ppReadPackedMsg, &harq_info_rel11->num_ant_ports, end) && - pull16(ppReadPackedMsg, &harq_info_rel11->n_pucch_2_0, end) && - pull16(ppReadPackedMsg, &harq_info_rel11->n_pucch_2_1, end) && - pull16(ppReadPackedMsg, &harq_info_rel11->n_pucch_2_2, end) && - pull16(ppReadPackedMsg, &harq_info_rel11->n_pucch_2_3, end)); +static uint8_t unpack_ul_config_harq_info_rel9_fdd_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_ul_config_harq_information_rel9_fdd_t *harq_info_fdd_rel9 = (nfapi_ul_config_harq_information_rel9_fdd_t *)tlv; + return (pull8(ppReadPackedMsg, &harq_info_fdd_rel9->harq_size, end) && + pull8(ppReadPackedMsg, &harq_info_fdd_rel9->ack_nack_mode, end) && + pull8(ppReadPackedMsg, &harq_info_fdd_rel9->number_of_pucch_resources, end) && + pull16(ppReadPackedMsg, &harq_info_fdd_rel9->n_pucch_1_0, end) && + pull16(ppReadPackedMsg, &harq_info_fdd_rel9->n_pucch_1_1, end) && + pull16(ppReadPackedMsg, &harq_info_fdd_rel9->n_pucch_1_2, end) && + pull16(ppReadPackedMsg, &harq_info_fdd_rel9->n_pucch_1_3, end)); } -static uint8_t unpack_ul_config_harq_info_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_ul_config_harq_information_rel13_t* harq_info_rel13 = (nfapi_ul_config_harq_information_rel13_t*)tlv; - - return (pull16(ppReadPackedMsg, &harq_info_rel13->harq_size_2, end) && - pull8(ppReadPackedMsg, &harq_info_rel13->starting_prb, end) && - pull8(ppReadPackedMsg, &harq_info_rel13->n_prb, end) && - pull8(ppReadPackedMsg, &harq_info_rel13->cdm_index, end) && - pull8(ppReadPackedMsg, &harq_info_rel13->n_srs, end)); +static uint8_t unpack_ul_config_harq_info_rel11_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_ul_config_harq_information_rel11_t *harq_info_rel11 = (nfapi_ul_config_harq_information_rel11_t *)tlv; + return (pull8(ppReadPackedMsg, &harq_info_rel11->num_ant_ports, end) && + pull16(ppReadPackedMsg, &harq_info_rel11->n_pucch_2_0, end) && + pull16(ppReadPackedMsg, &harq_info_rel11->n_pucch_2_1, end) && + pull16(ppReadPackedMsg, &harq_info_rel11->n_pucch_2_2, end) && + pull16(ppReadPackedMsg, &harq_info_rel11->n_pucch_2_3, end)); +} + +static uint8_t unpack_ul_config_harq_info_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_ul_config_harq_information_rel13_t *harq_info_rel13 = (nfapi_ul_config_harq_information_rel13_t *)tlv; + return (pull16(ppReadPackedMsg, &harq_info_rel13->harq_size_2, end) && + pull8(ppReadPackedMsg, &harq_info_rel13->starting_prb, end) && + pull8(ppReadPackedMsg, &harq_info_rel13->n_prb, end) && + pull8(ppReadPackedMsg, &harq_info_rel13->cdm_index, end) && + pull8(ppReadPackedMsg, &harq_info_rel13->n_srs, end)); } -static uint8_t unpack_ul_config_srs_pdu_rel8_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_ul_config_srs_pdu_rel8_t* srs_pdu_rel8 = (nfapi_ul_config_srs_pdu_rel8_t*)tlv; - - return (pull32(ppReadPackedMsg, &srs_pdu_rel8->handle, end) && - pull16(ppReadPackedMsg, &srs_pdu_rel8->size, end) && - pull16(ppReadPackedMsg, &srs_pdu_rel8->rnti, end) && - pull8(ppReadPackedMsg, &srs_pdu_rel8->srs_bandwidth, end) && - pull8(ppReadPackedMsg, &srs_pdu_rel8->frequency_domain_position, end) && - pull8(ppReadPackedMsg, &srs_pdu_rel8->srs_hopping_bandwidth, end) && - pull8(ppReadPackedMsg, &srs_pdu_rel8->transmission_comb, end) && - pull16(ppReadPackedMsg, &srs_pdu_rel8->i_srs, end) && - pull8(ppReadPackedMsg, &srs_pdu_rel8->sounding_reference_cyclic_shift, end)); +static uint8_t unpack_ul_config_srs_pdu_rel8_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_ul_config_srs_pdu_rel8_t *srs_pdu_rel8 = (nfapi_ul_config_srs_pdu_rel8_t *)tlv; + return (pull32(ppReadPackedMsg, &srs_pdu_rel8->handle, end) && + pull16(ppReadPackedMsg, &srs_pdu_rel8->size, end) && + pull16(ppReadPackedMsg, &srs_pdu_rel8->rnti, end) && + pull8(ppReadPackedMsg, &srs_pdu_rel8->srs_bandwidth, end) && + pull8(ppReadPackedMsg, &srs_pdu_rel8->frequency_domain_position, end) && + pull8(ppReadPackedMsg, &srs_pdu_rel8->srs_hopping_bandwidth, end) && + pull8(ppReadPackedMsg, &srs_pdu_rel8->transmission_comb, end) && + pull16(ppReadPackedMsg, &srs_pdu_rel8->i_srs, end) && + pull8(ppReadPackedMsg, &srs_pdu_rel8->sounding_reference_cyclic_shift, end)); } -static uint8_t unpack_ul_config_srs_pdu_rel10_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_ul_config_srs_pdu_rel10_t* srs_pdu_rel10 = (nfapi_ul_config_srs_pdu_rel10_t*)tlv; - return pull8(ppReadPackedMsg, &srs_pdu_rel10->antenna_port, end); +static uint8_t unpack_ul_config_srs_pdu_rel10_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_ul_config_srs_pdu_rel10_t *srs_pdu_rel10 = (nfapi_ul_config_srs_pdu_rel10_t *)tlv; + return pull8(ppReadPackedMsg, &srs_pdu_rel10->antenna_port, end); } -static uint8_t unpack_ul_config_srs_pdu_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_ul_config_srs_pdu_rel13_t* srs_pdu_rel13 = (nfapi_ul_config_srs_pdu_rel13_t*)tlv; - - return (pull8(ppReadPackedMsg, &srs_pdu_rel13->number_of_combs, end)); +static uint8_t unpack_ul_config_srs_pdu_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_ul_config_srs_pdu_rel13_t *srs_pdu_rel13 = (nfapi_ul_config_srs_pdu_rel13_t *)tlv; + return (pull8(ppReadPackedMsg, &srs_pdu_rel13->number_of_combs, end)); } -static uint8_t unpack_ul_nb_harq_info_rel13_fdd_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_ul_config_nb_harq_information_rel13_fdd_t* nb_harq_info_fdd_rel13 = (nfapi_ul_config_nb_harq_information_rel13_fdd_t*)tlv; - - return (pull8(ppReadPackedMsg, &nb_harq_info_fdd_rel13->harq_ack_resource, end)); +static uint8_t unpack_ul_nb_harq_info_rel13_fdd_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_ul_config_nb_harq_information_rel13_fdd_t *nb_harq_info_fdd_rel13 = (nfapi_ul_config_nb_harq_information_rel13_fdd_t *)tlv; + return (pull8(ppReadPackedMsg, &nb_harq_info_fdd_rel13->harq_ack_resource, end)); } -static uint8_t unpack_ul_config_nulsch_pdu_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_ul_config_nulsch_pdu_rel13_t* nulsch_pdu_rel13 = (nfapi_ul_config_nulsch_pdu_rel13_t*)tlv; +static uint8_t unpack_ul_config_nulsch_pdu_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_ul_config_nulsch_pdu_rel13_t *nulsch_pdu_rel13 = (nfapi_ul_config_nulsch_pdu_rel13_t *)tlv; - if(!(pull8(ppReadPackedMsg, &nulsch_pdu_rel13->nulsch_format, end) && - pull32(ppReadPackedMsg, &nulsch_pdu_rel13->handle, end) && - pull16(ppReadPackedMsg, &nulsch_pdu_rel13->size, end) && - pull16(ppReadPackedMsg, &nulsch_pdu_rel13->rnti, end) && - pull8(ppReadPackedMsg, &nulsch_pdu_rel13->subcarrier_indication, end) && - pull8(ppReadPackedMsg, &nulsch_pdu_rel13->resource_assignment, end) && - pull8(ppReadPackedMsg, &nulsch_pdu_rel13->mcs, end) && - pull8(ppReadPackedMsg, &nulsch_pdu_rel13->redudancy_version, end) && - pull8(ppReadPackedMsg, &nulsch_pdu_rel13->repetition_number, end) && - pull8(ppReadPackedMsg, &nulsch_pdu_rel13->new_data_indication, end) && - pull8(ppReadPackedMsg, &nulsch_pdu_rel13->n_srs, end) && - pull16(ppReadPackedMsg, &nulsch_pdu_rel13->scrambling_sequence_initialization_cinit, end) && - pull16(ppReadPackedMsg, &nulsch_pdu_rel13->sf_idx, end))) - return 0; - - unpack_tlv_t unpack_fns[] = - { - { NFAPI_UL_CONFIG_REQUEST_UE_INFORMATION_REL8_TAG, &nulsch_pdu_rel13->ue_information.ue_information_rel8, &unpack_ul_config_ue_info_rel8_value}, - { NFAPI_UL_CONFIG_REQUEST_UE_INFORMATION_REL11_TAG, &nulsch_pdu_rel13->ue_information.ue_information_rel11, &unpack_ul_config_ue_info_rel11_value}, - { NFAPI_UL_CONFIG_REQUEST_UE_INFORMATION_REL13_TAG, &nulsch_pdu_rel13->ue_information.ue_information_rel13, &unpack_ul_config_ue_info_rel13_value}, - { NFAPI_UL_CONFIG_REQUEST_NB_HARQ_INFORMATION_REL13_FDD_TAG, &nulsch_pdu_rel13->nb_harq_information.nb_harq_information_rel13_fdd, &unpack_ul_nb_harq_info_rel13_fdd_value}, - }; + if(!(pull8(ppReadPackedMsg, &nulsch_pdu_rel13->nulsch_format, end) && + pull32(ppReadPackedMsg, &nulsch_pdu_rel13->handle, end) && + pull16(ppReadPackedMsg, &nulsch_pdu_rel13->size, end) && + pull16(ppReadPackedMsg, &nulsch_pdu_rel13->rnti, end) && + pull8(ppReadPackedMsg, &nulsch_pdu_rel13->subcarrier_indication, end) && + pull8(ppReadPackedMsg, &nulsch_pdu_rel13->resource_assignment, end) && + pull8(ppReadPackedMsg, &nulsch_pdu_rel13->mcs, end) && + pull8(ppReadPackedMsg, &nulsch_pdu_rel13->redudancy_version, end) && + pull8(ppReadPackedMsg, &nulsch_pdu_rel13->repetition_number, end) && + pull8(ppReadPackedMsg, &nulsch_pdu_rel13->new_data_indication, end) && + pull8(ppReadPackedMsg, &nulsch_pdu_rel13->n_srs, end) && + pull16(ppReadPackedMsg, &nulsch_pdu_rel13->scrambling_sequence_initialization_cinit, end) && + pull16(ppReadPackedMsg, &nulsch_pdu_rel13->sf_idx, end))) + return 0; - return unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, 0, 0); + unpack_tlv_t unpack_fns[] = { + { NFAPI_UL_CONFIG_REQUEST_UE_INFORMATION_REL8_TAG, &nulsch_pdu_rel13->ue_information.ue_information_rel8, &unpack_ul_config_ue_info_rel8_value}, + { NFAPI_UL_CONFIG_REQUEST_UE_INFORMATION_REL11_TAG, &nulsch_pdu_rel13->ue_information.ue_information_rel11, &unpack_ul_config_ue_info_rel11_value}, + { NFAPI_UL_CONFIG_REQUEST_UE_INFORMATION_REL13_TAG, &nulsch_pdu_rel13->ue_information.ue_information_rel13, &unpack_ul_config_ue_info_rel13_value}, + { NFAPI_UL_CONFIG_REQUEST_NB_HARQ_INFORMATION_REL13_FDD_TAG, &nulsch_pdu_rel13->nb_harq_information.nb_harq_information_rel13_fdd, &unpack_ul_nb_harq_info_rel13_fdd_value}, + }; + return unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, 0, 0); } -static uint8_t unpack_ul_config_nrach_pdu_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_ul_config_nrach_pdu_rel13_t* nrach_pdu_rel13 = (nfapi_ul_config_nrach_pdu_rel13_t*)tlv; - - return (pull8(ppReadPackedMsg, &nrach_pdu_rel13->nprach_config_0, end) && - pull8(ppReadPackedMsg, &nrach_pdu_rel13->nprach_config_1, end) && - pull8(ppReadPackedMsg, &nrach_pdu_rel13->nprach_config_2, end)); +static uint8_t unpack_ul_config_nrach_pdu_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_ul_config_nrach_pdu_rel13_t *nrach_pdu_rel13 = (nfapi_ul_config_nrach_pdu_rel13_t *)tlv; + return (pull8(ppReadPackedMsg, &nrach_pdu_rel13->nprach_config_0, end) && + pull8(ppReadPackedMsg, &nrach_pdu_rel13->nprach_config_1, end) && + pull8(ppReadPackedMsg, &nrach_pdu_rel13->nprach_config_2, end)); } -static uint8_t unpack_ul_config_request_body_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) -{ - #define UL_CONFIG_ULSCH_PDU_UNPACK_FNS(_pdu) \ - { NFAPI_UL_CONFIG_REQUEST_ULSCH_PDU_REL8_TAG, &_pdu.ulsch_pdu_rel8, &unpack_ul_config_ulsch_pdu_rel8_value}, \ - { NFAPI_UL_CONFIG_REQUEST_ULSCH_PDU_REL10_TAG, &_pdu.ulsch_pdu_rel10, &unpack_ul_config_ulsch_pdu_rel10_value}, \ - { NFAPI_UL_CONFIG_REQUEST_ULSCH_PDU_REL11_TAG, &_pdu.ulsch_pdu_rel11, &unpack_ul_config_ulsch_pdu_rel11_value}, \ - { NFAPI_UL_CONFIG_REQUEST_ULSCH_PDU_REL13_TAG, &_pdu.ulsch_pdu_rel13, &unpack_ul_config_ulsch_pdu_rel13_value}, +static uint8_t unpack_ul_config_request_body_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end, nfapi_p7_codec_config_t *config) { +#define UL_CONFIG_ULSCH_PDU_UNPACK_FNS(_pdu) \ + { NFAPI_UL_CONFIG_REQUEST_ULSCH_PDU_REL8_TAG, &_pdu.ulsch_pdu_rel8, &unpack_ul_config_ulsch_pdu_rel8_value}, \ + { NFAPI_UL_CONFIG_REQUEST_ULSCH_PDU_REL10_TAG, &_pdu.ulsch_pdu_rel10, &unpack_ul_config_ulsch_pdu_rel10_value}, \ + { NFAPI_UL_CONFIG_REQUEST_ULSCH_PDU_REL11_TAG, &_pdu.ulsch_pdu_rel11, &unpack_ul_config_ulsch_pdu_rel11_value}, \ + { NFAPI_UL_CONFIG_REQUEST_ULSCH_PDU_REL13_TAG, &_pdu.ulsch_pdu_rel13, &unpack_ul_config_ulsch_pdu_rel13_value}, +#define UL_CONFIG_CQI_RI_INFO_UNPACK_FNS(_pdu) \ + { NFAPI_UL_CONFIG_REQUEST_CQI_RI_INFORMATION_REL8_TAG, &_pdu.cqi_ri_information_rel8, &unpack_ul_config_cqi_ri_info_rel8_value}, \ + { NFAPI_UL_CONFIG_REQUEST_CQI_RI_INFORMATION_REL9_TAG, &_pdu.cqi_ri_information_rel9, &unpack_ul_config_cqi_ri_info_rel9_value}, \ + { NFAPI_UL_CONFIG_REQUEST_CQI_RI_INFORMATION_REL13_TAG, &_pdu.cqi_ri_information_rel13, &unpack_ul_config_cqi_ri_info_rel13_value}, +#define UL_CONFIG_ULSCH_HARQ_INFO_UNPACK_FNS(_pdu) \ + { NFAPI_UL_CONFIG_REQUEST_ULSCH_HARQ_INFORMATION_REL10_TAG, &_pdu.harq_information_rel10, &unpack_ul_config_ulsch_harq_info_rel10_value},\ + { NFAPI_UL_CONFIG_REQUEST_ULSCH_HARQ_INFORMATION_REL13_TAG, &_pdu.harq_information_rel13, &unpack_ul_config_ulsch_harq_info_rel13_value}, +#define UL_CONFIG_INIT_TX_PARAMS_UNPACK_FNS(_pdu) \ + { NFAPI_UL_CONFIG_REQUEST_INITIAL_TRANSMISSION_PARAMETERS_REL8_TAG, &_pdu.initial_transmission_parameters_rel8, &unpack_ul_config_cqi_init_tx_params_rel8_value}, +#define UL_CONFIG_UCI_UE_INFO_UNPACK_FNS(_pdu) \ + { NFAPI_UL_CONFIG_REQUEST_UE_INFORMATION_REL8_TAG, &_pdu.ue_information_rel8, &unpack_ul_config_ue_info_rel8_value}, \ + { NFAPI_UL_CONFIG_REQUEST_UE_INFORMATION_REL11_TAG, &_pdu.ue_information_rel11, &unpack_ul_config_ue_info_rel11_value}, \ + { NFAPI_UL_CONFIG_REQUEST_UE_INFORMATION_REL13_TAG, &_pdu.ue_information_rel13, &unpack_ul_config_ue_info_rel13_value}, +#define UL_CONFIG_UCI_CQI_INFO_UNPACK_FNS(_pdu) \ + { NFAPI_UL_CONFIG_REQUEST_CQI_INFORMATION_REL8_TAG, &_pdu.cqi_information_rel8, &unpack_ul_config_cqi_info_rel8_value}, \ + { NFAPI_UL_CONFIG_REQUEST_CQI_INFORMATION_REL10_TAG, &_pdu.cqi_information_rel10, &unpack_ul_config_cqi_info_rel10_value}, \ + { NFAPI_UL_CONFIG_REQUEST_CQI_INFORMATION_REL13_TAG, &_pdu.cqi_information_rel13, &unpack_ul_config_cqi_info_rel13_value}, +#define UL_CONFIG_UCI_SR_INFO_UNPACK_FNS(_pdu) \ + { NFAPI_UL_CONFIG_REQUEST_SR_INFORMATION_REL8_TAG, &_pdu.sr_information_rel8, &unpack_ul_config_sr_info_rel8_value}, \ + { NFAPI_UL_CONFIG_REQUEST_SR_INFORMATION_REL10_TAG, &_pdu.sr_information_rel10, &unpack_ul_config_sr_info_rel10_value}, +#define UL_CONFIG_UCI_HARQ_INFO_UNPACK_FNS(_pdu) \ + { NFAPI_UL_CONFIG_REQUEST_HARQ_INFORMATION_REL10_TDD_TAG, &_pdu.harq_information_rel10_tdd, &unpack_ul_config_harq_info_rel10_tdd_value}, \ + { NFAPI_UL_CONFIG_REQUEST_HARQ_INFORMATION_REL8_FDD_TAG, &_pdu.harq_information_rel8_fdd, &unpack_ul_config_harq_info_rel8_fdd_value}, \ + { NFAPI_UL_CONFIG_REQUEST_HARQ_INFORMATION_REL9_FDD_TAG, &_pdu.harq_information_rel9_fdd, &unpack_ul_config_harq_info_rel9_fdd_value}, \ + { NFAPI_UL_CONFIG_REQUEST_HARQ_INFORMATION_REL11_TAG, &_pdu.harq_information_rel11, &unpack_ul_config_harq_info_rel11_value}, \ + { NFAPI_UL_CONFIG_REQUEST_HARQ_INFORMATION_REL13_TAG, &_pdu.harq_information_rel13, &unpack_ul_config_harq_info_rel13_value}, +#define UL_CONFIG_SRS_PDU_UNPACK_FNS(_pdu) \ + { NFAPI_UL_CONFIG_REQUEST_SRS_PDU_REL8_TAG, &_pdu.srs_pdu_rel8, &unpack_ul_config_srs_pdu_rel8_value}, \ + { NFAPI_UL_CONFIG_REQUEST_SRS_PDU_REL10_TAG, &_pdu.srs_pdu_rel10, &unpack_ul_config_srs_pdu_rel10_value}, \ + { NFAPI_UL_CONFIG_REQUEST_SRS_PDU_REL13_TAG, &_pdu.srs_pdu_rel13, &unpack_ul_config_srs_pdu_rel13_value}, +#define UL_CONFIG_NULSCH_PDU_UNPACK_FNS(_pdu) \ + { NFAPI_UL_CONFIG_REQUEST_NULSCH_PDU_REL13_TAG, &_pdu.nulsch_pdu_rel13, &unpack_ul_config_nulsch_pdu_rel13_value}, +#define UL_CONFIG_NRACH_PDU_UNPACK_FNS(_pdu) \ + { NFAPI_UL_CONFIG_REQUEST_NRACH_PDU_REL13_TAG, &_pdu.nrach_pdu_rel13, &unpack_ul_config_nrach_pdu_rel13_value}, + nfapi_ul_config_request_body_t *value = (nfapi_ul_config_request_body_t *)tlv; - #define UL_CONFIG_CQI_RI_INFO_UNPACK_FNS(_pdu) \ - { NFAPI_UL_CONFIG_REQUEST_CQI_RI_INFORMATION_REL8_TAG, &_pdu.cqi_ri_information_rel8, &unpack_ul_config_cqi_ri_info_rel8_value}, \ - { NFAPI_UL_CONFIG_REQUEST_CQI_RI_INFORMATION_REL9_TAG, &_pdu.cqi_ri_information_rel9, &unpack_ul_config_cqi_ri_info_rel9_value}, \ - { NFAPI_UL_CONFIG_REQUEST_CQI_RI_INFORMATION_REL13_TAG, &_pdu.cqi_ri_information_rel13, &unpack_ul_config_cqi_ri_info_rel13_value}, + if(!(pull8(ppReadPackedMsg, &value->number_of_pdus, end) && + pull8(ppReadPackedMsg, &value->rach_prach_frequency_resources, end) && + pull8(ppReadPackedMsg, &value->srs_present, end))) + return 0; - #define UL_CONFIG_ULSCH_HARQ_INFO_UNPACK_FNS(_pdu) \ - { NFAPI_UL_CONFIG_REQUEST_ULSCH_HARQ_INFORMATION_REL10_TAG, &_pdu.harq_information_rel10, &unpack_ul_config_ulsch_harq_info_rel10_value},\ - { NFAPI_UL_CONFIG_REQUEST_ULSCH_HARQ_INFORMATION_REL13_TAG, &_pdu.harq_information_rel13, &unpack_ul_config_ulsch_harq_info_rel13_value}, + if(value->number_of_pdus > NFAPI_UL_CONFIG_MAX_PDU) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s number of ul config pdus exceed maxium (count:%d max:%d)\n", __FUNCTION__, value->number_of_pdus, NFAPI_UL_CONFIG_MAX_PDU); + return 0; + } - #define UL_CONFIG_INIT_TX_PARAMS_UNPACK_FNS(_pdu) \ - { NFAPI_UL_CONFIG_REQUEST_INITIAL_TRANSMISSION_PARAMETERS_REL8_TAG, &_pdu.initial_transmission_parameters_rel8, &unpack_ul_config_cqi_init_tx_params_rel8_value}, + if(value->number_of_pdus > 0) { + value->ul_config_pdu_list = (nfapi_ul_config_request_pdu_t *)nfapi_p7_allocate(sizeof(nfapi_ul_config_request_pdu_t) * value->number_of_pdus, config); - #define UL_CONFIG_UCI_UE_INFO_UNPACK_FNS(_pdu) \ - { NFAPI_UL_CONFIG_REQUEST_UE_INFORMATION_REL8_TAG, &_pdu.ue_information_rel8, &unpack_ul_config_ue_info_rel8_value}, \ - { NFAPI_UL_CONFIG_REQUEST_UE_INFORMATION_REL11_TAG, &_pdu.ue_information_rel11, &unpack_ul_config_ue_info_rel11_value}, \ - { NFAPI_UL_CONFIG_REQUEST_UE_INFORMATION_REL13_TAG, &_pdu.ue_information_rel13, &unpack_ul_config_ue_info_rel13_value}, + if(value->ul_config_pdu_list == NULL) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s failed to allocate ul config pdu list (count:%d)\n", __FUNCTION__, value->number_of_pdus); + return 0; + } + } else { + value->ul_config_pdu_list = 0; + } - #define UL_CONFIG_UCI_CQI_INFO_UNPACK_FNS(_pdu) \ - { NFAPI_UL_CONFIG_REQUEST_CQI_INFORMATION_REL8_TAG, &_pdu.cqi_information_rel8, &unpack_ul_config_cqi_info_rel8_value}, \ - { NFAPI_UL_CONFIG_REQUEST_CQI_INFORMATION_REL10_TAG, &_pdu.cqi_information_rel10, &unpack_ul_config_cqi_info_rel10_value}, \ - { NFAPI_UL_CONFIG_REQUEST_CQI_INFORMATION_REL13_TAG, &_pdu.cqi_information_rel13, &unpack_ul_config_cqi_info_rel13_value}, - - #define UL_CONFIG_UCI_SR_INFO_UNPACK_FNS(_pdu) \ - { NFAPI_UL_CONFIG_REQUEST_SR_INFORMATION_REL8_TAG, &_pdu.sr_information_rel8, &unpack_ul_config_sr_info_rel8_value}, \ - { NFAPI_UL_CONFIG_REQUEST_SR_INFORMATION_REL10_TAG, &_pdu.sr_information_rel10, &unpack_ul_config_sr_info_rel10_value}, + uint16_t i; + uint16_t total_number_of_pdus = value->number_of_pdus; - #define UL_CONFIG_UCI_HARQ_INFO_UNPACK_FNS(_pdu) \ - { NFAPI_UL_CONFIG_REQUEST_HARQ_INFORMATION_REL10_TDD_TAG, &_pdu.harq_information_rel10_tdd, &unpack_ul_config_harq_info_rel10_tdd_value}, \ - { NFAPI_UL_CONFIG_REQUEST_HARQ_INFORMATION_REL8_FDD_TAG, &_pdu.harq_information_rel8_fdd, &unpack_ul_config_harq_info_rel8_fdd_value}, \ - { NFAPI_UL_CONFIG_REQUEST_HARQ_INFORMATION_REL9_FDD_TAG, &_pdu.harq_information_rel9_fdd, &unpack_ul_config_harq_info_rel9_fdd_value}, \ - { NFAPI_UL_CONFIG_REQUEST_HARQ_INFORMATION_REL11_TAG, &_pdu.harq_information_rel11, &unpack_ul_config_harq_info_rel11_value}, \ - { NFAPI_UL_CONFIG_REQUEST_HARQ_INFORMATION_REL13_TAG, &_pdu.harq_information_rel13, &unpack_ul_config_harq_info_rel13_value}, + for(i = 0; i < total_number_of_pdus; ++i) { + nfapi_ul_config_request_pdu_t *pdu = &(value->ul_config_pdu_list[i]); - #define UL_CONFIG_SRS_PDU_UNPACK_FNS(_pdu) \ - { NFAPI_UL_CONFIG_REQUEST_SRS_PDU_REL8_TAG, &_pdu.srs_pdu_rel8, &unpack_ul_config_srs_pdu_rel8_value}, \ - { NFAPI_UL_CONFIG_REQUEST_SRS_PDU_REL10_TAG, &_pdu.srs_pdu_rel10, &unpack_ul_config_srs_pdu_rel10_value}, \ - { NFAPI_UL_CONFIG_REQUEST_SRS_PDU_REL13_TAG, &_pdu.srs_pdu_rel13, &unpack_ul_config_srs_pdu_rel13_value}, - - #define UL_CONFIG_NULSCH_PDU_UNPACK_FNS(_pdu) \ - { NFAPI_UL_CONFIG_REQUEST_NULSCH_PDU_REL13_TAG, &_pdu.nulsch_pdu_rel13, &unpack_ul_config_nulsch_pdu_rel13_value}, + if(!(pull8(ppReadPackedMsg, &pdu->pdu_type, end) && + pull8(ppReadPackedMsg, &pdu->pdu_size, end))) + return 0; - #define UL_CONFIG_NRACH_PDU_UNPACK_FNS(_pdu) \ - { NFAPI_UL_CONFIG_REQUEST_NRACH_PDU_REL13_TAG, &_pdu.nrach_pdu_rel13, &unpack_ul_config_nrach_pdu_rel13_value}, + uint8_t *packedPduEnd = (*ppReadPackedMsg) + pdu->pdu_size - 2; + if(packedPduEnd > end) { + // pdu end is past buffer end + return 0; + } - nfapi_ul_config_request_body_t* value = (nfapi_ul_config_request_body_t*)tlv; + switch(pdu->pdu_type) { + case NFAPI_UL_CONFIG_ULSCH_PDU_TYPE: { + unpack_tlv_t unpack_fns[] = { + UL_CONFIG_ULSCH_PDU_UNPACK_FNS(pdu->ulsch_pdu) + }; + unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); + } + break; - if(!(pull8(ppReadPackedMsg, &value->number_of_pdus, end) && - pull8(ppReadPackedMsg, &value->rach_prach_frequency_resources, end) && - pull8(ppReadPackedMsg, &value->srs_present, end))) - return 0; + case NFAPI_UL_CONFIG_ULSCH_CQI_RI_PDU_TYPE: { + unpack_tlv_t unpack_fns[] = { + UL_CONFIG_ULSCH_PDU_UNPACK_FNS(pdu->ulsch_cqi_ri_pdu.ulsch_pdu) + UL_CONFIG_CQI_RI_INFO_UNPACK_FNS(pdu->ulsch_cqi_ri_pdu.cqi_ri_information) + UL_CONFIG_INIT_TX_PARAMS_UNPACK_FNS(pdu->ulsch_cqi_ri_pdu.initial_transmission_parameters) + }; + unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); + } + break; - if(value->number_of_pdus > NFAPI_UL_CONFIG_MAX_PDU) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s number of ul config pdus exceed maxium (count:%d max:%d)\n", __FUNCTION__, value->number_of_pdus, NFAPI_UL_CONFIG_MAX_PDU); - return 0; - } + case NFAPI_UL_CONFIG_ULSCH_HARQ_PDU_TYPE: { + unpack_tlv_t unpack_fns[] = { + UL_CONFIG_ULSCH_PDU_UNPACK_FNS(pdu->ulsch_harq_pdu.ulsch_pdu) + UL_CONFIG_ULSCH_HARQ_INFO_UNPACK_FNS(pdu->ulsch_harq_pdu.harq_information) + UL_CONFIG_INIT_TX_PARAMS_UNPACK_FNS(pdu->ulsch_harq_pdu.initial_transmission_parameters) + }; + unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); + } + break; - if(value->number_of_pdus > 0) - { - value->ul_config_pdu_list = (nfapi_ul_config_request_pdu_t*)nfapi_p7_allocate(sizeof(nfapi_ul_config_request_pdu_t) * value->number_of_pdus, config); + case NFAPI_UL_CONFIG_ULSCH_CQI_HARQ_RI_PDU_TYPE: { + unpack_tlv_t unpack_fns[] = { + UL_CONFIG_ULSCH_PDU_UNPACK_FNS(pdu->ulsch_cqi_harq_ri_pdu.ulsch_pdu) + UL_CONFIG_CQI_RI_INFO_UNPACK_FNS(pdu->ulsch_cqi_harq_ri_pdu.cqi_ri_information) + UL_CONFIG_ULSCH_HARQ_INFO_UNPACK_FNS(pdu->ulsch_cqi_harq_ri_pdu.harq_information) + UL_CONFIG_INIT_TX_PARAMS_UNPACK_FNS(pdu->ulsch_cqi_harq_ri_pdu.initial_transmission_parameters) + }; + unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); + } + break; - if(value->ul_config_pdu_list == NULL) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s failed to allocate ul config pdu list (count:%d)\n", __FUNCTION__, value->number_of_pdus); - return 0; - } - } - else - { - value->ul_config_pdu_list = 0; - } + case NFAPI_UL_CONFIG_UCI_CQI_PDU_TYPE: { + unpack_tlv_t unpack_fns[] = { + UL_CONFIG_UCI_UE_INFO_UNPACK_FNS(pdu->uci_cqi_pdu.ue_information) + UL_CONFIG_UCI_CQI_INFO_UNPACK_FNS(pdu->uci_cqi_pdu.cqi_information) + }; + unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); + } + break; + case NFAPI_UL_CONFIG_UCI_SR_PDU_TYPE: { + unpack_tlv_t unpack_fns[] = { + UL_CONFIG_UCI_UE_INFO_UNPACK_FNS(pdu->uci_sr_pdu.ue_information) + UL_CONFIG_UCI_SR_INFO_UNPACK_FNS(pdu->uci_sr_pdu.sr_information) + }; + unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); + } + break; - uint16_t i; - uint16_t total_number_of_pdus = value->number_of_pdus; - for(i = 0; i < total_number_of_pdus; ++i) - { - nfapi_ul_config_request_pdu_t* pdu = &(value->ul_config_pdu_list[i]); - - if(!(pull8(ppReadPackedMsg, &pdu->pdu_type, end) && - pull8(ppReadPackedMsg, &pdu->pdu_size, end))) - return 0; - - uint8_t *packedPduEnd = (*ppReadPackedMsg) + pdu->pdu_size - 2; + case NFAPI_UL_CONFIG_UCI_HARQ_PDU_TYPE: { + unpack_tlv_t unpack_fns[] = { + UL_CONFIG_UCI_UE_INFO_UNPACK_FNS(pdu->uci_harq_pdu.ue_information) + UL_CONFIG_UCI_HARQ_INFO_UNPACK_FNS(pdu->uci_harq_pdu.harq_information) + }; + unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); + } + break; - if(packedPduEnd > end) - { - // pdu end is past buffer end - return 0; - } + case NFAPI_UL_CONFIG_UCI_SR_HARQ_PDU_TYPE: { + unpack_tlv_t unpack_fns[] = { + UL_CONFIG_UCI_UE_INFO_UNPACK_FNS(pdu->uci_sr_harq_pdu.ue_information) + UL_CONFIG_UCI_SR_INFO_UNPACK_FNS(pdu->uci_sr_harq_pdu.sr_information) + UL_CONFIG_UCI_HARQ_INFO_UNPACK_FNS(pdu->uci_sr_harq_pdu.harq_information) + }; + unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); + } + break; - switch(pdu->pdu_type) - { - case NFAPI_UL_CONFIG_ULSCH_PDU_TYPE: - { - unpack_tlv_t unpack_fns[] = - { - UL_CONFIG_ULSCH_PDU_UNPACK_FNS(pdu->ulsch_pdu) - }; + case NFAPI_UL_CONFIG_UCI_CQI_HARQ_PDU_TYPE: { + unpack_tlv_t unpack_fns[] = { + UL_CONFIG_UCI_UE_INFO_UNPACK_FNS(pdu->uci_cqi_harq_pdu.ue_information) + UL_CONFIG_UCI_CQI_INFO_UNPACK_FNS(pdu->uci_cqi_harq_pdu.cqi_information) + UL_CONFIG_UCI_HARQ_INFO_UNPACK_FNS(pdu->uci_cqi_harq_pdu.harq_information) + }; + unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); + } + break; - unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); - } - break; + case NFAPI_UL_CONFIG_UCI_CQI_SR_PDU_TYPE: { + unpack_tlv_t unpack_fns[] = { + UL_CONFIG_UCI_UE_INFO_UNPACK_FNS(pdu->uci_cqi_sr_pdu.ue_information) + UL_CONFIG_UCI_CQI_INFO_UNPACK_FNS(pdu->uci_cqi_sr_pdu.cqi_information) + UL_CONFIG_UCI_SR_INFO_UNPACK_FNS(pdu->uci_cqi_sr_pdu.sr_information) + }; + unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); + } + break; - case NFAPI_UL_CONFIG_ULSCH_CQI_RI_PDU_TYPE: - { - unpack_tlv_t unpack_fns[] = - { - UL_CONFIG_ULSCH_PDU_UNPACK_FNS(pdu->ulsch_cqi_ri_pdu.ulsch_pdu) - UL_CONFIG_CQI_RI_INFO_UNPACK_FNS(pdu->ulsch_cqi_ri_pdu.cqi_ri_information) - UL_CONFIG_INIT_TX_PARAMS_UNPACK_FNS(pdu->ulsch_cqi_ri_pdu.initial_transmission_parameters) - }; + case NFAPI_UL_CONFIG_UCI_CQI_SR_HARQ_PDU_TYPE: { + unpack_tlv_t unpack_fns[] = { + UL_CONFIG_UCI_UE_INFO_UNPACK_FNS(pdu->uci_cqi_sr_harq_pdu.ue_information) + UL_CONFIG_UCI_CQI_INFO_UNPACK_FNS(pdu->uci_cqi_sr_harq_pdu.cqi_information) + UL_CONFIG_UCI_SR_INFO_UNPACK_FNS(pdu->uci_cqi_sr_harq_pdu.sr_information) + UL_CONFIG_UCI_HARQ_INFO_UNPACK_FNS(pdu->uci_cqi_sr_harq_pdu.harq_information) + }; + unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); + } + break; - unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); - } - break; - case NFAPI_UL_CONFIG_ULSCH_HARQ_PDU_TYPE: - { - unpack_tlv_t unpack_fns[] = - { - UL_CONFIG_ULSCH_PDU_UNPACK_FNS(pdu->ulsch_harq_pdu.ulsch_pdu) - UL_CONFIG_ULSCH_HARQ_INFO_UNPACK_FNS(pdu->ulsch_harq_pdu.harq_information) - UL_CONFIG_INIT_TX_PARAMS_UNPACK_FNS(pdu->ulsch_harq_pdu.initial_transmission_parameters) - }; + case NFAPI_UL_CONFIG_SRS_PDU_TYPE: { + unpack_tlv_t unpack_fns[] = { + UL_CONFIG_SRS_PDU_UNPACK_FNS(pdu->srs_pdu) + }; + unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); + } + break; - unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); - } - break; - case NFAPI_UL_CONFIG_ULSCH_CQI_HARQ_RI_PDU_TYPE: - { - unpack_tlv_t unpack_fns[] = - { - UL_CONFIG_ULSCH_PDU_UNPACK_FNS(pdu->ulsch_cqi_harq_ri_pdu.ulsch_pdu) - UL_CONFIG_CQI_RI_INFO_UNPACK_FNS(pdu->ulsch_cqi_harq_ri_pdu.cqi_ri_information) - UL_CONFIG_ULSCH_HARQ_INFO_UNPACK_FNS(pdu->ulsch_cqi_harq_ri_pdu.harq_information) - UL_CONFIG_INIT_TX_PARAMS_UNPACK_FNS(pdu->ulsch_cqi_harq_ri_pdu.initial_transmission_parameters) - }; + case NFAPI_UL_CONFIG_HARQ_BUFFER_PDU_TYPE: { + unpack_tlv_t unpack_fns[] = { + UL_CONFIG_UCI_UE_INFO_UNPACK_FNS(pdu->harq_buffer_pdu.ue_information) + }; + unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); + } + break; - unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); - } - break; - case NFAPI_UL_CONFIG_UCI_CQI_PDU_TYPE: - { - unpack_tlv_t unpack_fns[] = - { - UL_CONFIG_UCI_UE_INFO_UNPACK_FNS(pdu->uci_cqi_pdu.ue_information) - UL_CONFIG_UCI_CQI_INFO_UNPACK_FNS(pdu->uci_cqi_pdu.cqi_information) - }; + case NFAPI_UL_CONFIG_ULSCH_UCI_CSI_PDU_TYPE: { + unpack_tlv_t unpack_fns[] = { + UL_CONFIG_ULSCH_PDU_UNPACK_FNS(pdu->ulsch_uci_csi_pdu.ulsch_pdu) + UL_CONFIG_UCI_CQI_INFO_UNPACK_FNS(pdu->ulsch_uci_csi_pdu.csi_information) + }; + unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); + } + break; - unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); - } - break; - case NFAPI_UL_CONFIG_UCI_SR_PDU_TYPE: - { - unpack_tlv_t unpack_fns[] = - { - UL_CONFIG_UCI_UE_INFO_UNPACK_FNS(pdu->uci_sr_pdu.ue_information) - UL_CONFIG_UCI_SR_INFO_UNPACK_FNS(pdu->uci_sr_pdu.sr_information) - }; + case NFAPI_UL_CONFIG_ULSCH_UCI_HARQ_PDU_TYPE: { + unpack_tlv_t unpack_fns[] = { + UL_CONFIG_ULSCH_PDU_UNPACK_FNS(pdu->ulsch_uci_harq_pdu.ulsch_pdu) + UL_CONFIG_UCI_HARQ_INFO_UNPACK_FNS(pdu->ulsch_uci_harq_pdu.harq_information) + }; + unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); + } + break; - unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); - } - break; - case NFAPI_UL_CONFIG_UCI_HARQ_PDU_TYPE: - { - unpack_tlv_t unpack_fns[] = - { - UL_CONFIG_UCI_UE_INFO_UNPACK_FNS(pdu->uci_harq_pdu.ue_information) - UL_CONFIG_UCI_HARQ_INFO_UNPACK_FNS(pdu->uci_harq_pdu.harq_information) - }; + case NFAPI_UL_CONFIG_ULSCH_CSI_UCI_HARQ_PDU_TYPE: { + unpack_tlv_t unpack_fns[] = { + UL_CONFIG_ULSCH_PDU_UNPACK_FNS(pdu->ulsch_csi_uci_harq_pdu.ulsch_pdu) + UL_CONFIG_UCI_CQI_INFO_UNPACK_FNS(pdu->ulsch_csi_uci_harq_pdu.csi_information) + UL_CONFIG_UCI_HARQ_INFO_UNPACK_FNS(pdu->ulsch_csi_uci_harq_pdu.harq_information) + }; + unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); + } + break; - unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); - } - break; - case NFAPI_UL_CONFIG_UCI_SR_HARQ_PDU_TYPE: - { - unpack_tlv_t unpack_fns[] = - { - UL_CONFIG_UCI_UE_INFO_UNPACK_FNS(pdu->uci_sr_harq_pdu.ue_information) - UL_CONFIG_UCI_SR_INFO_UNPACK_FNS(pdu->uci_sr_harq_pdu.sr_information) - UL_CONFIG_UCI_HARQ_INFO_UNPACK_FNS(pdu->uci_sr_harq_pdu.harq_information) - }; + case NFAPI_UL_CONFIG_NULSCH_PDU_TYPE: { + unpack_tlv_t unpack_fns[] = { + UL_CONFIG_NULSCH_PDU_UNPACK_FNS(pdu->nulsch_pdu) + }; + unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); + } + break; - unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); - } - break; - case NFAPI_UL_CONFIG_UCI_CQI_HARQ_PDU_TYPE: - { - unpack_tlv_t unpack_fns[] = - { - UL_CONFIG_UCI_UE_INFO_UNPACK_FNS(pdu->uci_cqi_harq_pdu.ue_information) - UL_CONFIG_UCI_CQI_INFO_UNPACK_FNS(pdu->uci_cqi_harq_pdu.cqi_information) - UL_CONFIG_UCI_HARQ_INFO_UNPACK_FNS(pdu->uci_cqi_harq_pdu.harq_information) - }; + case NFAPI_UL_CONFIG_NRACH_PDU_TYPE: { + unpack_tlv_t unpack_fns[] = { + UL_CONFIG_NRACH_PDU_UNPACK_FNS(pdu->nrach_pdu) + }; + unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); + } + break; + } + } - unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); - } - break; - case NFAPI_UL_CONFIG_UCI_CQI_SR_PDU_TYPE: - { - unpack_tlv_t unpack_fns[] = - { - UL_CONFIG_UCI_UE_INFO_UNPACK_FNS(pdu->uci_cqi_sr_pdu.ue_information) - UL_CONFIG_UCI_CQI_INFO_UNPACK_FNS(pdu->uci_cqi_sr_pdu.cqi_information) - UL_CONFIG_UCI_SR_INFO_UNPACK_FNS(pdu->uci_cqi_sr_pdu.sr_information) - }; - - unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); - } - break; - case NFAPI_UL_CONFIG_UCI_CQI_SR_HARQ_PDU_TYPE: - { - unpack_tlv_t unpack_fns[] = - { - UL_CONFIG_UCI_UE_INFO_UNPACK_FNS(pdu->uci_cqi_sr_harq_pdu.ue_information) - UL_CONFIG_UCI_CQI_INFO_UNPACK_FNS(pdu->uci_cqi_sr_harq_pdu.cqi_information) - UL_CONFIG_UCI_SR_INFO_UNPACK_FNS(pdu->uci_cqi_sr_harq_pdu.sr_information) - UL_CONFIG_UCI_HARQ_INFO_UNPACK_FNS(pdu->uci_cqi_sr_harq_pdu.harq_information) - }; - - unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); - } - break; - case NFAPI_UL_CONFIG_SRS_PDU_TYPE: - { - unpack_tlv_t unpack_fns[] = - { - UL_CONFIG_SRS_PDU_UNPACK_FNS(pdu->srs_pdu) - }; - - unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); - } - break; - case NFAPI_UL_CONFIG_HARQ_BUFFER_PDU_TYPE: - { - unpack_tlv_t unpack_fns[] = - { - UL_CONFIG_UCI_UE_INFO_UNPACK_FNS(pdu->harq_buffer_pdu.ue_information) - }; - - unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); - } - break; - case NFAPI_UL_CONFIG_ULSCH_UCI_CSI_PDU_TYPE: - { - unpack_tlv_t unpack_fns[] = - { - UL_CONFIG_ULSCH_PDU_UNPACK_FNS(pdu->ulsch_uci_csi_pdu.ulsch_pdu) - UL_CONFIG_UCI_CQI_INFO_UNPACK_FNS(pdu->ulsch_uci_csi_pdu.csi_information) - }; - - unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); - } - break; - case NFAPI_UL_CONFIG_ULSCH_UCI_HARQ_PDU_TYPE: - { - unpack_tlv_t unpack_fns[] = - { - UL_CONFIG_ULSCH_PDU_UNPACK_FNS(pdu->ulsch_uci_harq_pdu.ulsch_pdu) - UL_CONFIG_UCI_HARQ_INFO_UNPACK_FNS(pdu->ulsch_uci_harq_pdu.harq_information) - }; - - unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); - } - break; - case NFAPI_UL_CONFIG_ULSCH_CSI_UCI_HARQ_PDU_TYPE: - { - unpack_tlv_t unpack_fns[] = - { - UL_CONFIG_ULSCH_PDU_UNPACK_FNS(pdu->ulsch_csi_uci_harq_pdu.ulsch_pdu) - UL_CONFIG_UCI_CQI_INFO_UNPACK_FNS(pdu->ulsch_csi_uci_harq_pdu.csi_information) - UL_CONFIG_UCI_HARQ_INFO_UNPACK_FNS(pdu->ulsch_csi_uci_harq_pdu.harq_information) - }; - - unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); - } - break; - case NFAPI_UL_CONFIG_NULSCH_PDU_TYPE: - { - unpack_tlv_t unpack_fns[] = - { - UL_CONFIG_NULSCH_PDU_UNPACK_FNS(pdu->nulsch_pdu) - }; - - unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); - } - break; - case NFAPI_UL_CONFIG_NRACH_PDU_TYPE: - { - unpack_tlv_t unpack_fns[] = - { - UL_CONFIG_NRACH_PDU_UNPACK_FNS(pdu->nrach_pdu) - }; - - unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); - } - break; - } - } - return 1; + return 1; } -static uint8_t unpack_ul_config_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config) -{ - nfapi_ul_config_request_t *pNfapiMsg = (nfapi_ul_config_request_t*)msg; - - unpack_p7_tlv_t unpack_fns[] = - { - { NFAPI_UL_CONFIG_REQUEST_BODY_TAG, &pNfapiMsg->ul_config_request_body, &unpack_ul_config_request_body_value}, - }; - - return (pull16(ppReadPackedMsg, &pNfapiMsg->sfn_sf, end) && - unpack_p7_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); +static uint8_t unpack_ul_config_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t *config) { + nfapi_ul_config_request_t *pNfapiMsg = (nfapi_ul_config_request_t *)msg; + unpack_p7_tlv_t unpack_fns[] = { + { NFAPI_UL_CONFIG_REQUEST_BODY_TAG, &pNfapiMsg->ul_config_request_body, &unpack_ul_config_request_body_value}, + }; + return (pull16(ppReadPackedMsg, &pNfapiMsg->sfn_sf, end) && + unpack_p7_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); } -static uint8_t unpack_hi_dci0_hi_pdu_rel8_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_hi_dci0_hi_pdu_rel8_t* hi_pdu_rel8 = (nfapi_hi_dci0_hi_pdu_rel8_t*)tlv; - - return( pull8(ppReadPackedMsg, &hi_pdu_rel8->resource_block_start, end) && - pull8(ppReadPackedMsg, &hi_pdu_rel8->cyclic_shift_2_for_drms, end) && - pull8(ppReadPackedMsg, &hi_pdu_rel8->hi_value, end) && - pull8(ppReadPackedMsg, &hi_pdu_rel8->i_phich, end) && - pull16(ppReadPackedMsg, &hi_pdu_rel8->transmission_power, end)); +static uint8_t unpack_hi_dci0_hi_pdu_rel8_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_hi_dci0_hi_pdu_rel8_t *hi_pdu_rel8 = (nfapi_hi_dci0_hi_pdu_rel8_t *)tlv; + return( pull8(ppReadPackedMsg, &hi_pdu_rel8->resource_block_start, end) && + pull8(ppReadPackedMsg, &hi_pdu_rel8->cyclic_shift_2_for_drms, end) && + pull8(ppReadPackedMsg, &hi_pdu_rel8->hi_value, end) && + pull8(ppReadPackedMsg, &hi_pdu_rel8->i_phich, end) && + pull16(ppReadPackedMsg, &hi_pdu_rel8->transmission_power, end)); } -static uint8_t unpack_hi_dci0_hi_pdu_rel10_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_hi_dci0_hi_pdu_rel10_t* hi_pdu_rel10 = (nfapi_hi_dci0_hi_pdu_rel10_t*)tlv; - - return (pull8(ppReadPackedMsg, &hi_pdu_rel10->flag_tb2, end) && - pull8(ppReadPackedMsg, &hi_pdu_rel10->hi_value_2, end)); +static uint8_t unpack_hi_dci0_hi_pdu_rel10_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_hi_dci0_hi_pdu_rel10_t *hi_pdu_rel10 = (nfapi_hi_dci0_hi_pdu_rel10_t *)tlv; + return (pull8(ppReadPackedMsg, &hi_pdu_rel10->flag_tb2, end) && + pull8(ppReadPackedMsg, &hi_pdu_rel10->hi_value_2, end)); } -static uint8_t unpack_hi_dci0_dci_pdu_rel8_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_hi_dci0_dci_pdu_rel8_t* dci_pdu_rel8 = (nfapi_hi_dci0_dci_pdu_rel8_t*)tlv; - - return (pull8(ppReadPackedMsg, &dci_pdu_rel8->dci_format, end) && - pull8(ppReadPackedMsg, &dci_pdu_rel8->cce_index, end) && - pull8(ppReadPackedMsg, &dci_pdu_rel8->aggregation_level, end) && - pull16(ppReadPackedMsg, &dci_pdu_rel8->rnti, end) && - pull8(ppReadPackedMsg, &dci_pdu_rel8->resource_block_start, end) && - pull8(ppReadPackedMsg, &dci_pdu_rel8->number_of_resource_block, end) && - pull8(ppReadPackedMsg, &dci_pdu_rel8->mcs_1, end) && - pull8(ppReadPackedMsg, &dci_pdu_rel8->cyclic_shift_2_for_drms, end) && - pull8(ppReadPackedMsg, &dci_pdu_rel8->frequency_hopping_enabled_flag, end) && - pull8(ppReadPackedMsg, &dci_pdu_rel8->frequency_hopping_bits, end) && - pull8(ppReadPackedMsg, &dci_pdu_rel8->new_data_indication_1, end) && - pull8(ppReadPackedMsg, &dci_pdu_rel8->ue_tx_antenna_seleciton, end) && - pull8(ppReadPackedMsg, &dci_pdu_rel8->tpc, end) && - pull8(ppReadPackedMsg, &dci_pdu_rel8->cqi_csi_request, end) && - pull8(ppReadPackedMsg, &dci_pdu_rel8->ul_index, end) && - pull8(ppReadPackedMsg, &dci_pdu_rel8->dl_assignment_index, end) && - pull32(ppReadPackedMsg, &dci_pdu_rel8->tpc_bitmap, end) && - pull16(ppReadPackedMsg, &dci_pdu_rel8->transmission_power, end)); +static uint8_t unpack_hi_dci0_dci_pdu_rel8_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_hi_dci0_dci_pdu_rel8_t *dci_pdu_rel8 = (nfapi_hi_dci0_dci_pdu_rel8_t *)tlv; + return (pull8(ppReadPackedMsg, &dci_pdu_rel8->dci_format, end) && + pull8(ppReadPackedMsg, &dci_pdu_rel8->cce_index, end) && + pull8(ppReadPackedMsg, &dci_pdu_rel8->aggregation_level, end) && + pull16(ppReadPackedMsg, &dci_pdu_rel8->rnti, end) && + pull8(ppReadPackedMsg, &dci_pdu_rel8->resource_block_start, end) && + pull8(ppReadPackedMsg, &dci_pdu_rel8->number_of_resource_block, end) && + pull8(ppReadPackedMsg, &dci_pdu_rel8->mcs_1, end) && + pull8(ppReadPackedMsg, &dci_pdu_rel8->cyclic_shift_2_for_drms, end) && + pull8(ppReadPackedMsg, &dci_pdu_rel8->frequency_hopping_enabled_flag, end) && + pull8(ppReadPackedMsg, &dci_pdu_rel8->frequency_hopping_bits, end) && + pull8(ppReadPackedMsg, &dci_pdu_rel8->new_data_indication_1, end) && + pull8(ppReadPackedMsg, &dci_pdu_rel8->ue_tx_antenna_seleciton, end) && + pull8(ppReadPackedMsg, &dci_pdu_rel8->tpc, end) && + pull8(ppReadPackedMsg, &dci_pdu_rel8->cqi_csi_request, end) && + pull8(ppReadPackedMsg, &dci_pdu_rel8->ul_index, end) && + pull8(ppReadPackedMsg, &dci_pdu_rel8->dl_assignment_index, end) && + pull32(ppReadPackedMsg, &dci_pdu_rel8->tpc_bitmap, end) && + pull16(ppReadPackedMsg, &dci_pdu_rel8->transmission_power, end)); } -static uint8_t unpack_hi_dci0_dci_pdu_rel10_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_hi_dci0_dci_pdu_rel10_t* dci_pdu_rel10 = (nfapi_hi_dci0_dci_pdu_rel10_t*)tlv; - - return (pull8(ppReadPackedMsg, &dci_pdu_rel10->cross_carrier_scheduling_flag, end) && - pull8(ppReadPackedMsg, &dci_pdu_rel10->carrier_indicator, end) && - pull8(ppReadPackedMsg, &dci_pdu_rel10->size_of_cqi_csi_feild, end) && - pull8(ppReadPackedMsg, &dci_pdu_rel10->srs_flag, end) && - pull8(ppReadPackedMsg, &dci_pdu_rel10->srs_request, end) && - pull8(ppReadPackedMsg, &dci_pdu_rel10->resource_allocation_flag, end) && - pull8(ppReadPackedMsg, &dci_pdu_rel10->resource_allocation_type, end) && - pull32(ppReadPackedMsg, &dci_pdu_rel10->resource_block_coding, end) && - pull8(ppReadPackedMsg, &dci_pdu_rel10->mcs_2, end) && - pull8(ppReadPackedMsg, &dci_pdu_rel10->new_data_indication_2, end) && - pull8(ppReadPackedMsg, &dci_pdu_rel10->number_of_antenna_ports, end) && - pull8(ppReadPackedMsg, &dci_pdu_rel10->tpmi, end) && - pull8(ppReadPackedMsg, &dci_pdu_rel10->total_dci_length_including_padding, end) && - pull8(ppReadPackedMsg, &dci_pdu_rel10->n_ul_rb, end)); +static uint8_t unpack_hi_dci0_dci_pdu_rel10_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_hi_dci0_dci_pdu_rel10_t *dci_pdu_rel10 = (nfapi_hi_dci0_dci_pdu_rel10_t *)tlv; + return (pull8(ppReadPackedMsg, &dci_pdu_rel10->cross_carrier_scheduling_flag, end) && + pull8(ppReadPackedMsg, &dci_pdu_rel10->carrier_indicator, end) && + pull8(ppReadPackedMsg, &dci_pdu_rel10->size_of_cqi_csi_feild, end) && + pull8(ppReadPackedMsg, &dci_pdu_rel10->srs_flag, end) && + pull8(ppReadPackedMsg, &dci_pdu_rel10->srs_request, end) && + pull8(ppReadPackedMsg, &dci_pdu_rel10->resource_allocation_flag, end) && + pull8(ppReadPackedMsg, &dci_pdu_rel10->resource_allocation_type, end) && + pull32(ppReadPackedMsg, &dci_pdu_rel10->resource_block_coding, end) && + pull8(ppReadPackedMsg, &dci_pdu_rel10->mcs_2, end) && + pull8(ppReadPackedMsg, &dci_pdu_rel10->new_data_indication_2, end) && + pull8(ppReadPackedMsg, &dci_pdu_rel10->number_of_antenna_ports, end) && + pull8(ppReadPackedMsg, &dci_pdu_rel10->tpmi, end) && + pull8(ppReadPackedMsg, &dci_pdu_rel10->total_dci_length_including_padding, end) && + pull8(ppReadPackedMsg, &dci_pdu_rel10->n_ul_rb, end)); } -static uint8_t unpack_hi_dci0_dci_pdu_rel12_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_hi_dci0_dci_pdu_rel12_t* dci_pdu_rel12 = (nfapi_hi_dci0_dci_pdu_rel12_t*)tlv; - - return ( pull8(ppReadPackedMsg, &dci_pdu_rel12->pscch_resource, end) && - pull8(ppReadPackedMsg, &dci_pdu_rel12->time_resource_pattern, end)); +static uint8_t unpack_hi_dci0_dci_pdu_rel12_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_hi_dci0_dci_pdu_rel12_t *dci_pdu_rel12 = (nfapi_hi_dci0_dci_pdu_rel12_t *)tlv; + return ( pull8(ppReadPackedMsg, &dci_pdu_rel12->pscch_resource, end) && + pull8(ppReadPackedMsg, &dci_pdu_rel12->time_resource_pattern, end)); } -static uint8_t unpack_hi_dci0_mpdcch_dci_pdu_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_hi_dci0_mpdcch_dci_pdu_rel13_t* value = (nfapi_hi_dci0_mpdcch_dci_pdu_rel13_t*)tlv; - - return (pull8(ppReadPackedMsg, &value->mpdcch_narrowband, end) && - pull8(ppReadPackedMsg, &value->number_of_prb_pairs, end) && - pull8(ppReadPackedMsg, &value->resource_block_assignment, end) && - pull8(ppReadPackedMsg, &value->mpdcch_transmission_type, end) && - pull8(ppReadPackedMsg, &value->start_symbol, end) && - pull8(ppReadPackedMsg, &value->ecce_index, end) && - pull8(ppReadPackedMsg, &value->aggreagation_level, end) && - pull8(ppReadPackedMsg, &value->rnti_type, end) && - pull16(ppReadPackedMsg, &value->rnti, end) && - pull8(ppReadPackedMsg, &value->ce_mode, end) && - pull16(ppReadPackedMsg, &value->drms_scrambling_init, end) && - pull16(ppReadPackedMsg, &value->initial_transmission_sf_io, end) && - pull16(ppReadPackedMsg, &value->transmission_power, end) && - pull8(ppReadPackedMsg, &value->dci_format, end) && - pull8(ppReadPackedMsg, &value->resource_block_start, end) && - pull8(ppReadPackedMsg, &value->number_of_resource_blocks, end) && - pull8(ppReadPackedMsg, &value->mcs, end) && - pull8(ppReadPackedMsg, &value->pusch_repetition_levels, end) && - pull8(ppReadPackedMsg, &value->frequency_hopping_flag, end) && - pull8(ppReadPackedMsg, &value->new_data_indication, end) && - pull8(ppReadPackedMsg, &value->harq_process, end) && - pull8(ppReadPackedMsg, &value->redudency_version, end) && - pull8(ppReadPackedMsg, &value->tpc, end) && - pull8(ppReadPackedMsg, &value->csi_request, end) && - pull8(ppReadPackedMsg, &value->ul_inex, end) && - pull8(ppReadPackedMsg, &value->dai_presence_flag, end) && - pull8(ppReadPackedMsg, &value->dl_assignment_index, end) && - pull8(ppReadPackedMsg, &value->srs_request, end) && - pull8(ppReadPackedMsg, &value->dci_subframe_repetition_number, end) && - pull32(ppReadPackedMsg, &value->tcp_bitmap, end) && - pull8(ppReadPackedMsg, &value->total_dci_length_include_padding, end) && - pull8(ppReadPackedMsg, &value->number_of_tx_antenna_ports, end) && - pullarray16(ppReadPackedMsg, value->precoding_value, NFAPI_MAX_TX_PHYSICAL_ANTENNA_PORTS, value->number_of_tx_antenna_ports, end)); +static uint8_t unpack_hi_dci0_mpdcch_dci_pdu_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_hi_dci0_mpdcch_dci_pdu_rel13_t *value = (nfapi_hi_dci0_mpdcch_dci_pdu_rel13_t *)tlv; + return (pull8(ppReadPackedMsg, &value->mpdcch_narrowband, end) && + pull8(ppReadPackedMsg, &value->number_of_prb_pairs, end) && + pull8(ppReadPackedMsg, &value->resource_block_assignment, end) && + pull8(ppReadPackedMsg, &value->mpdcch_transmission_type, end) && + pull8(ppReadPackedMsg, &value->start_symbol, end) && + pull8(ppReadPackedMsg, &value->ecce_index, end) && + pull8(ppReadPackedMsg, &value->aggreagation_level, end) && + pull8(ppReadPackedMsg, &value->rnti_type, end) && + pull16(ppReadPackedMsg, &value->rnti, end) && + pull8(ppReadPackedMsg, &value->ce_mode, end) && + pull16(ppReadPackedMsg, &value->drms_scrambling_init, end) && + pull16(ppReadPackedMsg, &value->initial_transmission_sf_io, end) && + pull16(ppReadPackedMsg, &value->transmission_power, end) && + pull8(ppReadPackedMsg, &value->dci_format, end) && + pull8(ppReadPackedMsg, &value->resource_block_start, end) && + pull8(ppReadPackedMsg, &value->number_of_resource_blocks, end) && + pull8(ppReadPackedMsg, &value->mcs, end) && + pull8(ppReadPackedMsg, &value->pusch_repetition_levels, end) && + pull8(ppReadPackedMsg, &value->frequency_hopping_flag, end) && + pull8(ppReadPackedMsg, &value->new_data_indication, end) && + pull8(ppReadPackedMsg, &value->harq_process, end) && + pull8(ppReadPackedMsg, &value->redudency_version, end) && + pull8(ppReadPackedMsg, &value->tpc, end) && + pull8(ppReadPackedMsg, &value->csi_request, end) && + pull8(ppReadPackedMsg, &value->ul_inex, end) && + pull8(ppReadPackedMsg, &value->dai_presence_flag, end) && + pull8(ppReadPackedMsg, &value->dl_assignment_index, end) && + pull8(ppReadPackedMsg, &value->srs_request, end) && + pull8(ppReadPackedMsg, &value->dci_subframe_repetition_number, end) && + pull32(ppReadPackedMsg, &value->tcp_bitmap, end) && + pull8(ppReadPackedMsg, &value->total_dci_length_include_padding, end) && + pull8(ppReadPackedMsg, &value->number_of_tx_antenna_ports, end) && + pullarray16(ppReadPackedMsg, value->precoding_value, NFAPI_MAX_TX_PHYSICAL_ANTENNA_PORTS, value->number_of_tx_antenna_ports, end)); } -static uint8_t unpack_hi_dci0_npdcch_dci_pdu_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_hi_dci0_npdcch_dci_pdu_rel13_t* value = (nfapi_hi_dci0_npdcch_dci_pdu_rel13_t*)tlv; - - return (pull8(ppReadPackedMsg, &value->ncce_index, end) && - pull8(ppReadPackedMsg, &value->aggregation_level, end) && - pull8(ppReadPackedMsg, &value->start_symbol, end) && - pull16(ppReadPackedMsg, &value->rnti, end) && - pull8(ppReadPackedMsg, &value->scrambling_reinitialization_batch_index, end) && - pull8(ppReadPackedMsg, &value->nrs_antenna_ports_assumed_by_the_ue, end) && - pull8(ppReadPackedMsg, &value->subcarrier_indication, end) && - pull8(ppReadPackedMsg, &value->resource_assignment, end) && - pull8(ppReadPackedMsg, &value->scheduling_delay, end) && - pull8(ppReadPackedMsg, &value->mcs, end) && - pull8(ppReadPackedMsg, &value->redudancy_version, end) && - pull8(ppReadPackedMsg, &value->repetition_number, end) && - pull8(ppReadPackedMsg, &value->new_data_indicator, end) && - pull8(ppReadPackedMsg, &value->dci_subframe_repetition_number, end)); +static uint8_t unpack_hi_dci0_npdcch_dci_pdu_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_hi_dci0_npdcch_dci_pdu_rel13_t *value = (nfapi_hi_dci0_npdcch_dci_pdu_rel13_t *)tlv; + return (pull8(ppReadPackedMsg, &value->ncce_index, end) && + pull8(ppReadPackedMsg, &value->aggregation_level, end) && + pull8(ppReadPackedMsg, &value->start_symbol, end) && + pull16(ppReadPackedMsg, &value->rnti, end) && + pull8(ppReadPackedMsg, &value->scrambling_reinitialization_batch_index, end) && + pull8(ppReadPackedMsg, &value->nrs_antenna_ports_assumed_by_the_ue, end) && + pull8(ppReadPackedMsg, &value->subcarrier_indication, end) && + pull8(ppReadPackedMsg, &value->resource_assignment, end) && + pull8(ppReadPackedMsg, &value->scheduling_delay, end) && + pull8(ppReadPackedMsg, &value->mcs, end) && + pull8(ppReadPackedMsg, &value->redudancy_version, end) && + pull8(ppReadPackedMsg, &value->repetition_number, end) && + pull8(ppReadPackedMsg, &value->new_data_indicator, end) && + pull8(ppReadPackedMsg, &value->dci_subframe_repetition_number, end)); } -static uint8_t unpack_hi_dci0_request_body_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) -{ - nfapi_hi_dci0_request_body_t* value = (nfapi_hi_dci0_request_body_t*)tlv; +static uint8_t unpack_hi_dci0_request_body_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end, nfapi_p7_codec_config_t *config) { + nfapi_hi_dci0_request_body_t *value = (nfapi_hi_dci0_request_body_t *)tlv; - if(!(pull16(ppReadPackedMsg, &value->sfnsf, end) && - pull8(ppReadPackedMsg, &value->number_of_dci, end) && - pull8(ppReadPackedMsg, &value->number_of_hi, end))) - return 0; + if(!(pull16(ppReadPackedMsg, &value->sfnsf, end) && + pull8(ppReadPackedMsg, &value->number_of_dci, end) && + pull8(ppReadPackedMsg, &value->number_of_hi, end))) + return 0; - uint8_t totalNumPdus = value->number_of_hi + value->number_of_dci; + uint8_t totalNumPdus = value->number_of_hi + value->number_of_dci; - if(totalNumPdus > NFAPI_HI_DCI0_MAX_PDU) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s number of dci0 pdu's exceed maxium (count:%d max:%d)\n", __FUNCTION__, totalNumPdus, NFAPI_HI_DCI0_MAX_PDU); - return 0; - } + if(totalNumPdus > NFAPI_HI_DCI0_MAX_PDU) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s number of dci0 pdu's exceed maxium (count:%d max:%d)\n", __FUNCTION__, totalNumPdus, NFAPI_HI_DCI0_MAX_PDU); + return 0; + } - if(totalNumPdus > 0) - { - value->hi_dci0_pdu_list = (nfapi_hi_dci0_request_pdu_t*)nfapi_p7_allocate(sizeof(nfapi_hi_dci0_request_pdu_t) * totalNumPdus, config); - if(value->hi_dci0_pdu_list == NULL) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s failed to allocate hi dci0 pdu list (count:%d)\n", __FUNCTION__, totalNumPdus); - return 0; - } - } - else - { - value->hi_dci0_pdu_list = 0; - } + if(totalNumPdus > 0) { + value->hi_dci0_pdu_list = (nfapi_hi_dci0_request_pdu_t *)nfapi_p7_allocate(sizeof(nfapi_hi_dci0_request_pdu_t) * totalNumPdus, config); - uint8_t i; - for(i = 0; i < totalNumPdus; ++i) - { - nfapi_hi_dci0_request_pdu_t* pdu = &(value->hi_dci0_pdu_list[i]); + if(value->hi_dci0_pdu_list == NULL) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s failed to allocate hi dci0 pdu list (count:%d)\n", __FUNCTION__, totalNumPdus); + return 0; + } + } else { + value->hi_dci0_pdu_list = 0; + } - if(!(pull8(ppReadPackedMsg, &pdu->pdu_type, end) && - pull8(ppReadPackedMsg, &pdu->pdu_size, end))) - return 0; + uint8_t i; - uint8_t *packedPduEnd = (*ppReadPackedMsg) + pdu->pdu_size - 2; + for(i = 0; i < totalNumPdus; ++i) { + nfapi_hi_dci0_request_pdu_t *pdu = &(value->hi_dci0_pdu_list[i]); - if(packedPduEnd > end) - { - // pdu end if past buffer end - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s pdu size to big %d %d\n", __FUNCTION__, packedPduEnd, end); - return 0; - } + if(!(pull8(ppReadPackedMsg, &pdu->pdu_type, end) && + pull8(ppReadPackedMsg, &pdu->pdu_size, end))) + return 0; - switch(pdu->pdu_type) - { - case NFAPI_HI_DCI0_HI_PDU_TYPE: - { - unpack_tlv_t unpack_fns[] = - { - { NFAPI_HI_DCI0_REQUEST_HI_PDU_REL8_TAG, &pdu->hi_pdu.hi_pdu_rel8, &unpack_hi_dci0_hi_pdu_rel8_value}, - { NFAPI_HI_DCI0_REQUEST_HI_PDU_REL10_TAG, &pdu->hi_pdu.hi_pdu_rel10, &unpack_hi_dci0_hi_pdu_rel10_value}, - }; + uint8_t *packedPduEnd = (*ppReadPackedMsg) + pdu->pdu_size - 2; - unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); - } - break; - case NFAPI_HI_DCI0_DCI_PDU_TYPE: - { - unpack_tlv_t unpack_fns[] = - { - { NFAPI_HI_DCI0_REQUEST_DCI_PDU_REL8_TAG, &pdu->dci_pdu.dci_pdu_rel8, &unpack_hi_dci0_dci_pdu_rel8_value}, - { NFAPI_HI_DCI0_REQUEST_DCI_PDU_REL10_TAG, &pdu->dci_pdu.dci_pdu_rel10, &unpack_hi_dci0_dci_pdu_rel10_value}, - { NFAPI_HI_DCI0_REQUEST_DCI_PDU_REL12_TAG, &pdu->dci_pdu.dci_pdu_rel12, &unpack_hi_dci0_dci_pdu_rel12_value}, - }; + if(packedPduEnd > end) { + // pdu end if past buffer end + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s pdu size to big %d %d\n", __FUNCTION__, packedPduEnd, end); + return 0; + } - unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); - } - break; - case NFAPI_HI_DCI0_EPDCCH_DCI_PDU_TYPE: - { - unpack_tlv_t unpack_fns[] = - { - { NFAPI_HI_DCI0_REQUEST_EPDCCH_DCI_PDU_REL8_TAG, &pdu->epdcch_dci_pdu.epdcch_dci_pdu_rel8, &unpack_hi_dci0_dci_pdu_rel8_value}, - { NFAPI_HI_DCI0_REQUEST_EPDCCH_DCI_PDU_REL10_TAG, &pdu->epdcch_dci_pdu.epdcch_dci_pdu_rel10, &unpack_hi_dci0_dci_pdu_rel10_value}, - { NFAPI_HI_DCI0_REQUEST_EPDCCH_PARAMETERS_REL11_TAG, &pdu->epdcch_dci_pdu.epdcch_parameters_rel11, &unpack_dl_config_epdcch_params_rel11_value}, - }; + switch(pdu->pdu_type) { + case NFAPI_HI_DCI0_HI_PDU_TYPE: { + unpack_tlv_t unpack_fns[] = { + { NFAPI_HI_DCI0_REQUEST_HI_PDU_REL8_TAG, &pdu->hi_pdu.hi_pdu_rel8, &unpack_hi_dci0_hi_pdu_rel8_value}, + { NFAPI_HI_DCI0_REQUEST_HI_PDU_REL10_TAG, &pdu->hi_pdu.hi_pdu_rel10, &unpack_hi_dci0_hi_pdu_rel10_value}, + }; + unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); + } + break; - unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); - } - break; - case NFAPI_HI_DCI0_MPDCCH_DCI_PDU_TYPE: - { - unpack_tlv_t unpack_fns[] = - { - { NFAPI_HI_DCI0_REQUEST_MPDCCH_DCI_PDU_REL13_TAG, &pdu->mpdcch_dci_pdu.mpdcch_dci_pdu_rel13, &unpack_hi_dci0_mpdcch_dci_pdu_rel13_value}, - }; + case NFAPI_HI_DCI0_DCI_PDU_TYPE: { + unpack_tlv_t unpack_fns[] = { + { NFAPI_HI_DCI0_REQUEST_DCI_PDU_REL8_TAG, &pdu->dci_pdu.dci_pdu_rel8, &unpack_hi_dci0_dci_pdu_rel8_value}, + { NFAPI_HI_DCI0_REQUEST_DCI_PDU_REL10_TAG, &pdu->dci_pdu.dci_pdu_rel10, &unpack_hi_dci0_dci_pdu_rel10_value}, + { NFAPI_HI_DCI0_REQUEST_DCI_PDU_REL12_TAG, &pdu->dci_pdu.dci_pdu_rel12, &unpack_hi_dci0_dci_pdu_rel12_value}, + }; + unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); + } + break; - unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); - } - break; - case NFAPI_HI_DCI0_NPDCCH_DCI_PDU_TYPE: - { - unpack_tlv_t unpack_fns[] = - { - { NFAPI_HI_DCI0_REQUEST_NPDCCH_DCI_PDU_REL13_TAG, &pdu->npdcch_dci_pdu.npdcch_dci_pdu_rel13, &unpack_hi_dci0_npdcch_dci_pdu_rel13_value}, - }; + case NFAPI_HI_DCI0_EPDCCH_DCI_PDU_TYPE: { + unpack_tlv_t unpack_fns[] = { + { NFAPI_HI_DCI0_REQUEST_EPDCCH_DCI_PDU_REL8_TAG, &pdu->epdcch_dci_pdu.epdcch_dci_pdu_rel8, &unpack_hi_dci0_dci_pdu_rel8_value}, + { NFAPI_HI_DCI0_REQUEST_EPDCCH_DCI_PDU_REL10_TAG, &pdu->epdcch_dci_pdu.epdcch_dci_pdu_rel10, &unpack_hi_dci0_dci_pdu_rel10_value}, + { NFAPI_HI_DCI0_REQUEST_EPDCCH_PARAMETERS_REL11_TAG, &pdu->epdcch_dci_pdu.epdcch_parameters_rel11, &unpack_dl_config_epdcch_params_rel11_value}, + }; + unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); + } + break; - unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); - } - break; - default: - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "FIXME : Invalid pdu type %d \n", pdu->pdu_type ); - } - break; - }; - } + case NFAPI_HI_DCI0_MPDCCH_DCI_PDU_TYPE: { + unpack_tlv_t unpack_fns[] = { + { NFAPI_HI_DCI0_REQUEST_MPDCCH_DCI_PDU_REL13_TAG, &pdu->mpdcch_dci_pdu.mpdcch_dci_pdu_rel13, &unpack_hi_dci0_mpdcch_dci_pdu_rel13_value}, + }; + unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); + } + break; - return 1; + case NFAPI_HI_DCI0_NPDCCH_DCI_PDU_TYPE: { + unpack_tlv_t unpack_fns[] = { + { NFAPI_HI_DCI0_REQUEST_NPDCCH_DCI_PDU_REL13_TAG, &pdu->npdcch_dci_pdu.npdcch_dci_pdu_rel13, &unpack_hi_dci0_npdcch_dci_pdu_rel13_value}, + }; + unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); + } + break; + + default: { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "FIXME : Invalid pdu type %d \n", pdu->pdu_type ); + } + break; + }; + } + + return 1; } //unpack_ul_dci_pdu_list_value -static uint8_t unpack_ul_dci_pdu_list_value(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg) -{ - nfapi_nr_ul_dci_request_pdus_t* value = (nfapi_nr_ul_dci_request_pdus_t*)msg; - - for(uint8_t i = 0; i < MAX_DCI_CORESET; ++i) - { - if(!pull16(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].RNTI, end) && - pull16(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].ScramblingId, end) && +static uint8_t unpack_ul_dci_pdu_list_value(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg) { + nfapi_nr_ul_dci_request_pdus_t *value = (nfapi_nr_ul_dci_request_pdus_t *)msg; - pull16(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].ScramblingRNTI, end) && - pull8(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].CceIndex, end) && - pull8(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].AggregationLevel, end) && - pull8(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].beta_PDCCH_1_0, end) && + for(uint8_t i = 0; i < MAX_DCI_CORESET; ++i) { + if(!pull16(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].RNTI, end) && + pull16(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].ScramblingId, end) && + pull16(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].ScramblingRNTI, end) && + pull8(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].CceIndex, end) && + pull8(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].AggregationLevel, end) && + pull8(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].beta_PDCCH_1_0, end) && + pull8(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].powerControlOffsetSS, end) && + pull16(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].PayloadSizeBits, end) && + pullarray8(ppReadPackedMsg, value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].Payload, DCI_PAYLOAD_BYTE_LEN, value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].PayloadSizeBits, end)); - pull8(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].powerControlOffsetSS, end) && - pull16(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].PayloadSizeBits, end) && - - pullarray8(ppReadPackedMsg, value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].Payload, DCI_PAYLOAD_BYTE_LEN, value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].PayloadSizeBits, end)); - - return 0; - } + return 0; + } - return (pull16(ppReadPackedMsg, &value->PDUType, end) && - pull16(ppReadPackedMsg, &value->PDUSize, end) && - pull16(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.BWPSize, end) && - pull16(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.BWPStart, end) && - pull8(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.SubcarrierSpacing, end) && - pull8(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.CyclicPrefix, end) && - - pull8(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.StartSymbolIndex, end) && - pull8(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.DurationSymbols, end) && - pullarray8(ppReadPackedMsg, value->pdcch_pdu.pdcch_pdu_rel15.FreqDomainResource, 6, 6, end) && - pull8(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.CceRegMappingType, end) && - - pull8(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.RegBundleSize, end) && - pull8(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.InterleaverSize, end) && - pull8(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.CoreSetType, end) && - pull16(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.ShiftIndex, end) && - - pull8(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.precoderGranularity, end) && - pull16(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.numDlDci, end)); - + return (pull16(ppReadPackedMsg, &value->PDUType, end) && + pull16(ppReadPackedMsg, &value->PDUSize, end) && + pull16(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.BWPSize, end) && + pull16(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.BWPStart, end) && + pull8(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.SubcarrierSpacing, end) && + pull8(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.CyclicPrefix, end) && + pull8(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.StartSymbolIndex, end) && + pull8(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.DurationSymbols, end) && + pullarray8(ppReadPackedMsg, value->pdcch_pdu.pdcch_pdu_rel15.FreqDomainResource, 6, 6, end) && + pull8(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.CceRegMappingType, end) && + pull8(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.RegBundleSize, end) && + pull8(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.InterleaverSize, end) && + pull8(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.CoreSetType, end) && + pull16(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.ShiftIndex, end) && + pull8(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.precoderGranularity, end) && + pull16(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.numDlDci, end)); } -static uint8_t unpack_ul_dci_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config) -{ -nfapi_nr_ul_dci_request_t *pNfapiMsg = (nfapi_nr_ul_dci_request_t*)msg; - - if (!(pull16(ppReadPackedMsg, &pNfapiMsg->SFN, end) && - pull16(ppReadPackedMsg, &pNfapiMsg->Slot, end) && - pull8(ppReadPackedMsg, &pNfapiMsg->numPdus, end) - )) - return 0; - for(int i=0; i< pNfapiMsg->numPdus; i++) - { - if (!unpack_ul_dci_pdu_list_value(ppReadPackedMsg, end, &pNfapiMsg->ul_dci_pdu_list[i])) - return 0; - } +static uint8_t unpack_ul_dci_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t *config) { + nfapi_nr_ul_dci_request_t *pNfapiMsg = (nfapi_nr_ul_dci_request_t *)msg; - return 1; + if (!(pull16(ppReadPackedMsg, &pNfapiMsg->SFN, end) && + pull16(ppReadPackedMsg, &pNfapiMsg->Slot, end) && + pull8(ppReadPackedMsg, &pNfapiMsg->numPdus, end) + )) + return 0; + for(int i=0; i< pNfapiMsg->numPdus; i++) { + if (!unpack_ul_dci_pdu_list_value(ppReadPackedMsg, end, &pNfapiMsg->ul_dci_pdu_list[i])) + return 0; + } + + return 1; } -static uint8_t unpack_hi_dci0_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config) -{ - nfapi_hi_dci0_request_t *pNfapiMsg = (nfapi_hi_dci0_request_t*)msg; - - unpack_p7_tlv_t unpack_fns[] = - { - { NFAPI_HI_DCI0_REQUEST_BODY_TAG, &pNfapiMsg->hi_dci0_request_body, &unpack_hi_dci0_request_body_value}, - }; - - return (pull16(ppReadPackedMsg, &pNfapiMsg->sfn_sf, end) && - unpack_p7_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); - +static uint8_t unpack_hi_dci0_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t *config) { + nfapi_hi_dci0_request_t *pNfapiMsg = (nfapi_hi_dci0_request_t *)msg; + unpack_p7_tlv_t unpack_fns[] = { + { NFAPI_HI_DCI0_REQUEST_BODY_TAG, &pNfapiMsg->hi_dci0_request_body, &unpack_hi_dci0_request_body_value}, + }; + return (pull16(ppReadPackedMsg, &pNfapiMsg->sfn_sf, end) && + unpack_p7_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); } -static uint8_t unpack_tx_data_pdu_list_value(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg) -{ - nfapi_nr_pdu_t* pNfapiMsg = (nfapi_nr_pdu_t*)msg; +static uint8_t unpack_tx_data_pdu_list_value(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg) { + nfapi_nr_pdu_t *pNfapiMsg = (nfapi_nr_pdu_t *)msg; - if(!(pull32(ppReadPackedMsg, &pNfapiMsg->num_TLV, end) && - pull16(ppReadPackedMsg, &pNfapiMsg->PDU_index, end) && - pull16(ppReadPackedMsg, &pNfapiMsg->PDU_length, end) - )) - return 0; + if(!(pull32(ppReadPackedMsg, &pNfapiMsg->num_TLV, end) && + pull16(ppReadPackedMsg, &pNfapiMsg->PDU_index, end) && + pull16(ppReadPackedMsg, &pNfapiMsg->PDU_length, end) + )) + return 0; - uint16_t i = 0; - uint16_t total_number_of_tlvs = pNfapiMsg->num_TLV; - for(; i < total_number_of_tlvs; ++i) - { - - if (!(pull16(ppReadPackedMsg, &pNfapiMsg->TLVs[i].length, end) && - pull16(ppReadPackedMsg, &pNfapiMsg->TLVs[i].tag, end))) - return 0; + uint16_t i = 0; + uint16_t total_number_of_tlvs = pNfapiMsg->num_TLV; - switch(pNfapiMsg->TLVs[i].tag){ - case 0: - { - if(!pullarray32(ppReadPackedMsg, pNfapiMsg->TLVs[i].value.direct, 16384, pNfapiMsg->TLVs[i].length, end)) - return 0; - break; + for(; i < total_number_of_tlvs; ++i) { + if (!(pull16(ppReadPackedMsg, &pNfapiMsg->TLVs[i].length, end) && + pull16(ppReadPackedMsg, &pNfapiMsg->TLVs[i].tag, end))) + return 0; - } + switch(pNfapiMsg->TLVs[i].tag) { + case 0: { + if(!pullarray32(ppReadPackedMsg, pNfapiMsg->TLVs[i].value.direct, 16384, pNfapiMsg->TLVs[i].length, end)) + return 0; - case 1: - { - if(!pullarray32(ppReadPackedMsg, pNfapiMsg->TLVs[i].value.ptr, pNfapiMsg->TLVs[i].length , pNfapiMsg->TLVs[i].length, end)) - return 0; - break; + break; + } - } - - default: - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "FIXME : Invalid tag value %d \n", pNfapiMsg->TLVs[i].tag ); - break; - } - - } - } + case 1: { + if(!pullarray32(ppReadPackedMsg, pNfapiMsg->TLVs[i].value.ptr, pNfapiMsg->TLVs[i].length, pNfapiMsg->TLVs[i].length, end)) + return 0; + break; + } - return 1; + default: { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "FIXME : Invalid tag value %d \n", pNfapiMsg->TLVs[i].tag ); + break; + } + } + } + + return 1; } -static uint8_t unpack_tx_data_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config) -{ - nfapi_nr_tx_data_request_t *pNfapiMsg = (nfapi_nr_tx_data_request_t*)msg; +static uint8_t unpack_tx_data_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t *config) { + nfapi_nr_tx_data_request_t *pNfapiMsg = (nfapi_nr_tx_data_request_t *)msg; - if(!(pull16(ppReadPackedMsg, &pNfapiMsg->SFN, end) && - pull16(ppReadPackedMsg, &pNfapiMsg->Slot, end) && - pull16(ppReadPackedMsg, &pNfapiMsg->Number_of_PDUs, end))) - return 0; + if(!(pull16(ppReadPackedMsg, &pNfapiMsg->SFN, end) && + pull16(ppReadPackedMsg, &pNfapiMsg->Slot, end) && + pull16(ppReadPackedMsg, &pNfapiMsg->Number_of_PDUs, end))) + return 0; - for(int i=0; i< pNfapiMsg->Number_of_PDUs; i++) - { - if (!unpack_tx_data_pdu_list_value(ppReadPackedMsg, end, &pNfapiMsg->pdu_list[i])) - return 0; - } + for(int i=0; i< pNfapiMsg->Number_of_PDUs; i++) { + if (!unpack_tx_data_pdu_list_value(ppReadPackedMsg, end, &pNfapiMsg->pdu_list[i])) + return 0; + } - return 1; + return 1; } -static uint8_t unpack_tx_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config) -{ - uint8_t proceed = 1; - nfapi_tx_request_t *pNfapiMsg = (nfapi_tx_request_t*)msg; +static uint8_t unpack_tx_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t *config) { + uint8_t proceed = 1; + nfapi_tx_request_t *pNfapiMsg = (nfapi_tx_request_t *)msg; - if(pull16(ppReadPackedMsg, &pNfapiMsg->sfn_sf, end) == 0) - return 0; + if(pull16(ppReadPackedMsg, &pNfapiMsg->sfn_sf, end) == 0) + return 0; - while (((uint8_t*)(*ppReadPackedMsg) < end) && proceed) - { - nfapi_tl_t generic_tl; - if(unpack_tl(ppReadPackedMsg, &generic_tl, end) == 0) - return 0; + while (((uint8_t *)(*ppReadPackedMsg) < end) && proceed) { + nfapi_tl_t generic_tl; - switch(generic_tl.tag) - { - case NFAPI_TX_REQUEST_BODY_TAG: - { - pNfapiMsg->tx_request_body.tl = generic_tl; + if(unpack_tl(ppReadPackedMsg, &generic_tl, end) == 0) + return 0; - if( pull16(ppReadPackedMsg, &pNfapiMsg->tx_request_body.number_of_pdus, end) == 0) - return 0; + switch(generic_tl.tag) { + case NFAPI_TX_REQUEST_BODY_TAG: { + pNfapiMsg->tx_request_body.tl = generic_tl; - if(pNfapiMsg->tx_request_body.number_of_pdus > NFAPI_TX_MAX_PDU) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s number of tx pdu's exceed maxium (count:%d max:%d)\n", __FUNCTION__, pNfapiMsg->tx_request_body.number_of_pdus, NFAPI_TX_MAX_PDU); - return 0; - } + if( pull16(ppReadPackedMsg, &pNfapiMsg->tx_request_body.number_of_pdus, end) == 0) + return 0; - if(pNfapiMsg->tx_request_body.number_of_pdus > 0) - { - pNfapiMsg->tx_request_body.tx_pdu_list = (nfapi_tx_request_pdu_t*)nfapi_p7_allocate(sizeof(nfapi_tx_request_pdu_t) * pNfapiMsg->tx_request_body.number_of_pdus, config); - if(pNfapiMsg->tx_request_body.tx_pdu_list == NULL) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s failed to allocate tx pdu list (count:%d)\n", __FUNCTION__, pNfapiMsg->tx_request_body.number_of_pdus); - return 0; - } - } - else - { - pNfapiMsg->tx_request_body.tx_pdu_list = 0; - } + if(pNfapiMsg->tx_request_body.number_of_pdus > NFAPI_TX_MAX_PDU) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s number of tx pdu's exceed maxium (count:%d max:%d)\n", __FUNCTION__, pNfapiMsg->tx_request_body.number_of_pdus, NFAPI_TX_MAX_PDU); + return 0; + } + if(pNfapiMsg->tx_request_body.number_of_pdus > 0) { + pNfapiMsg->tx_request_body.tx_pdu_list = (nfapi_tx_request_pdu_t *)nfapi_p7_allocate(sizeof(nfapi_tx_request_pdu_t) * pNfapiMsg->tx_request_body.number_of_pdus, config); - uint16_t i; - uint16_t totalNumPdus = pNfapiMsg->tx_request_body.number_of_pdus; - for(i = 0; i < totalNumPdus; ++i) - { - nfapi_tx_request_pdu_t* pdu = &(pNfapiMsg->tx_request_body.tx_pdu_list[i]); - if (pdu) { - uint16_t length = 0; - uint16_t index = 0; - - if(!(pull16(ppReadPackedMsg, &length, end) && - pull16(ppReadPackedMsg, &index, end))) - return 0; - - pdu->pdu_length = length; - pdu->pdu_index = index; - - - // TODO : May need to rethink this bit - pdu->num_segments = 1; - pdu->segments[0].segment_length = pdu->pdu_length; - pdu->segments[0].segment_data = nfapi_p7_allocate(pdu->pdu_length, config); - - if(pdu->segments[0].segment_data) - { - if(!pullarray8(ppReadPackedMsg, pdu->segments[0].segment_data, pdu->segments[0].segment_length, pdu->segments[0].segment_length, end)) - return 0; - if (pdu->segments[0].segment_length == 3) - { - NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() BCH? segment_data:%x %x %x\n", __FUNCTION__, - pdu->segments[0].segment_data[0], - pdu->segments[0].segment_data[1], - pdu->segments[0].segment_data[2] - ); - } - } - else - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "unpack_tx_request: Failed to allocate pdu (len:%d) %d/%d %d\n", pdu->pdu_length, totalNumPdus, i, pdu->pdu_index); - } - } else { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "NULL pdu\n"); - } - } - } - break; - default: - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "unpack_tx_request FIXME : Invalid pdu type %d \n", generic_tl.tag ); - } - break; - }; - } - - return 1; -} - -static uint8_t unpack_ue_release_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config) -{ - uint8_t proceed = 1; - nfapi_ue_release_request_t *pNfapiMsg = (nfapi_ue_release_request_t*)msg; - - if(pull16(ppReadPackedMsg, &pNfapiMsg->sfn_sf, end) == 0) - return 0; - - while (((uint8_t*)(*ppReadPackedMsg) < end) && proceed) - { - nfapi_tl_t generic_tl; - if(unpack_tl(ppReadPackedMsg, &generic_tl, end) == 0) + if(pNfapiMsg->tx_request_body.tx_pdu_list == NULL) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s failed to allocate tx pdu list (count:%d)\n", __FUNCTION__, pNfapiMsg->tx_request_body.number_of_pdus); return 0; + } + } else { + pNfapiMsg->tx_request_body.tx_pdu_list = 0; + } - switch(generic_tl.tag) - { - case NFAPI_UE_RELEASE_BODY_TAG: - { - pNfapiMsg->ue_release_request_body.tl = generic_tl; - if( pull16(ppReadPackedMsg, &pNfapiMsg->ue_release_request_body.number_of_TLVs, end) == 0) - return 0; + uint16_t i; + uint16_t totalNumPdus = pNfapiMsg->tx_request_body.number_of_pdus; - if(pNfapiMsg->ue_release_request_body.number_of_TLVs > NFAPI_RELEASE_MAX_RNTI) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s number of relese rnti's exceed maxium (count:%d max:%d)\n", __FUNCTION__, pNfapiMsg->ue_release_request_body.number_of_TLVs, NFAPI_RELEASE_MAX_RNTI); - return 0; - } else { - uint8_t j; - uint16_t num = pNfapiMsg->ue_release_request_body.number_of_TLVs; - for(j = 0; j < num; ++j){ - if(pull16(ppReadPackedMsg, &pNfapiMsg->ue_release_request_body.ue_release_request_TLVs_list[j].rnti, end) == 0){ - return 0; - } - } - } + for(i = 0; i < totalNumPdus; ++i) { + nfapi_tx_request_pdu_t *pdu = &(pNfapiMsg->tx_request_body.tx_pdu_list[i]); + + if (pdu) { + uint16_t length = 0; + uint16_t index = 0; + + if(!(pull16(ppReadPackedMsg, &length, end) && + pull16(ppReadPackedMsg, &index, end))) + return 0; + + pdu->pdu_length = length; + pdu->pdu_index = index; + // TODO : May need to rethink this bit + pdu->num_segments = 1; + pdu->segments[0].segment_length = pdu->pdu_length; + pdu->segments[0].segment_data = nfapi_p7_allocate(pdu->pdu_length, config); + + if(pdu->segments[0].segment_data) { + if(!pullarray8(ppReadPackedMsg, pdu->segments[0].segment_data, pdu->segments[0].segment_length, pdu->segments[0].segment_length, end)) + return 0; + + if (pdu->segments[0].segment_length == 3) { + NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() BCH? segment_data:%x %x %x\n", __FUNCTION__, + pdu->segments[0].segment_data[0], + pdu->segments[0].segment_data[1], + pdu->segments[0].segment_data[2] + ); + } + } else { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "unpack_tx_request: Failed to allocate pdu (len:%d) %d/%d %d\n", pdu->pdu_length, totalNumPdus, i, pdu->pdu_index); } - break; - default: - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "unpack_ue_release_request FIXME : Invalid type %d \n", generic_tl.tag ); + } else { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "NULL pdu\n"); + } + } + } + break; + + default: { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "unpack_tx_request FIXME : Invalid pdu type %d \n", generic_tl.tag ); + } + break; + }; + } + + return 1; +} + +static uint8_t unpack_ue_release_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t *config) { + uint8_t proceed = 1; + nfapi_ue_release_request_t *pNfapiMsg = (nfapi_ue_release_request_t *)msg; + + if(pull16(ppReadPackedMsg, &pNfapiMsg->sfn_sf, end) == 0) + return 0; + + while (((uint8_t *)(*ppReadPackedMsg) < end) && proceed) { + nfapi_tl_t generic_tl; + + if(unpack_tl(ppReadPackedMsg, &generic_tl, end) == 0) + return 0; + + switch(generic_tl.tag) { + case NFAPI_UE_RELEASE_BODY_TAG: { + pNfapiMsg->ue_release_request_body.tl = generic_tl; + + if( pull16(ppReadPackedMsg, &pNfapiMsg->ue_release_request_body.number_of_TLVs, end) == 0) + return 0; + + if(pNfapiMsg->ue_release_request_body.number_of_TLVs > NFAPI_RELEASE_MAX_RNTI) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s number of relese rnti's exceed maxium (count:%d max:%d)\n", __FUNCTION__, pNfapiMsg->ue_release_request_body.number_of_TLVs, NFAPI_RELEASE_MAX_RNTI); + return 0; + } else { + uint8_t j; + uint16_t num = pNfapiMsg->ue_release_request_body.number_of_TLVs; + + for(j = 0; j < num; ++j) { + if(pull16(ppReadPackedMsg, &pNfapiMsg->ue_release_request_body.ue_release_request_TLVs_list[j].rnti, end) == 0) { + return 0; } - break; - }; + } + } + } + break; + + default: { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "unpack_ue_release_request FIXME : Invalid type %d \n", generic_tl.tag ); + } + break; + }; + } + + return 1; +} + +static uint8_t unpack_harq_indication_tdd_harq_data_bundling(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_harq_indication_tdd_harq_data_bundling_t *value = (nfapi_harq_indication_tdd_harq_data_bundling_t *)tlv; + return (pull8(ppReadPackedMsg, &value->value_0, end) && + pull8(ppReadPackedMsg, &value->value_1, end)); +} + +static uint8_t unpack_harq_indication_tdd_harq_data_multiplexing(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_harq_indication_tdd_harq_data_multiplexing_t *value = (nfapi_harq_indication_tdd_harq_data_multiplexing_t *)tlv; + return (pull8(ppReadPackedMsg, &value->value_0, end) && + pull8(ppReadPackedMsg, &value->value_1, end) && + pull8(ppReadPackedMsg, &value->value_2, end) && + pull8(ppReadPackedMsg, &value->value_3, end)); +} +static uint8_t unpack_harq_indication_tdd_harq_data_special_bundling(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_harq_indication_tdd_harq_data_special_bundling_t *value = (nfapi_harq_indication_tdd_harq_data_special_bundling_t *)tlv; + return ( pull8(ppReadPackedMsg, &value->value_0, end)); +} +static uint8_t unpack_harq_indication_tdd_harq_data(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_harq_indication_tdd_harq_data_t *value = (nfapi_harq_indication_tdd_harq_data_t *)tlv; + return (pull8(ppReadPackedMsg, &value->value_0, end)); +} + +static uint8_t unpack_harq_indication_tdd_rel8_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_harq_indication_tdd_rel8_t *value = (nfapi_harq_indication_tdd_rel8_t *)tlv; + + if(!(pull8(ppReadPackedMsg, &value->mode, end) && + pull8(ppReadPackedMsg, &value->number_of_ack_nack, end))) + return 0; + + uint8_t result = 0; + + switch(value->mode) { + case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_BUNDLING: + result = unpack_harq_indication_tdd_harq_data_bundling(&value->harq_data.bundling, ppReadPackedMsg, end); + break; + + case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_MULIPLEXING: + result = unpack_harq_indication_tdd_harq_data_multiplexing(&value->harq_data.multiplex, ppReadPackedMsg, end); + break; + + case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_SPECIAL_BUNDLING: + result = unpack_harq_indication_tdd_harq_data_special_bundling(&value->harq_data.special_bundling, ppReadPackedMsg, end); + break; + + case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_FORMAT_3: + case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_CHANNEL_SELECTION: + result = 1; + break; + + default: + // TODO add error message + return 0; + break; + } + + return result; +} + +static uint8_t unpack_harq_indication_tdd_rel9_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_harq_indication_tdd_rel9_t *value = (nfapi_harq_indication_tdd_rel9_t *)tlv; + + if(!(pull8(ppReadPackedMsg, &value->mode, end) && + pull8(ppReadPackedMsg, &value->number_of_ack_nack, end))) + return 0; + + if(value->number_of_ack_nack > NFAPI_MAX_NUMBER_ACK_NACK_TDD) { + // TODO : add error message + return 0; + } + + uint16_t idx = 0; + + for(idx = 0; idx < value->number_of_ack_nack; ++idx) { + uint8_t result = 0; + + switch(value->mode) { + case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_BUNDLING: + result = unpack_harq_indication_tdd_harq_data(&value->harq_data[idx].bundling, ppReadPackedMsg, end); + break; + + case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_MULIPLEXING: + result = unpack_harq_indication_tdd_harq_data(&value->harq_data[idx].multiplex, ppReadPackedMsg, end); + break; + + case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_SPECIAL_BUNDLING: + result = unpack_harq_indication_tdd_harq_data_special_bundling(&value->harq_data[idx].special_bundling, ppReadPackedMsg, end); + break; + + case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_CHANNEL_SELECTION: + result = unpack_harq_indication_tdd_harq_data(&value->harq_data[idx].channel_selection, ppReadPackedMsg, end); + break; + + case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_FORMAT_3: + result = unpack_harq_indication_tdd_harq_data(&value->harq_data[idx].format_3, ppReadPackedMsg, end); + break; + + default: + // TODO add error message + return 0; + break; } - return 1; + if(result == 0) + return 0; + } + + return 1; } -static uint8_t unpack_harq_indication_tdd_harq_data_bundling(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_harq_indication_tdd_harq_data_bundling_t* value = (nfapi_harq_indication_tdd_harq_data_bundling_t*)tlv; - - return (pull8(ppReadPackedMsg, &value->value_0, end) && - pull8(ppReadPackedMsg, &value->value_1, end)); +static uint8_t unpack_harq_indication_tdd_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_harq_indication_tdd_rel13_t *value = (nfapi_harq_indication_tdd_rel13_t *)tlv; + + if(!(pull8(ppReadPackedMsg, &value->mode, end) && + pull16(ppReadPackedMsg, &value->number_of_ack_nack, end))) + return 0; + + if(value->number_of_ack_nack > NFAPI_MAX_NUMBER_ACK_NACK_TDD) { + // TODO : add error message + return 0; + } + + uint16_t idx = 0; + + for(idx = 0; idx < value->number_of_ack_nack; ++idx) { + uint8_t result = 0; + + switch(value->mode) { + case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_BUNDLING: + result = unpack_harq_indication_tdd_harq_data(&value->harq_data[idx].bundling, ppReadPackedMsg, end); + break; + + case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_MULIPLEXING: + result = unpack_harq_indication_tdd_harq_data(&value->harq_data[idx].multiplex, ppReadPackedMsg, end); + break; + + case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_SPECIAL_BUNDLING: + result = unpack_harq_indication_tdd_harq_data_special_bundling(&value->harq_data[idx].special_bundling, ppReadPackedMsg, end); + break; + + case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_CHANNEL_SELECTION: + result = unpack_harq_indication_tdd_harq_data(&value->harq_data[idx].channel_selection, ppReadPackedMsg, end); + break; + + case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_FORMAT_3: + result = unpack_harq_indication_tdd_harq_data(&value->harq_data[idx].format_3, ppReadPackedMsg, end); + break; + + case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_FORMAT_4: + result = unpack_harq_indication_tdd_harq_data(&value->harq_data[idx].format_4, ppReadPackedMsg, end); + break; + + case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_FORMAT_5: + result = unpack_harq_indication_tdd_harq_data(&value->harq_data[idx].format_5, ppReadPackedMsg, end); + break; + + default: + // TODO add error message + return 0; + break; + } + + if(result == 0) + return 0; + } + + return 1; } -static uint8_t unpack_harq_indication_tdd_harq_data_multiplexing(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_harq_indication_tdd_harq_data_multiplexing_t* value = (nfapi_harq_indication_tdd_harq_data_multiplexing_t*)tlv; - - return (pull8(ppReadPackedMsg, &value->value_0, end) && - pull8(ppReadPackedMsg, &value->value_1, end) && - pull8(ppReadPackedMsg, &value->value_2, end) && - pull8(ppReadPackedMsg, &value->value_3, end)); -} -static uint8_t unpack_harq_indication_tdd_harq_data_special_bundling(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_harq_indication_tdd_harq_data_special_bundling_t* value = (nfapi_harq_indication_tdd_harq_data_special_bundling_t*)tlv; - return ( pull8(ppReadPackedMsg, &value->value_0, end)); -} -static uint8_t unpack_harq_indication_tdd_harq_data(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_harq_indication_tdd_harq_data_t* value = (nfapi_harq_indication_tdd_harq_data_t*)tlv; - return (pull8(ppReadPackedMsg, &value->value_0, end)); +static uint8_t unpack_harq_indication_fdd_rel8_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_harq_indication_fdd_rel8_t *value = (nfapi_harq_indication_fdd_rel8_t *)tlv; + return (pull8(ppReadPackedMsg, &value->harq_tb1, end) && + pull8(ppReadPackedMsg, &value->harq_tb2, end)); } -static uint8_t unpack_harq_indication_tdd_rel8_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_harq_indication_tdd_rel8_t* value = (nfapi_harq_indication_tdd_rel8_t*)tlv; - - if(!(pull8(ppReadPackedMsg, &value->mode, end) && - pull8(ppReadPackedMsg, &value->number_of_ack_nack, end))) - return 0; - - uint8_t result = 0; - switch(value->mode) - { - case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_BUNDLING: - result = unpack_harq_indication_tdd_harq_data_bundling(&value->harq_data.bundling, ppReadPackedMsg, end); - break; - case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_MULIPLEXING: - result = unpack_harq_indication_tdd_harq_data_multiplexing(&value->harq_data.multiplex, ppReadPackedMsg, end); - break; - case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_SPECIAL_BUNDLING: - result = unpack_harq_indication_tdd_harq_data_special_bundling(&value->harq_data.special_bundling, ppReadPackedMsg, end); - break; - case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_FORMAT_3: - case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_CHANNEL_SELECTION: - result = 1; - break; - default: - // TODO add error message - return 0; - break; - } - return result; +static uint8_t unpack_harq_indication_fdd_rel9_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_harq_indication_fdd_rel9_t *value = (nfapi_harq_indication_fdd_rel9_t *)tlv; + return (pull8(ppReadPackedMsg, &value->mode, end) && + pull8(ppReadPackedMsg, &value->number_of_ack_nack, end) && + pullarray8(ppReadPackedMsg, value->harq_tb_n, NFAPI_HARQ_ACK_NACK_REL9_MAX, value->number_of_ack_nack, end)); } -static uint8_t unpack_harq_indication_tdd_rel9_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_harq_indication_tdd_rel9_t* value = (nfapi_harq_indication_tdd_rel9_t*)tlv; - - if(!(pull8(ppReadPackedMsg, &value->mode, end) && - pull8(ppReadPackedMsg, &value->number_of_ack_nack, end))) - return 0; - - if(value->number_of_ack_nack > NFAPI_MAX_NUMBER_ACK_NACK_TDD) - { - // TODO : add error message - return 0; - } - - uint16_t idx = 0; - for(idx = 0; idx < value->number_of_ack_nack; ++idx) - { - uint8_t result = 0; - switch(value->mode) - { - case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_BUNDLING: - result = unpack_harq_indication_tdd_harq_data(&value->harq_data[idx].bundling, ppReadPackedMsg, end); - break; - case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_MULIPLEXING: - result = unpack_harq_indication_tdd_harq_data(&value->harq_data[idx].multiplex, ppReadPackedMsg, end); - break; - case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_SPECIAL_BUNDLING: - result = unpack_harq_indication_tdd_harq_data_special_bundling(&value->harq_data[idx].special_bundling, ppReadPackedMsg, end); - break; - case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_CHANNEL_SELECTION: - result = unpack_harq_indication_tdd_harq_data(&value->harq_data[idx].channel_selection, ppReadPackedMsg, end); - break; - case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_FORMAT_3: - result = unpack_harq_indication_tdd_harq_data(&value->harq_data[idx].format_3, ppReadPackedMsg, end); - break; - default: - // TODO add error message - return 0; - break; - } - - if(result == 0) - return 0; - } - return 1; +static uint8_t unpack_harq_indication_fdd_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_harq_indication_fdd_rel13_t *value = (nfapi_harq_indication_fdd_rel13_t *)tlv; + return (pull8(ppReadPackedMsg, &value->mode, end) && + pull16(ppReadPackedMsg, &value->number_of_ack_nack, end) && + pullarray8(ppReadPackedMsg, value->harq_tb_n, NFAPI_HARQ_ACK_NACK_REL13_MAX, value->number_of_ack_nack, end)); } -static uint8_t unpack_harq_indication_tdd_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_harq_indication_tdd_rel13_t* value = (nfapi_harq_indication_tdd_rel13_t*)tlv; - - if(!(pull8(ppReadPackedMsg, &value->mode, end) && - pull16(ppReadPackedMsg, &value->number_of_ack_nack, end))) - return 0; - - if(value->number_of_ack_nack > NFAPI_MAX_NUMBER_ACK_NACK_TDD) - { - // TODO : add error message - return 0; - } - - uint16_t idx = 0; - for(idx = 0; idx < value->number_of_ack_nack; ++idx) - { - uint8_t result = 0; - switch(value->mode) - { - case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_BUNDLING: - result = unpack_harq_indication_tdd_harq_data(&value->harq_data[idx].bundling, ppReadPackedMsg, end); - break; - case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_MULIPLEXING: - result = unpack_harq_indication_tdd_harq_data(&value->harq_data[idx].multiplex, ppReadPackedMsg, end); - break; - case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_SPECIAL_BUNDLING: - result = unpack_harq_indication_tdd_harq_data_special_bundling(&value->harq_data[idx].special_bundling, ppReadPackedMsg, end); - break; - case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_CHANNEL_SELECTION: - result = unpack_harq_indication_tdd_harq_data(&value->harq_data[idx].channel_selection, ppReadPackedMsg, end); - break; - case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_FORMAT_3: - result = unpack_harq_indication_tdd_harq_data(&value->harq_data[idx].format_3, ppReadPackedMsg, end); - break; - case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_FORMAT_4: - result = unpack_harq_indication_tdd_harq_data(&value->harq_data[idx].format_4, ppReadPackedMsg, end); - break; - case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_FORMAT_5: - result = unpack_harq_indication_tdd_harq_data(&value->harq_data[idx].format_5, ppReadPackedMsg, end); - break; - default: - // TODO add error message - return 0; - break; - } - - if(result == 0) - return 0; - } - return 1; -} - -static uint8_t unpack_harq_indication_fdd_rel8_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_harq_indication_fdd_rel8_t* value = (nfapi_harq_indication_fdd_rel8_t*)tlv; - return (pull8(ppReadPackedMsg, &value->harq_tb1, end) && - pull8(ppReadPackedMsg, &value->harq_tb2, end)); -} - -static uint8_t unpack_harq_indication_fdd_rel9_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_harq_indication_fdd_rel9_t* value = (nfapi_harq_indication_fdd_rel9_t*)tlv; - - return (pull8(ppReadPackedMsg, &value->mode, end) && - pull8(ppReadPackedMsg, &value->number_of_ack_nack, end) && - pullarray8(ppReadPackedMsg, value->harq_tb_n, NFAPI_HARQ_ACK_NACK_REL9_MAX, value->number_of_ack_nack, end)); -} - -static uint8_t unpack_harq_indication_fdd_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_harq_indication_fdd_rel13_t* value = (nfapi_harq_indication_fdd_rel13_t*)tlv; - - return (pull8(ppReadPackedMsg, &value->mode, end) && - pull16(ppReadPackedMsg, &value->number_of_ack_nack, end) && - pullarray8(ppReadPackedMsg, value->harq_tb_n, NFAPI_HARQ_ACK_NACK_REL13_MAX, value->number_of_ack_nack, end)); -} - -static uint8_t unpack_ul_cqi_information_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_ul_cqi_information_t* value = (nfapi_ul_cqi_information_t*)tlv; - - return (pull8(ppReadPackedMsg, &value->ul_cqi, end) && - pull8(ppReadPackedMsg, &value->channel, end)); +static uint8_t unpack_ul_cqi_information_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_ul_cqi_information_t *value = (nfapi_ul_cqi_information_t *)tlv; + return (pull8(ppReadPackedMsg, &value->ul_cqi, end) && + pull8(ppReadPackedMsg, &value->channel, end)); } -static uint8_t unpack_harq_indication_body_value(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) -{ - nfapi_harq_indication_body_t* value = (nfapi_harq_indication_body_t*)tlv; - uint8_t* harqBodyEnd = *ppReadPackedMsg + value->tl.length; +static uint8_t unpack_harq_indication_body_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end, nfapi_p7_codec_config_t *config) { + nfapi_harq_indication_body_t *value = (nfapi_harq_indication_body_t *)tlv; + uint8_t *harqBodyEnd = *ppReadPackedMsg + value->tl.length; - if(harqBodyEnd > end) - return 0; + if(harqBodyEnd > end) + return 0; - if(pull16(ppReadPackedMsg, &value->number_of_harqs, end) == 0) - return 0; + if(pull16(ppReadPackedMsg, &value->number_of_harqs, end) == 0) + return 0; - if(value->number_of_harqs > NFAPI_HARQ_IND_MAX_PDU) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s number of harq ind pdus exceed maxium (count:%d max:%d)\n", __FUNCTION__, value->number_of_harqs, NFAPI_HARQ_IND_MAX_PDU); - return 0; - } + if(value->number_of_harqs > NFAPI_HARQ_IND_MAX_PDU) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s number of harq ind pdus exceed maxium (count:%d max:%d)\n", __FUNCTION__, value->number_of_harqs, NFAPI_HARQ_IND_MAX_PDU); + return 0; + } - value->harq_pdu_list = (nfapi_harq_indication_pdu_t*)nfapi_p7_allocate(sizeof(nfapi_harq_indication_pdu_t) * value->number_of_harqs, config); - if(value->harq_pdu_list == NULL) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s failed to allocate harq ind pdu list (count:%d)\n", __FUNCTION__, value->number_of_harqs); - return 0; - } - - uint8_t i = 0; - for(i = 0; i < value->number_of_harqs; ++i) - { - nfapi_harq_indication_pdu_t* pdu = &(value->harq_pdu_list[i]); - if(pull16(ppReadPackedMsg, &pdu->instance_length, end) == 0) - return 0; + value->harq_pdu_list = (nfapi_harq_indication_pdu_t *)nfapi_p7_allocate(sizeof(nfapi_harq_indication_pdu_t) * value->number_of_harqs, config); - uint8_t* harqPduInstanceEnd = *ppReadPackedMsg + pdu->instance_length; + if(value->harq_pdu_list == NULL) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s failed to allocate harq ind pdu list (count:%d)\n", __FUNCTION__, value->number_of_harqs); + return 0; + } - unpack_tlv_t unpack_fns[] = - { - { NFAPI_RX_UE_INFORMATION_TAG, &pdu->rx_ue_information, unpack_rx_ue_information_value }, - { NFAPI_HARQ_INDICATION_TDD_REL8_TAG, &pdu->harq_indication_tdd_rel8, &unpack_harq_indication_tdd_rel8_value}, - { NFAPI_HARQ_INDICATION_TDD_REL9_TAG, &pdu->harq_indication_tdd_rel9, &unpack_harq_indication_tdd_rel9_value}, - { NFAPI_HARQ_INDICATION_TDD_REL13_TAG, &pdu->harq_indication_tdd_rel13, &unpack_harq_indication_tdd_rel13_value}, - { NFAPI_HARQ_INDICATION_FDD_REL8_TAG, &pdu->harq_indication_fdd_rel8, &unpack_harq_indication_fdd_rel8_value}, - { NFAPI_HARQ_INDICATION_FDD_REL9_TAG, &pdu->harq_indication_fdd_rel9, &unpack_harq_indication_fdd_rel9_value}, - { NFAPI_HARQ_INDICATION_FDD_REL13_TAG, &pdu->harq_indication_fdd_rel13, &unpack_harq_indication_fdd_rel13_value}, - { NFAPI_UL_CQI_INFORMATION_TAG, &pdu->ul_cqi_information, &unpack_ul_cqi_information_value} - }; + uint8_t i = 0; - if(unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, harqPduInstanceEnd, 0, 0) == 0) - return 0; - - } + for(i = 0; i < value->number_of_harqs; ++i) { + nfapi_harq_indication_pdu_t *pdu = &(value->harq_pdu_list[i]); - return 1; + if(pull16(ppReadPackedMsg, &pdu->instance_length, end) == 0) + return 0; + + uint8_t *harqPduInstanceEnd = *ppReadPackedMsg + pdu->instance_length; + unpack_tlv_t unpack_fns[] = { + { NFAPI_RX_UE_INFORMATION_TAG, &pdu->rx_ue_information, unpack_rx_ue_information_value }, + { NFAPI_HARQ_INDICATION_TDD_REL8_TAG, &pdu->harq_indication_tdd_rel8, &unpack_harq_indication_tdd_rel8_value}, + { NFAPI_HARQ_INDICATION_TDD_REL9_TAG, &pdu->harq_indication_tdd_rel9, &unpack_harq_indication_tdd_rel9_value}, + { NFAPI_HARQ_INDICATION_TDD_REL13_TAG, &pdu->harq_indication_tdd_rel13, &unpack_harq_indication_tdd_rel13_value}, + { NFAPI_HARQ_INDICATION_FDD_REL8_TAG, &pdu->harq_indication_fdd_rel8, &unpack_harq_indication_fdd_rel8_value}, + { NFAPI_HARQ_INDICATION_FDD_REL9_TAG, &pdu->harq_indication_fdd_rel9, &unpack_harq_indication_fdd_rel9_value}, + { NFAPI_HARQ_INDICATION_FDD_REL13_TAG, &pdu->harq_indication_fdd_rel13, &unpack_harq_indication_fdd_rel13_value}, + { NFAPI_UL_CQI_INFORMATION_TAG, &pdu->ul_cqi_information, &unpack_ul_cqi_information_value} + }; + + if(unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, harqPduInstanceEnd, 0, 0) == 0) + return 0; + } + + return 1; } -static uint8_t unpack_harq_indication(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config) -{ - nfapi_harq_indication_t *pNfapiMsg = (nfapi_harq_indication_t*)msg; - - unpack_p7_tlv_t unpack_fns[] = - { - { NFAPI_HARQ_INDICATION_BODY_TAG, &pNfapiMsg->harq_indication_body, &unpack_harq_indication_body_value}, - }; - - return (pull16(ppReadPackedMsg, &pNfapiMsg->sfn_sf, end) && - unpack_p7_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); +static uint8_t unpack_harq_indication(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t *config) { + nfapi_harq_indication_t *pNfapiMsg = (nfapi_harq_indication_t *)msg; + unpack_p7_tlv_t unpack_fns[] = { + { NFAPI_HARQ_INDICATION_BODY_TAG, &pNfapiMsg->harq_indication_body, &unpack_harq_indication_body_value}, + }; + return (pull16(ppReadPackedMsg, &pNfapiMsg->sfn_sf, end) && + unpack_p7_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); } -static uint8_t unpack_crc_indication_rel8_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_crc_indication_rel8_t* crc_pdu_rel8 = (nfapi_crc_indication_rel8_t*)tlv; - return ( pull8(ppReadPackedMsg, &crc_pdu_rel8->crc_flag, end) ); +static uint8_t unpack_crc_indication_rel8_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_crc_indication_rel8_t *crc_pdu_rel8 = (nfapi_crc_indication_rel8_t *)tlv; + return ( pull8(ppReadPackedMsg, &crc_pdu_rel8->crc_flag, end) ); } -static uint8_t unpack_crc_indication_body_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) -{ - nfapi_crc_indication_body_t* value = (nfapi_crc_indication_body_t*)tlv; - uint8_t* crcBodyEnd = *ppReadPackedMsg + value->tl.length; +static uint8_t unpack_crc_indication_body_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end, nfapi_p7_codec_config_t *config) { + nfapi_crc_indication_body_t *value = (nfapi_crc_indication_body_t *)tlv; + uint8_t *crcBodyEnd = *ppReadPackedMsg + value->tl.length; - if(crcBodyEnd > end) - return 0; + if(crcBodyEnd > end) + return 0; - if(pull16(ppReadPackedMsg, &value->number_of_crcs, end) == 0) - return 0; + if(pull16(ppReadPackedMsg, &value->number_of_crcs, end) == 0) + return 0; - if(value->number_of_crcs > NFAPI_CRC_IND_MAX_PDU) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s number of crc ind pdu's exceed maxium (count:%d max:%d)\n", __FUNCTION__, value->number_of_crcs, NFAPI_CRC_IND_MAX_PDU); - return 0; - } + if(value->number_of_crcs > NFAPI_CRC_IND_MAX_PDU) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s number of crc ind pdu's exceed maxium (count:%d max:%d)\n", __FUNCTION__, value->number_of_crcs, NFAPI_CRC_IND_MAX_PDU); + return 0; + } - if(value->number_of_crcs > 0) - { - value->crc_pdu_list = (nfapi_crc_indication_pdu_t*)nfapi_p7_allocate(sizeof(nfapi_crc_indication_pdu_t) * value->number_of_crcs, config); - if(value->crc_pdu_list == NULL) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s failed to allocate crc ind pdu list (count:%d)\n", __FUNCTION__, value->number_of_crcs); - return 0; - } - } - else - { - value->crc_pdu_list = 0; - } + if(value->number_of_crcs > 0) { + value->crc_pdu_list = (nfapi_crc_indication_pdu_t *)nfapi_p7_allocate(sizeof(nfapi_crc_indication_pdu_t) * value->number_of_crcs, config); - - uint8_t i = 0; - for(i = 0; i < value->number_of_crcs; ++i) - { - nfapi_crc_indication_pdu_t* pdu = &(value->crc_pdu_list[i]); + if(value->crc_pdu_list == NULL) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s failed to allocate crc ind pdu list (count:%d)\n", __FUNCTION__, value->number_of_crcs); + return 0; + } + } else { + value->crc_pdu_list = 0; + } - if(pull16(ppReadPackedMsg, &pdu->instance_length, end) == 0) - return 0; + uint8_t i = 0; - uint8_t* crcPduInstanceEnd = *ppReadPackedMsg + pdu->instance_length; + for(i = 0; i < value->number_of_crcs; ++i) { + nfapi_crc_indication_pdu_t *pdu = &(value->crc_pdu_list[i]); + if(pull16(ppReadPackedMsg, &pdu->instance_length, end) == 0) + return 0; - unpack_tlv_t unpack_fns[] = - { - { NFAPI_RX_UE_INFORMATION_TAG, &pdu->rx_ue_information, unpack_rx_ue_information_value }, - { NFAPI_CRC_INDICATION_REL8_TAG, &pdu->crc_indication_rel8, unpack_crc_indication_rel8_value }, - }; + uint8_t *crcPduInstanceEnd = *ppReadPackedMsg + pdu->instance_length; + unpack_tlv_t unpack_fns[] = { + { NFAPI_RX_UE_INFORMATION_TAG, &pdu->rx_ue_information, unpack_rx_ue_information_value }, + { NFAPI_CRC_INDICATION_REL8_TAG, &pdu->crc_indication_rel8, unpack_crc_indication_rel8_value }, + }; - if(unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, crcPduInstanceEnd, 0, 0) == 0) - return 0; - } + if(unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, crcPduInstanceEnd, 0, 0) == 0) + return 0; + } - return 1; + return 1; } -static uint8_t unpack_crc_indication(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config) -{ - nfapi_crc_indication_t *pNfapiMsg = (nfapi_crc_indication_t*)msg; - - unpack_p7_tlv_t unpack_fns[] = - { - { NFAPI_CRC_INDICATION_BODY_TAG, &pNfapiMsg->crc_indication_body, &unpack_crc_indication_body_value}, - }; - - return (pull16(ppReadPackedMsg, &pNfapiMsg->sfn_sf, end) && - unpack_p7_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); +static uint8_t unpack_crc_indication(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t *config) { + nfapi_crc_indication_t *pNfapiMsg = (nfapi_crc_indication_t *)msg; + unpack_p7_tlv_t unpack_fns[] = { + { NFAPI_CRC_INDICATION_BODY_TAG, &pNfapiMsg->crc_indication_body, &unpack_crc_indication_body_value}, + }; + return (pull16(ppReadPackedMsg, &pNfapiMsg->sfn_sf, end) && + unpack_p7_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); } -static uint8_t unpack_rx_indication_rel8_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_rx_indication_rel8_t* value = (nfapi_rx_indication_rel8_t*)tlv; - - return (pull16(ppReadPackedMsg, &value->length, end) && - pull16(ppReadPackedMsg, &value->offset, end) && - pull8(ppReadPackedMsg, &value->ul_cqi, end) && - pull16(ppReadPackedMsg, &value->timing_advance, end)); +static uint8_t unpack_rx_indication_rel8_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_rx_indication_rel8_t *value = (nfapi_rx_indication_rel8_t *)tlv; + return (pull16(ppReadPackedMsg, &value->length, end) && + pull16(ppReadPackedMsg, &value->offset, end) && + pull8(ppReadPackedMsg, &value->ul_cqi, end) && + pull16(ppReadPackedMsg, &value->timing_advance, end)); } -static uint8_t unpack_rx_indication_rel9_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_rx_indication_rel9_t* value = (nfapi_rx_indication_rel9_t*)tlv; - return (pull16(ppReadPackedMsg, &value->timing_advance_r9, end)); +static uint8_t unpack_rx_indication_rel9_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_rx_indication_rel9_t *value = (nfapi_rx_indication_rel9_t *)tlv; + return (pull16(ppReadPackedMsg, &value->timing_advance_r9, end)); } -static uint8_t unpack_rx_indication_body_value(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) -{ - nfapi_rx_indication_body_t* value = (nfapi_rx_indication_body_t*)tlv; +static uint8_t unpack_rx_indication_body_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end, nfapi_p7_codec_config_t *config) { + nfapi_rx_indication_body_t *value = (nfapi_rx_indication_body_t *)tlv; + // the rxBodyEnd points to the end of the cqi PDU's + uint8_t *rxBodyEnd = *ppReadPackedMsg + value->tl.length; + uint8_t *rxPduEnd = rxBodyEnd; + uint8_t *numberOfPdusAddress = *ppReadPackedMsg; - // the rxBodyEnd points to the end of the cqi PDU's - uint8_t* rxBodyEnd = *ppReadPackedMsg + value->tl.length; - uint8_t* rxPduEnd = rxBodyEnd; + if(rxBodyEnd > end) { + // pdu end is past buffer end + return 0; + } - uint8_t* numberOfPdusAddress = *ppReadPackedMsg; + if(pull16(ppReadPackedMsg, &value->number_of_pdus, end) == 0) + return 0; - if(rxBodyEnd > end) - { - // pdu end is past buffer end - return 0; - } + if(value->number_of_pdus > NFAPI_RX_IND_MAX_PDU) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s number of rx ind pdu's exceed maxium (count:%d max:%d)\n", __FUNCTION__, value->number_of_pdus, NFAPI_RX_IND_MAX_PDU); + return 0; + } - if(pull16(ppReadPackedMsg, &value->number_of_pdus, end) == 0) - return 0; + if(value->number_of_pdus > 0) { + value->rx_pdu_list = (nfapi_rx_indication_pdu_t *)nfapi_p7_allocate(sizeof(nfapi_rx_indication_pdu_t) * value->number_of_pdus, config); - if(value->number_of_pdus > NFAPI_RX_IND_MAX_PDU) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s number of rx ind pdu's exceed maxium (count:%d max:%d)\n", __FUNCTION__, value->number_of_pdus, NFAPI_RX_IND_MAX_PDU); - return 0; - } + if(value->rx_pdu_list == NULL) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s failed to allocate rx ind pdu list (count:%d)\n", __FUNCTION__, value->number_of_pdus); + return 0; + } + } else { + value->rx_pdu_list = 0; + } - if(value->number_of_pdus > 0) - { - value->rx_pdu_list = (nfapi_rx_indication_pdu_t*)nfapi_p7_allocate(sizeof(nfapi_rx_indication_pdu_t) * value->number_of_pdus, config); - if(value->rx_pdu_list == NULL) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s failed to allocate rx ind pdu list (count:%d)\n", __FUNCTION__, value->number_of_pdus); - return 0; - } - } - else - { - value->rx_pdu_list = 0; - } - - uint8_t i = 0; - nfapi_rx_indication_pdu_t* pdu = 0; - while((uint8_t*)(*ppReadPackedMsg) < rxBodyEnd && (uint8_t*)(*ppReadPackedMsg) < rxPduEnd) - { - nfapi_tl_t generic_tl; - if( unpack_tl(ppReadPackedMsg, &generic_tl, end) == 0) - return 0; + uint8_t i = 0; + nfapi_rx_indication_pdu_t *pdu = 0; - switch(generic_tl.tag) - { - case NFAPI_RX_UE_INFORMATION_TAG: - { - pdu = &(value->rx_pdu_list[i++]); - pdu->rx_ue_information.tl = generic_tl; - if(unpack_rx_ue_information_value(&pdu->rx_ue_information, ppReadPackedMsg, end) == 0) - return 0; - } - break; - case NFAPI_RX_INDICATION_REL8_TAG: - { - if(pdu != 0) - { - pdu->rx_indication_rel8.tl = generic_tl; - if(unpack_rx_indication_rel8_value(&pdu->rx_indication_rel8, ppReadPackedMsg, end) == 0) - return 0; - - if(pdu->rx_indication_rel8.offset > 0) - { - // Need to check that the data is within the tlv - if(numberOfPdusAddress + pdu->rx_indication_rel8.offset + pdu->rx_indication_rel8.length <= rxBodyEnd) - { - // If this the first pdu set the rxPduEnd - if(numberOfPdusAddress + pdu->rx_indication_rel8.offset < rxPduEnd) - { - rxPduEnd = numberOfPdusAddress + pdu->rx_indication_rel8.offset; - - if(rxPduEnd > end) - { - // pdu end is past buffer end - return 0; - } - } - } - else - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "FIXME: the rx data is outside of the tlv\n"); - } - } - } - } - break; - case NFAPI_RX_INDICATION_REL9_TAG: - { - if(pdu != 0) - { - pdu->rx_indication_rel9.tl = generic_tl; - if(unpack_rx_indication_rel9_value(&pdu->rx_indication_rel9, ppReadPackedMsg, end) == 0) - return 0; - } - } - break; - default: - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "RX_ULSCH.indication Invalid pdu type %d \n", generic_tl.tag ); - } - break; - } - } - - uint8_t idx = 0; - for(idx = 0; idx < value->number_of_pdus; ++idx) - { - if(value->rx_pdu_list[idx].rx_indication_rel8.tl.tag == NFAPI_RX_INDICATION_REL8_TAG) - { - uint32_t length = value->rx_pdu_list[idx].rx_indication_rel8.length; - value->rx_pdu_list[idx].data = nfapi_p7_allocate(length, config); - if(pullarray8(ppReadPackedMsg, value->rx_pdu_list[idx].data, length, length, end) == 0) - { - return 0; - } - } - } + while((uint8_t *)(*ppReadPackedMsg) < rxBodyEnd && (uint8_t *)(*ppReadPackedMsg) < rxPduEnd) { + nfapi_tl_t generic_tl; - return 1; + if( unpack_tl(ppReadPackedMsg, &generic_tl, end) == 0) + return 0; + + switch(generic_tl.tag) { + case NFAPI_RX_UE_INFORMATION_TAG: { + pdu = &(value->rx_pdu_list[i++]); + pdu->rx_ue_information.tl = generic_tl; + + if(unpack_rx_ue_information_value(&pdu->rx_ue_information, ppReadPackedMsg, end) == 0) + return 0; + } + break; + + case NFAPI_RX_INDICATION_REL8_TAG: { + if(pdu != 0) { + pdu->rx_indication_rel8.tl = generic_tl; + + if(unpack_rx_indication_rel8_value(&pdu->rx_indication_rel8, ppReadPackedMsg, end) == 0) + return 0; + + if(pdu->rx_indication_rel8.offset > 0) { + // Need to check that the data is within the tlv + if(numberOfPdusAddress + pdu->rx_indication_rel8.offset + pdu->rx_indication_rel8.length <= rxBodyEnd) { + // If this the first pdu set the rxPduEnd + if(numberOfPdusAddress + pdu->rx_indication_rel8.offset < rxPduEnd) { + rxPduEnd = numberOfPdusAddress + pdu->rx_indication_rel8.offset; + + if(rxPduEnd > end) { + // pdu end is past buffer end + return 0; + } + } + } else { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "FIXME: the rx data is outside of the tlv\n"); + } + } + } + } + break; + + case NFAPI_RX_INDICATION_REL9_TAG: { + if(pdu != 0) { + pdu->rx_indication_rel9.tl = generic_tl; + + if(unpack_rx_indication_rel9_value(&pdu->rx_indication_rel9, ppReadPackedMsg, end) == 0) + return 0; + } + } + break; + + default: { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "RX_ULSCH.indication Invalid pdu type %d \n", generic_tl.tag ); + } + break; + } + } + + uint8_t idx = 0; + + for(idx = 0; idx < value->number_of_pdus; ++idx) { + if(value->rx_pdu_list[idx].rx_indication_rel8.tl.tag == NFAPI_RX_INDICATION_REL8_TAG) { + uint32_t length = value->rx_pdu_list[idx].rx_indication_rel8.length; + value->rx_pdu_list[idx].data = nfapi_p7_allocate(length, config); + + if(pullarray8(ppReadPackedMsg, value->rx_pdu_list[idx].data, length, length, end) == 0) { + return 0; + } + } + } + + return 1; } -static uint8_t unpack_rx_indication(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config) -{ - nfapi_rx_indication_t *pNfapiMsg = (nfapi_rx_indication_t*)msg; - - unpack_p7_tlv_t unpack_fns[] = - { - { NFAPI_RX_INDICATION_BODY_TAG, &pNfapiMsg->rx_indication_body, &unpack_rx_indication_body_value}, - }; - - return (pull16(ppReadPackedMsg, &pNfapiMsg->sfn_sf, end) && - unpack_p7_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); +static uint8_t unpack_rx_indication(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t *config) { + nfapi_rx_indication_t *pNfapiMsg = (nfapi_rx_indication_t *)msg; + unpack_p7_tlv_t unpack_fns[] = { + { NFAPI_RX_INDICATION_BODY_TAG, &pNfapiMsg->rx_indication_body, &unpack_rx_indication_body_value}, + }; + return (pull16(ppReadPackedMsg, &pNfapiMsg->sfn_sf, end) && + unpack_p7_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); } -static uint8_t unpack_preamble_pdu_rel8_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_preamble_pdu_rel8_t* preamble_pdu_rel8 = (nfapi_preamble_pdu_rel8_t*)tlv; - - return (pull16(ppReadPackedMsg, &preamble_pdu_rel8->rnti, end) && - pull8(ppReadPackedMsg, &preamble_pdu_rel8->preamble, end) && - pull16(ppReadPackedMsg, &preamble_pdu_rel8->timing_advance, end)); +static uint8_t unpack_preamble_pdu_rel8_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_preamble_pdu_rel8_t *preamble_pdu_rel8 = (nfapi_preamble_pdu_rel8_t *)tlv; + return (pull16(ppReadPackedMsg, &preamble_pdu_rel8->rnti, end) && + pull8(ppReadPackedMsg, &preamble_pdu_rel8->preamble, end) && + pull16(ppReadPackedMsg, &preamble_pdu_rel8->timing_advance, end)); } -static uint8_t unpack_preamble_pdu_rel9_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_preamble_pdu_rel9_t* preamble_pdu_rel9 = (nfapi_preamble_pdu_rel9_t*)tlv; - return pull16(ppReadPackedMsg, &preamble_pdu_rel9->timing_advance_r9, end); +static uint8_t unpack_preamble_pdu_rel9_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_preamble_pdu_rel9_t *preamble_pdu_rel9 = (nfapi_preamble_pdu_rel9_t *)tlv; + return pull16(ppReadPackedMsg, &preamble_pdu_rel9->timing_advance_r9, end); } -static uint8_t unpack_preamble_pdu_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_preamble_pdu_rel13_t* preamble_pdu_rel13 = (nfapi_preamble_pdu_rel13_t*)tlv; - return pull8(ppReadPackedMsg, &preamble_pdu_rel13->rach_resource_type, end); +static uint8_t unpack_preamble_pdu_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_preamble_pdu_rel13_t *preamble_pdu_rel13 = (nfapi_preamble_pdu_rel13_t *)tlv; + return pull8(ppReadPackedMsg, &preamble_pdu_rel13->rach_resource_type, end); } -static uint8_t unpack_rach_indication_body_value(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) -{ - nfapi_rach_indication_body_t* value = (nfapi_rach_indication_body_t*)tlv; - uint8_t* rachBodyEnd = *ppReadPackedMsg + value->tl.length; +static uint8_t unpack_rach_indication_body_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end, nfapi_p7_codec_config_t *config) { + nfapi_rach_indication_body_t *value = (nfapi_rach_indication_body_t *)tlv; + uint8_t *rachBodyEnd = *ppReadPackedMsg + value->tl.length; - if(rachBodyEnd > end) - return 0; + if(rachBodyEnd > end) + return 0; - if(pull16(ppReadPackedMsg, &value->number_of_preambles, end) == 0) - return 0; + if(pull16(ppReadPackedMsg, &value->number_of_preambles, end) == 0) + return 0; - if(value->number_of_preambles > NFAPI_PREAMBLE_MAX_PDU) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s number of preamble du's exceed maxium (count:%d max:%d)\n", __FUNCTION__, value->number_of_preambles, NFAPI_PREAMBLE_MAX_PDU); - return 0; - } + if(value->number_of_preambles > NFAPI_PREAMBLE_MAX_PDU) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s number of preamble du's exceed maxium (count:%d max:%d)\n", __FUNCTION__, value->number_of_preambles, NFAPI_PREAMBLE_MAX_PDU); + return 0; + } - if(value->number_of_preambles > 0) - { - value->preamble_list = (nfapi_preamble_pdu_t*)nfapi_p7_allocate(sizeof(nfapi_preamble_pdu_t) * value->number_of_preambles, config); - if(value->preamble_list == NULL) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s failed to allocate preamble pdu list (count:%d)\n", __FUNCTION__, value->number_of_preambles); - return 0; - } - } - else - { - value->preamble_list = 0; - } + if(value->number_of_preambles > 0) { + value->preamble_list = (nfapi_preamble_pdu_t *)nfapi_p7_allocate(sizeof(nfapi_preamble_pdu_t) * value->number_of_preambles, config); - - uint8_t i = 0; - for(i = 0; i < value->number_of_preambles; ++i) - { - nfapi_preamble_pdu_t* pdu = &(value->preamble_list[i]); + if(value->preamble_list == NULL) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s failed to allocate preamble pdu list (count:%d)\n", __FUNCTION__, value->number_of_preambles); + return 0; + } + } else { + value->preamble_list = 0; + } - if(pull16(ppReadPackedMsg, &pdu->instance_length, end) == 0) - return 0; + uint8_t i = 0; - uint8_t* preamblePduInstanceEnd = *ppReadPackedMsg + pdu->instance_length; + for(i = 0; i < value->number_of_preambles; ++i) { + nfapi_preamble_pdu_t *pdu = &(value->preamble_list[i]); + if(pull16(ppReadPackedMsg, &pdu->instance_length, end) == 0) + return 0; - unpack_tlv_t unpack_fns[] = - { - { NFAPI_PREAMBLE_REL8_TAG, &pdu->preamble_rel8, unpack_preamble_pdu_rel8_value }, - { NFAPI_PREAMBLE_REL9_TAG, &pdu->preamble_rel9, unpack_preamble_pdu_rel9_value }, - { NFAPI_PREAMBLE_REL13_TAG, &pdu->preamble_rel13, unpack_preamble_pdu_rel13_value }, - }; + uint8_t *preamblePduInstanceEnd = *ppReadPackedMsg + pdu->instance_length; + unpack_tlv_t unpack_fns[] = { + { NFAPI_PREAMBLE_REL8_TAG, &pdu->preamble_rel8, unpack_preamble_pdu_rel8_value }, + { NFAPI_PREAMBLE_REL9_TAG, &pdu->preamble_rel9, unpack_preamble_pdu_rel9_value }, + { NFAPI_PREAMBLE_REL13_TAG, &pdu->preamble_rel13, unpack_preamble_pdu_rel13_value }, + }; - if(unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, preamblePduInstanceEnd, 0, 0) == 0) - return 0; - } - return 1; + if(unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, preamblePduInstanceEnd, 0, 0) == 0) + return 0; + } + + return 1; } -static uint8_t unpack_rach_indication(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config) -{ - nfapi_rach_indication_t *pNfapiMsg = (nfapi_rach_indication_t*)msg; - - unpack_p7_tlv_t unpack_fns[] = - { - { NFAPI_RACH_INDICATION_BODY_TAG, &pNfapiMsg->rach_indication_body, &unpack_rach_indication_body_value}, - }; - - return (pull16(ppReadPackedMsg, &pNfapiMsg->sfn_sf, end) && - unpack_p7_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); +static uint8_t unpack_rach_indication(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t *config) { + nfapi_rach_indication_t *pNfapiMsg = (nfapi_rach_indication_t *)msg; + unpack_p7_tlv_t unpack_fns[] = { + { NFAPI_RACH_INDICATION_BODY_TAG, &pNfapiMsg->rach_indication_body, &unpack_rach_indication_body_value}, + }; + return (pull16(ppReadPackedMsg, &pNfapiMsg->sfn_sf, end) && + unpack_p7_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); } -static uint8_t unpack_srs_indication_fdd_rel8_value(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_srs_indication_fdd_rel8_t* srs_pdu_fdd_rel8 = (nfapi_srs_indication_fdd_rel8_t*)tlv; - - if(!(pull16(ppReadPackedMsg, &srs_pdu_fdd_rel8->doppler_estimation, end) && - pull16(ppReadPackedMsg, &srs_pdu_fdd_rel8->timing_advance, end) && - pull8(ppReadPackedMsg, &srs_pdu_fdd_rel8->number_of_resource_blocks, end) && - pull8(ppReadPackedMsg, &srs_pdu_fdd_rel8->rb_start, end) && - pullarray8(ppReadPackedMsg, srs_pdu_fdd_rel8->snr, NFAPI_NUM_RB_MAX, srs_pdu_fdd_rel8->number_of_resource_blocks, end))) - return 0; - return 1; +static uint8_t unpack_srs_indication_fdd_rel8_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_srs_indication_fdd_rel8_t *srs_pdu_fdd_rel8 = (nfapi_srs_indication_fdd_rel8_t *)tlv; + + if(!(pull16(ppReadPackedMsg, &srs_pdu_fdd_rel8->doppler_estimation, end) && + pull16(ppReadPackedMsg, &srs_pdu_fdd_rel8->timing_advance, end) && + pull8(ppReadPackedMsg, &srs_pdu_fdd_rel8->number_of_resource_blocks, end) && + pull8(ppReadPackedMsg, &srs_pdu_fdd_rel8->rb_start, end) && + pullarray8(ppReadPackedMsg, srs_pdu_fdd_rel8->snr, NFAPI_NUM_RB_MAX, srs_pdu_fdd_rel8->number_of_resource_blocks, end))) + return 0; + + return 1; } -static uint8_t unpack_srs_indication_fdd_rel9_value(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_srs_indication_fdd_rel9_t* srs_pdu_fdd_rel9 = (nfapi_srs_indication_fdd_rel9_t*)tlv; - return (pull16(ppReadPackedMsg, &srs_pdu_fdd_rel9->timing_advance_r9, end)); +static uint8_t unpack_srs_indication_fdd_rel9_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_srs_indication_fdd_rel9_t *srs_pdu_fdd_rel9 = (nfapi_srs_indication_fdd_rel9_t *)tlv; + return (pull16(ppReadPackedMsg, &srs_pdu_fdd_rel9->timing_advance_r9, end)); } -static uint8_t unpack_srs_indication_tdd_rel10_value(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_srs_indication_ttd_rel10_t* srs_pdu_tdd_rel10 = (nfapi_srs_indication_ttd_rel10_t*)tlv; - return (pull8(ppReadPackedMsg, &srs_pdu_tdd_rel10->uppts_symbol, end)); +static uint8_t unpack_srs_indication_tdd_rel10_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_srs_indication_ttd_rel10_t *srs_pdu_tdd_rel10 = (nfapi_srs_indication_ttd_rel10_t *)tlv; + return (pull8(ppReadPackedMsg, &srs_pdu_tdd_rel10->uppts_symbol, end)); } -static uint8_t unpack_srs_indication_fdd_rel11_value(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_srs_indication_fdd_rel11_t* srs_pdu_fdd_rel11 = (nfapi_srs_indication_fdd_rel11_t*)tlv; - return ( pull16(ppReadPackedMsg, &srs_pdu_fdd_rel11->ul_rtoa, end)); +static uint8_t unpack_srs_indication_fdd_rel11_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_srs_indication_fdd_rel11_t *srs_pdu_fdd_rel11 = (nfapi_srs_indication_fdd_rel11_t *)tlv; + return ( pull16(ppReadPackedMsg, &srs_pdu_fdd_rel11->ul_rtoa, end)); } -static uint8_t unpack_tdd_channel_measurement_value(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_tdd_channel_measurement_t* value = (nfapi_tdd_channel_measurement_t*)tlv; - - if(!(pull8(ppReadPackedMsg, &value->num_prb_per_subband, end) && - pull8(ppReadPackedMsg, &value->number_of_subbands, end) && - pull8(ppReadPackedMsg, &value->num_atennas, end))) - return 0; +static uint8_t unpack_tdd_channel_measurement_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_tdd_channel_measurement_t *value = (nfapi_tdd_channel_measurement_t *)tlv; - if(value->number_of_subbands > NFAPI_MAX_NUM_SUBBANDS) - { - // todo : add error - return 0; - } + if(!(pull8(ppReadPackedMsg, &value->num_prb_per_subband, end) && + pull8(ppReadPackedMsg, &value->number_of_subbands, end) && + pull8(ppReadPackedMsg, &value->num_atennas, end))) + return 0; - if(value->num_atennas > NFAPI_MAX_NUM_PHYSICAL_ANTENNAS) - { - // todo : add error - return 0; - } + if(value->number_of_subbands > NFAPI_MAX_NUM_SUBBANDS) { + // todo : add error + return 0; + } - uint8_t idx = 0; - for(idx = 0; idx < value->number_of_subbands; ++idx) - { - if(!(pull8(ppReadPackedMsg, &value->subands[idx].subband_index, end) && - pullarray16(ppReadPackedMsg, value->subands[idx].channel, NFAPI_MAX_NUM_PHYSICAL_ANTENNAS, value->num_atennas, end))) - return 0; - } + if(value->num_atennas > NFAPI_MAX_NUM_PHYSICAL_ANTENNAS) { + // todo : add error + return 0; + } - return 1; + uint8_t idx = 0; + + for(idx = 0; idx < value->number_of_subbands; ++idx) { + if(!(pull8(ppReadPackedMsg, &value->subands[idx].subband_index, end) && + pullarray16(ppReadPackedMsg, value->subands[idx].channel, NFAPI_MAX_NUM_PHYSICAL_ANTENNAS, value->num_atennas, end))) + return 0; + } + + return 1; } -static uint8_t unpack_srs_indication_body_value(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) -{ - nfapi_srs_indication_body_t* value = (nfapi_srs_indication_body_t*)tlv; - uint8_t* srsBodyEnd = *ppReadPackedMsg + value->tl.length; - - if(srsBodyEnd > end) - return 0; +static uint8_t unpack_srs_indication_body_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end, nfapi_p7_codec_config_t *config) { + nfapi_srs_indication_body_t *value = (nfapi_srs_indication_body_t *)tlv; + uint8_t *srsBodyEnd = *ppReadPackedMsg + value->tl.length; - if(pull8(ppReadPackedMsg, &value->number_of_ues, end) == 0) - return 0; + if(srsBodyEnd > end) + return 0; - if(value->number_of_ues > NFAPI_SRS_IND_MAX_PDU) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s number of srs ind pdu's exceed maxium (count:%d max:%d)\n", __FUNCTION__, value->number_of_ues, NFAPI_SRS_IND_MAX_PDU); - return 0; - } + if(pull8(ppReadPackedMsg, &value->number_of_ues, end) == 0) + return 0; - if(value->number_of_ues > 0) - { - value->srs_pdu_list = (nfapi_srs_indication_pdu_t*)nfapi_p7_allocate(sizeof(nfapi_srs_indication_pdu_t) * value->number_of_ues, config); - if(value->srs_pdu_list == NULL) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s failed to allocate srs ind pdu list (count:%d)\n", __FUNCTION__, value->number_of_ues); - return 0; - } - } - else - { - value->srs_pdu_list = 0; - } + if(value->number_of_ues > NFAPI_SRS_IND_MAX_PDU) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s number of srs ind pdu's exceed maxium (count:%d max:%d)\n", __FUNCTION__, value->number_of_ues, NFAPI_SRS_IND_MAX_PDU); + return 0; + } + if(value->number_of_ues > 0) { + value->srs_pdu_list = (nfapi_srs_indication_pdu_t *)nfapi_p7_allocate(sizeof(nfapi_srs_indication_pdu_t) * value->number_of_ues, config); - - uint8_t i = 0; - for(i = 0; i < value->number_of_ues; ++i) - { - nfapi_srs_indication_pdu_t* pdu = &(value->srs_pdu_list[i]); + if(value->srs_pdu_list == NULL) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s failed to allocate srs ind pdu list (count:%d)\n", __FUNCTION__, value->number_of_ues); + return 0; + } + } else { + value->srs_pdu_list = 0; + } - - if(pull16(ppReadPackedMsg, &pdu->instance_length, end) == 0) - return 0; + uint8_t i = 0; - uint8_t* srsPduInstanceEnd = *ppReadPackedMsg + pdu->instance_length; + for(i = 0; i < value->number_of_ues; ++i) { + nfapi_srs_indication_pdu_t *pdu = &(value->srs_pdu_list[i]); + if(pull16(ppReadPackedMsg, &pdu->instance_length, end) == 0) + return 0; - unpack_tlv_t unpack_fns[] = - { - { NFAPI_RX_UE_INFORMATION_TAG, &pdu->rx_ue_information, unpack_rx_ue_information_value }, - { NFAPI_SRS_INDICATION_FDD_REL8_TAG, &pdu->srs_indication_fdd_rel8, unpack_srs_indication_fdd_rel8_value}, - { NFAPI_SRS_INDICATION_FDD_REL9_TAG, &pdu->srs_indication_fdd_rel9, unpack_srs_indication_fdd_rel9_value}, - { NFAPI_SRS_INDICATION_TDD_REL10_TAG, &pdu->srs_indication_tdd_rel10, unpack_srs_indication_tdd_rel10_value}, - { NFAPI_SRS_INDICATION_FDD_REL11_TAG, &pdu->srs_indication_fdd_rel11, unpack_srs_indication_fdd_rel11_value}, - { NFAPI_TDD_CHANNEL_MEASUREMENT_TAG, &pdu->tdd_channel_measurement, unpack_tdd_channel_measurement_value}, - }; + uint8_t *srsPduInstanceEnd = *ppReadPackedMsg + pdu->instance_length; + unpack_tlv_t unpack_fns[] = { + { NFAPI_RX_UE_INFORMATION_TAG, &pdu->rx_ue_information, unpack_rx_ue_information_value }, + { NFAPI_SRS_INDICATION_FDD_REL8_TAG, &pdu->srs_indication_fdd_rel8, unpack_srs_indication_fdd_rel8_value}, + { NFAPI_SRS_INDICATION_FDD_REL9_TAG, &pdu->srs_indication_fdd_rel9, unpack_srs_indication_fdd_rel9_value}, + { NFAPI_SRS_INDICATION_TDD_REL10_TAG, &pdu->srs_indication_tdd_rel10, unpack_srs_indication_tdd_rel10_value}, + { NFAPI_SRS_INDICATION_FDD_REL11_TAG, &pdu->srs_indication_fdd_rel11, unpack_srs_indication_fdd_rel11_value}, + { NFAPI_TDD_CHANNEL_MEASUREMENT_TAG, &pdu->tdd_channel_measurement, unpack_tdd_channel_measurement_value}, + }; - if(unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, srsPduInstanceEnd, 0, 0) == 0) - return 0; - } - return 1; + if(unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, srsPduInstanceEnd, 0, 0) == 0) + return 0; + } + + return 1; } -static uint8_t unpack_srs_indication(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config) -{ - nfapi_srs_indication_t *pNfapiMsg = (nfapi_srs_indication_t*)msg; - - unpack_p7_tlv_t unpack_fns[] = - { - { NFAPI_SRS_INDICATION_BODY_TAG, &pNfapiMsg->srs_indication_body, &unpack_srs_indication_body_value}, - }; - - return (pull16(ppReadPackedMsg, &pNfapiMsg->sfn_sf, end) && - unpack_p7_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); +static uint8_t unpack_srs_indication(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t *config) { + nfapi_srs_indication_t *pNfapiMsg = (nfapi_srs_indication_t *)msg; + unpack_p7_tlv_t unpack_fns[] = { + { NFAPI_SRS_INDICATION_BODY_TAG, &pNfapiMsg->srs_indication_body, &unpack_srs_indication_body_value}, + }; + return (pull16(ppReadPackedMsg, &pNfapiMsg->sfn_sf, end) && + unpack_p7_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); } -static uint8_t unpack_sr_indication_body_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) -{ - nfapi_sr_indication_body_t* value = (nfapi_sr_indication_body_t*)tlv; - uint8_t* srBodyEnd = *ppReadPackedMsg + value->tl.length; +static uint8_t unpack_sr_indication_body_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end, nfapi_p7_codec_config_t *config) { + nfapi_sr_indication_body_t *value = (nfapi_sr_indication_body_t *)tlv; + uint8_t *srBodyEnd = *ppReadPackedMsg + value->tl.length; - if(srBodyEnd > end) - return 0; + if(srBodyEnd > end) + return 0; - if(pull16(ppReadPackedMsg, &value->number_of_srs, end) == 0) - return 0; + if(pull16(ppReadPackedMsg, &value->number_of_srs, end) == 0) + return 0; - if(value->number_of_srs > NFAPI_SR_IND_MAX_PDU) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s number of sr ind pdu's exceed maxium (count:%d max:%d)\n", __FUNCTION__, value->number_of_srs, NFAPI_SR_IND_MAX_PDU); - return 0; - } + if(value->number_of_srs > NFAPI_SR_IND_MAX_PDU) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s number of sr ind pdu's exceed maxium (count:%d max:%d)\n", __FUNCTION__, value->number_of_srs, NFAPI_SR_IND_MAX_PDU); + return 0; + } - if(value->number_of_srs > 0) - { - value->sr_pdu_list = (nfapi_sr_indication_pdu_t*)nfapi_p7_allocate(sizeof(nfapi_sr_indication_pdu_t) * value->number_of_srs, config); - if(value->sr_pdu_list == NULL) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s failed to allocate sr ind pdu list (count:%d)\n", __FUNCTION__, value->number_of_srs); - return 0; - } - } - else - { - value->sr_pdu_list = 0; - } - - uint8_t i = 0; - for(i = 0; i < value->number_of_srs; ++i) - { - nfapi_sr_indication_pdu_t* pdu = &(value->sr_pdu_list[i]); + if(value->number_of_srs > 0) { + value->sr_pdu_list = (nfapi_sr_indication_pdu_t *)nfapi_p7_allocate(sizeof(nfapi_sr_indication_pdu_t) * value->number_of_srs, config); - if(pull16(ppReadPackedMsg, &pdu->instance_length, end) == 0) - return 0; + if(value->sr_pdu_list == NULL) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s failed to allocate sr ind pdu list (count:%d)\n", __FUNCTION__, value->number_of_srs); + return 0; + } + } else { + value->sr_pdu_list = 0; + } - uint8_t* srPduInstanceEnd = *ppReadPackedMsg + pdu->instance_length; + uint8_t i = 0; + for(i = 0; i < value->number_of_srs; ++i) { + nfapi_sr_indication_pdu_t *pdu = &(value->sr_pdu_list[i]); - unpack_tlv_t unpack_fns[] = - { - { NFAPI_RX_UE_INFORMATION_TAG, &pdu->rx_ue_information, unpack_rx_ue_information_value }, - { NFAPI_UL_CQI_INFORMATION_TAG, &pdu->ul_cqi_information, unpack_ul_cqi_information_value }, - }; + if(pull16(ppReadPackedMsg, &pdu->instance_length, end) == 0) + return 0; - if(unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, srPduInstanceEnd, 0, 0) == 0) - return 0; - } + uint8_t *srPduInstanceEnd = *ppReadPackedMsg + pdu->instance_length; + unpack_tlv_t unpack_fns[] = { + { NFAPI_RX_UE_INFORMATION_TAG, &pdu->rx_ue_information, unpack_rx_ue_information_value }, + { NFAPI_UL_CQI_INFORMATION_TAG, &pdu->ul_cqi_information, unpack_ul_cqi_information_value }, + }; - return 1; + if(unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, srPduInstanceEnd, 0, 0) == 0) + return 0; + } + return 1; } -static int unpack_sr_indication(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config) -{ - nfapi_sr_indication_t *pNfapiMsg = (nfapi_sr_indication_t*)msg; - - unpack_p7_tlv_t unpack_fns[] = - { - { NFAPI_SR_INDICATION_BODY_TAG, &pNfapiMsg->sr_indication_body, &unpack_sr_indication_body_value}, - }; - - return (pull16(ppReadPackedMsg, &pNfapiMsg->sfn_sf, end) && - unpack_p7_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); +static int unpack_sr_indication(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t *config) { + nfapi_sr_indication_t *pNfapiMsg = (nfapi_sr_indication_t *)msg; + unpack_p7_tlv_t unpack_fns[] = { + { NFAPI_SR_INDICATION_BODY_TAG, &pNfapiMsg->sr_indication_body, &unpack_sr_indication_body_value}, + }; + return (pull16(ppReadPackedMsg, &pNfapiMsg->sfn_sf, end) && + unpack_p7_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); } -static uint8_t unpack_cqi_indication_rel8_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_cqi_indication_rel8_t* cqi_pdu_rel8 = (nfapi_cqi_indication_rel8_t*)tlv; - - return (pull16(ppReadPackedMsg, &cqi_pdu_rel8->length, end) && - pull16(ppReadPackedMsg, &cqi_pdu_rel8->data_offset, end) && - pull8(ppReadPackedMsg, &cqi_pdu_rel8->ul_cqi, end) && - pull8(ppReadPackedMsg, &cqi_pdu_rel8->ri, end) && - pull16(ppReadPackedMsg, &cqi_pdu_rel8->timing_advance, end)); - +static uint8_t unpack_cqi_indication_rel8_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_cqi_indication_rel8_t *cqi_pdu_rel8 = (nfapi_cqi_indication_rel8_t *)tlv; + return (pull16(ppReadPackedMsg, &cqi_pdu_rel8->length, end) && + pull16(ppReadPackedMsg, &cqi_pdu_rel8->data_offset, end) && + pull8(ppReadPackedMsg, &cqi_pdu_rel8->ul_cqi, end) && + pull8(ppReadPackedMsg, &cqi_pdu_rel8->ri, end) && + pull16(ppReadPackedMsg, &cqi_pdu_rel8->timing_advance, end)); } -static uint8_t unpack_cqi_indication_rel9_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_cqi_indication_rel9_t* cqi_pdu_rel9 = (nfapi_cqi_indication_rel9_t*)tlv; - - if(!(pull16(ppReadPackedMsg, &cqi_pdu_rel9->length, end) && - pull16(ppReadPackedMsg, &cqi_pdu_rel9->data_offset, end) && - pull8(ppReadPackedMsg, &cqi_pdu_rel9->ul_cqi, end) && - pull8(ppReadPackedMsg, &cqi_pdu_rel9->number_of_cc_reported, end))) - return 0; +static uint8_t unpack_cqi_indication_rel9_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_cqi_indication_rel9_t *cqi_pdu_rel9 = (nfapi_cqi_indication_rel9_t *)tlv; - if(cqi_pdu_rel9->number_of_cc_reported > NFAPI_CC_MAX) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "FIXME : out of bound array\n"); - return 0; - } - - if(!(pullarray8(ppReadPackedMsg, cqi_pdu_rel9->ri, NFAPI_CC_MAX, cqi_pdu_rel9->number_of_cc_reported, end) && - pull16(ppReadPackedMsg, &cqi_pdu_rel9->timing_advance, end) && - pull16(ppReadPackedMsg, &cqi_pdu_rel9->timing_advance_r9, end))) - return 0; + if(!(pull16(ppReadPackedMsg, &cqi_pdu_rel9->length, end) && + pull16(ppReadPackedMsg, &cqi_pdu_rel9->data_offset, end) && + pull8(ppReadPackedMsg, &cqi_pdu_rel9->ul_cqi, end) && + pull8(ppReadPackedMsg, &cqi_pdu_rel9->number_of_cc_reported, end))) + return 0; - return 1; + if(cqi_pdu_rel9->number_of_cc_reported > NFAPI_CC_MAX) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "FIXME : out of bound array\n"); + return 0; + } + + if(!(pullarray8(ppReadPackedMsg, cqi_pdu_rel9->ri, NFAPI_CC_MAX, cqi_pdu_rel9->number_of_cc_reported, end) && + pull16(ppReadPackedMsg, &cqi_pdu_rel9->timing_advance, end) && + pull16(ppReadPackedMsg, &cqi_pdu_rel9->timing_advance_r9, end))) + return 0; + + return 1; } -static uint8_t unpack_cqi_indication_body_value(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) -{ - nfapi_cqi_indication_body_t* value = (nfapi_cqi_indication_body_t*)tlv; +static uint8_t unpack_cqi_indication_body_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end, nfapi_p7_codec_config_t *config) { + nfapi_cqi_indication_body_t *value = (nfapi_cqi_indication_body_t *)tlv; + // the cqiBodyEnd points to the end of the cqi PDU's + uint8_t *cqiBodyEnd = *ppReadPackedMsg + value->tl.length; - // the cqiBodyEnd points to the end of the cqi PDU's - uint8_t* cqiBodyEnd = *ppReadPackedMsg + value->tl.length; + //uint8_t* cqiPduEnd = cqiBodyEnd; + //uint8_t* numberOfPdusAddress = *ppReadPackedMsg; - //uint8_t* cqiPduEnd = cqiBodyEnd; - //uint8_t* numberOfPdusAddress = *ppReadPackedMsg; + if(cqiBodyEnd > end) + return 0; - if(cqiBodyEnd > end) - return 0; + if(pull16(ppReadPackedMsg, &value->number_of_cqis, end) == 0) + return 0; - if(pull16(ppReadPackedMsg, &value->number_of_cqis, end) == 0) - return 0; + if(value->number_of_cqis > NFAPI_CQI_IND_MAX_PDU) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s number of cqi ind pdu's exceed maxium (count:%d max:%d)\n", __FUNCTION__, value->number_of_cqis, NFAPI_CQI_IND_MAX_PDU); + return -1; + } - if(value->number_of_cqis > NFAPI_CQI_IND_MAX_PDU) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s number of cqi ind pdu's exceed maxium (count:%d max:%d)\n", __FUNCTION__, value->number_of_cqis, NFAPI_CQI_IND_MAX_PDU); - return -1; - } + if(value->number_of_cqis > 0) { + value->cqi_pdu_list = (nfapi_cqi_indication_pdu_t *)nfapi_p7_allocate(sizeof(nfapi_cqi_indication_pdu_t) * value->number_of_cqis, config); - if(value->number_of_cqis > 0) - { - value->cqi_pdu_list = (nfapi_cqi_indication_pdu_t*)nfapi_p7_allocate(sizeof(nfapi_cqi_indication_pdu_t) * value->number_of_cqis, config); - if(value->cqi_pdu_list == NULL) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s failed to allocate cqi ind pdu list (count:%d)\n", __FUNCTION__, value->number_of_cqis); - return 0; - } - } - else - { - value->cqi_pdu_list = 0; - } + if(value->cqi_pdu_list == NULL) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s failed to allocate cqi ind pdu list (count:%d)\n", __FUNCTION__, value->number_of_cqis); + return 0; + } + } else { + value->cqi_pdu_list = 0; + } - if(value->number_of_cqis > 0) - { - value->cqi_raw_pdu_list = (nfapi_cqi_indication_raw_pdu_t*)nfapi_p7_allocate(sizeof(nfapi_cqi_indication_raw_pdu_t) * value->number_of_cqis, config); - if(value->cqi_raw_pdu_list == NULL) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s failed to allocate raw cqi ind pdu list (count:%d)\n", __FUNCTION__, value->number_of_cqis); - return 0; - } - } - else - { - value->cqi_raw_pdu_list = 0; - } + if(value->number_of_cqis > 0) { + value->cqi_raw_pdu_list = (nfapi_cqi_indication_raw_pdu_t *)nfapi_p7_allocate(sizeof(nfapi_cqi_indication_raw_pdu_t) * value->number_of_cqis, config); - uint8_t i = 0; - for(i = 0; i < value->number_of_cqis; ++i) - { - nfapi_cqi_indication_pdu_t* pdu = &(value->cqi_pdu_list[i]); - memset(pdu, 0, sizeof(nfapi_cqi_indication_pdu_t)); + if(value->cqi_raw_pdu_list == NULL) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s failed to allocate raw cqi ind pdu list (count:%d)\n", __FUNCTION__, value->number_of_cqis); + return 0; + } + } else { + value->cqi_raw_pdu_list = 0; + } - if(pull16(ppReadPackedMsg, &pdu->instance_length, end) == 0) - return 0; + uint8_t i = 0; - uint8_t* cqiPduInstanceEnd = *ppReadPackedMsg + pdu->instance_length; + for(i = 0; i < value->number_of_cqis; ++i) { + nfapi_cqi_indication_pdu_t *pdu = &(value->cqi_pdu_list[i]); + memset(pdu, 0, sizeof(nfapi_cqi_indication_pdu_t)); + if(pull16(ppReadPackedMsg, &pdu->instance_length, end) == 0) + return 0; - while((uint8_t*)(*ppReadPackedMsg) < cqiPduInstanceEnd) - { - nfapi_tl_t generic_tl; - if(unpack_tl(ppReadPackedMsg, &generic_tl, end) == 0) - return 0; + uint8_t *cqiPduInstanceEnd = *ppReadPackedMsg + pdu->instance_length; - switch(generic_tl.tag) - { - case NFAPI_RX_UE_INFORMATION_TAG: - pdu->rx_ue_information.tl = generic_tl; - if(unpack_rx_ue_information_value(&pdu->rx_ue_information, ppReadPackedMsg, end) == 0) - return 0; - break; - case NFAPI_CQI_INDICATION_REL8_TAG: - pdu->cqi_indication_rel8.tl = generic_tl; - if(unpack_cqi_indication_rel8_value(&pdu->cqi_indication_rel8, ppReadPackedMsg, end) == 0) - return 0; + while((uint8_t *)(*ppReadPackedMsg) < cqiPduInstanceEnd) { + nfapi_tl_t generic_tl; - break; - case NFAPI_CQI_INDICATION_REL9_TAG: - pdu->cqi_indication_rel9.tl = generic_tl; - if(unpack_cqi_indication_rel9_value(&pdu->cqi_indication_rel9, ppReadPackedMsg, end) == 0) - return 0; + if(unpack_tl(ppReadPackedMsg, &generic_tl, end) == 0) + return 0; - break; - case NFAPI_UL_CQI_INFORMATION_TAG: - pdu->ul_cqi_information.tl = generic_tl; - if(unpack_ul_cqi_information_value(&pdu->ul_cqi_information, ppReadPackedMsg, end) == 0) - return 0; - break; - default: - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "RX_CQI.indication Invalid pdu type %d \n", generic_tl.tag ); - } - break; + switch(generic_tl.tag) { + case NFAPI_RX_UE_INFORMATION_TAG: + pdu->rx_ue_information.tl = generic_tl; - }; - } - } + if(unpack_rx_ue_information_value(&pdu->rx_ue_information, ppReadPackedMsg, end) == 0) + return 0; - uint8_t idx = 0; - for(idx = 0; idx < value->number_of_cqis; ++idx) - { - if(value->cqi_pdu_list[idx].cqi_indication_rel8.tl.tag == NFAPI_CQI_INDICATION_REL8_TAG) - { - if(pullarray8(ppReadPackedMsg, &(value->cqi_raw_pdu_list[idx].pdu[0]), NFAPI_CQI_RAW_MAX_LEN, value->cqi_pdu_list[idx].cqi_indication_rel8.length, end) == 0) - return 0; - } - else if(value->cqi_pdu_list[idx].cqi_indication_rel9.tl.tag == NFAPI_CQI_INDICATION_REL9_TAG) - { - if(pullarray8(ppReadPackedMsg, &(value->cqi_raw_pdu_list[idx].pdu[0]), NFAPI_CQI_RAW_MAX_LEN, value->cqi_pdu_list[idx].cqi_indication_rel9.length, end) == 0) - return 0; - } - } + break; + case NFAPI_CQI_INDICATION_REL8_TAG: + pdu->cqi_indication_rel8.tl = generic_tl; - return 1; + if(unpack_cqi_indication_rel8_value(&pdu->cqi_indication_rel8, ppReadPackedMsg, end) == 0) + return 0; + break; + + case NFAPI_CQI_INDICATION_REL9_TAG: + pdu->cqi_indication_rel9.tl = generic_tl; + + if(unpack_cqi_indication_rel9_value(&pdu->cqi_indication_rel9, ppReadPackedMsg, end) == 0) + return 0; + + break; + + case NFAPI_UL_CQI_INFORMATION_TAG: + pdu->ul_cqi_information.tl = generic_tl; + + if(unpack_ul_cqi_information_value(&pdu->ul_cqi_information, ppReadPackedMsg, end) == 0) + return 0; + + break; + + default: { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "RX_CQI.indication Invalid pdu type %d \n", generic_tl.tag ); + } + break; + }; + } + } + + uint8_t idx = 0; + + for(idx = 0; idx < value->number_of_cqis; ++idx) { + if(value->cqi_pdu_list[idx].cqi_indication_rel8.tl.tag == NFAPI_CQI_INDICATION_REL8_TAG) { + if(pullarray8(ppReadPackedMsg, &(value->cqi_raw_pdu_list[idx].pdu[0]), NFAPI_CQI_RAW_MAX_LEN, value->cqi_pdu_list[idx].cqi_indication_rel8.length, end) == 0) + return 0; + } else if(value->cqi_pdu_list[idx].cqi_indication_rel9.tl.tag == NFAPI_CQI_INDICATION_REL9_TAG) { + if(pullarray8(ppReadPackedMsg, &(value->cqi_raw_pdu_list[idx].pdu[0]), NFAPI_CQI_RAW_MAX_LEN, value->cqi_pdu_list[idx].cqi_indication_rel9.length, end) == 0) + return 0; + } + } + + return 1; } -static uint8_t unpack_cqi_indication(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config) -{ - nfapi_cqi_indication_t *pNfapiMsg = (nfapi_cqi_indication_t*)msg; - - unpack_p7_tlv_t unpack_fns[] = - { - { NFAPI_CQI_INDICATION_BODY_TAG, &pNfapiMsg->cqi_indication_body, &unpack_cqi_indication_body_value}, - }; - - return (pull16(ppReadPackedMsg, &pNfapiMsg->sfn_sf, end) && - unpack_p7_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); +static uint8_t unpack_cqi_indication(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t *config) { + nfapi_cqi_indication_t *pNfapiMsg = (nfapi_cqi_indication_t *)msg; + unpack_p7_tlv_t unpack_fns[] = { + { NFAPI_CQI_INDICATION_BODY_TAG, &pNfapiMsg->cqi_indication_body, &unpack_cqi_indication_body_value}, + }; + return (pull16(ppReadPackedMsg, &pNfapiMsg->sfn_sf, end) && + unpack_p7_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); } -static uint8_t unpack_lbt_pdsch_req_pdu_rel13_value(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_lbt_pdsch_req_pdu_rel13_t* value = (nfapi_lbt_pdsch_req_pdu_rel13_t*)tlv; - - return (pull32(ppReadPackedMsg, &value->handle, end) && - pull32(ppReadPackedMsg, &value->mp_cca, end) && - pull32(ppReadPackedMsg, &value->n_cca, end) && - pull32(ppReadPackedMsg, &value->offset, end) && - pull32(ppReadPackedMsg, &value->lte_txop_sf, end) && - pull16(ppReadPackedMsg, &value->txop_sfn_sf_end, end) && - pull32(ppReadPackedMsg, &value->lbt_mode, end)); +static uint8_t unpack_lbt_pdsch_req_pdu_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_lbt_pdsch_req_pdu_rel13_t *value = (nfapi_lbt_pdsch_req_pdu_rel13_t *)tlv; + return (pull32(ppReadPackedMsg, &value->handle, end) && + pull32(ppReadPackedMsg, &value->mp_cca, end) && + pull32(ppReadPackedMsg, &value->n_cca, end) && + pull32(ppReadPackedMsg, &value->offset, end) && + pull32(ppReadPackedMsg, &value->lte_txop_sf, end) && + pull16(ppReadPackedMsg, &value->txop_sfn_sf_end, end) && + pull32(ppReadPackedMsg, &value->lbt_mode, end)); } -static uint8_t unpack_lbt_drs_req_pdu_rel13_value(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_lbt_drs_req_pdu_rel13_t* value = (nfapi_lbt_drs_req_pdu_rel13_t*)tlv; - - return (pull32(ppReadPackedMsg, &value->handle, end) && - pull32(ppReadPackedMsg, &value->offset, end) && - pull16(ppReadPackedMsg, &value->sfn_sf_end, end) && - pull32(ppReadPackedMsg, &value->lbt_mode, end)); +static uint8_t unpack_lbt_drs_req_pdu_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_lbt_drs_req_pdu_rel13_t *value = (nfapi_lbt_drs_req_pdu_rel13_t *)tlv; + return (pull32(ppReadPackedMsg, &value->handle, end) && + pull32(ppReadPackedMsg, &value->offset, end) && + pull16(ppReadPackedMsg, &value->sfn_sf_end, end) && + pull32(ppReadPackedMsg, &value->lbt_mode, end)); } -static uint8_t unpack_lbt_config_request_body_value(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) -{ - nfapi_lbt_dl_config_request_body_t* value = (nfapi_lbt_dl_config_request_body_t*)tlv; +static uint8_t unpack_lbt_config_request_body_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end, nfapi_p7_codec_config_t *config) { + nfapi_lbt_dl_config_request_body_t *value = (nfapi_lbt_dl_config_request_body_t *)tlv; - if(pull16(ppReadPackedMsg, &value->number_of_pdus, end) == 0) - return 0; + if(pull16(ppReadPackedMsg, &value->number_of_pdus, end) == 0) + return 0; - if(value->number_of_pdus > NFAPI_LBT_DL_CONFIG_REQ_MAX_PDU) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s number of lbt dl config pdu's exceed maxium (count:%d max:%d)\n", __FUNCTION__, value->number_of_pdus, NFAPI_LBT_DL_CONFIG_REQ_MAX_PDU); - return 0; - } + if(value->number_of_pdus > NFAPI_LBT_DL_CONFIG_REQ_MAX_PDU) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s number of lbt dl config pdu's exceed maxium (count:%d max:%d)\n", __FUNCTION__, value->number_of_pdus, NFAPI_LBT_DL_CONFIG_REQ_MAX_PDU); + return 0; + } - if(value->number_of_pdus) - { - value->lbt_dl_config_req_pdu_list = (nfapi_lbt_dl_config_request_pdu_t*)nfapi_p7_allocate(sizeof(nfapi_lbt_dl_config_request_pdu_t) * value->number_of_pdus, config); - if(value->lbt_dl_config_req_pdu_list == NULL) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s failed to allocate lbt dl config pdu list (count:%d)\n", __FUNCTION__, value->number_of_pdus); - return 0; - } - } - else - { - value->lbt_dl_config_req_pdu_list = 0; - } + if(value->number_of_pdus) { + value->lbt_dl_config_req_pdu_list = (nfapi_lbt_dl_config_request_pdu_t *)nfapi_p7_allocate(sizeof(nfapi_lbt_dl_config_request_pdu_t) * value->number_of_pdus, config); + if(value->lbt_dl_config_req_pdu_list == NULL) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s failed to allocate lbt dl config pdu list (count:%d)\n", __FUNCTION__, value->number_of_pdus); + return 0; + } + } else { + value->lbt_dl_config_req_pdu_list = 0; + } - uint16_t i; - uint16_t total_number_of_pdus = value->number_of_pdus; - for(i = 0; i < total_number_of_pdus; ++i) - { - nfapi_lbt_dl_config_request_pdu_t* pdu = &(value->lbt_dl_config_req_pdu_list[i]); + uint16_t i; + uint16_t total_number_of_pdus = value->number_of_pdus; - if(!(pull8(ppReadPackedMsg, &pdu->pdu_type, end) && - pull8(ppReadPackedMsg, &pdu->pdu_size, end))) - return 0; - - uint8_t *packedPduEnd = (*ppReadPackedMsg) + pdu->pdu_size - 2; + for(i = 0; i < total_number_of_pdus; ++i) { + nfapi_lbt_dl_config_request_pdu_t *pdu = &(value->lbt_dl_config_req_pdu_list[i]); - if(packedPduEnd > end) - return 0; + if(!(pull8(ppReadPackedMsg, &pdu->pdu_type, end) && + pull8(ppReadPackedMsg, &pdu->pdu_size, end))) + return 0; - switch(pdu->pdu_type) - { - case NFAPI_LBT_DL_CONFIG_REQUEST_PDSCH_PDU_TYPE: - { - unpack_tlv_t unpack_fns[] = - { - { NFAPI_LBT_PDSCH_REQ_PDU_REL13_TAG, &pdu->lbt_pdsch_req_pdu.lbt_pdsch_req_pdu_rel13, &unpack_lbt_pdsch_req_pdu_rel13_value}, - }; + uint8_t *packedPduEnd = (*ppReadPackedMsg) + pdu->pdu_size - 2; - unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); - } - break; - case NFAPI_LBT_DL_CONFIG_REQUEST_DRS_PDU_TYPE: - { - unpack_tlv_t unpack_fns[] = - { - { NFAPI_LBT_DRS_REQ_PDU_REL13_TAG, &pdu->lbt_drs_req_pdu.lbt_drs_req_pdu_rel13, &unpack_lbt_drs_req_pdu_rel13_value}, - }; + if(packedPduEnd > end) + return 0; - unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); - } - break; - default: - NFAPI_TRACE(NFAPI_TRACE_ERROR, "LBT_DL_CONFIG.request body invalid pdu type %d\n", pdu->pdu_type); - return 0; - } - } + switch(pdu->pdu_type) { + case NFAPI_LBT_DL_CONFIG_REQUEST_PDSCH_PDU_TYPE: { + unpack_tlv_t unpack_fns[] = { + { NFAPI_LBT_PDSCH_REQ_PDU_REL13_TAG, &pdu->lbt_pdsch_req_pdu.lbt_pdsch_req_pdu_rel13, &unpack_lbt_pdsch_req_pdu_rel13_value}, + }; + unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); + } + break; - return 1; + case NFAPI_LBT_DL_CONFIG_REQUEST_DRS_PDU_TYPE: { + unpack_tlv_t unpack_fns[] = { + { NFAPI_LBT_DRS_REQ_PDU_REL13_TAG, &pdu->lbt_drs_req_pdu.lbt_drs_req_pdu_rel13, &unpack_lbt_drs_req_pdu_rel13_value}, + }; + unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); + } + break; + + default: + NFAPI_TRACE(NFAPI_TRACE_ERROR, "LBT_DL_CONFIG.request body invalid pdu type %d\n", pdu->pdu_type); + return 0; + } + } + + return 1; } -static uint8_t unpack_lbt_dl_config_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config) -{ - nfapi_lbt_dl_config_request_t *pNfapiMsg = (nfapi_lbt_dl_config_request_t*)msg; - - unpack_p7_tlv_t unpack_fns[] = - { - { NFAPI_LBT_DL_CONFIG_REQUEST_BODY_TAG, &pNfapiMsg->lbt_dl_config_request_body, &unpack_lbt_config_request_body_value}, - }; - - return (pull16(ppReadPackedMsg, &pNfapiMsg->sfn_sf, end) && - unpack_p7_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); +static uint8_t unpack_lbt_dl_config_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t *config) { + nfapi_lbt_dl_config_request_t *pNfapiMsg = (nfapi_lbt_dl_config_request_t *)msg; + unpack_p7_tlv_t unpack_fns[] = { + { NFAPI_LBT_DL_CONFIG_REQUEST_BODY_TAG, &pNfapiMsg->lbt_dl_config_request_body, &unpack_lbt_config_request_body_value}, + }; + return (pull16(ppReadPackedMsg, &pNfapiMsg->sfn_sf, end) && + unpack_p7_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); } -static uint8_t unpack_lbt_pdsch_rsp_pdu_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_lbt_pdsch_rsp_pdu_rel13_t* value = (nfapi_lbt_pdsch_rsp_pdu_rel13_t*)tlv; - - return (pull32(ppReadPackedMsg, &value->handle, end) && - pull32(ppReadPackedMsg, &value->result, end) && - pull32(ppReadPackedMsg, &value->lte_txop_symbols, end) && - pull32(ppReadPackedMsg, &value->initial_partial_sf, end)); - +static uint8_t unpack_lbt_pdsch_rsp_pdu_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_lbt_pdsch_rsp_pdu_rel13_t *value = (nfapi_lbt_pdsch_rsp_pdu_rel13_t *)tlv; + return (pull32(ppReadPackedMsg, &value->handle, end) && + pull32(ppReadPackedMsg, &value->result, end) && + pull32(ppReadPackedMsg, &value->lte_txop_symbols, end) && + pull32(ppReadPackedMsg, &value->initial_partial_sf, end)); } -static uint8_t unpack_lbt_drs_rsp_pdu_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_lbt_drs_rsp_pdu_rel13_t* value = (nfapi_lbt_drs_rsp_pdu_rel13_t*)tlv; - - return (pull32(ppReadPackedMsg, &value->handle, end) && - pull32(ppReadPackedMsg, &value->result, end)); +static uint8_t unpack_lbt_drs_rsp_pdu_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_lbt_drs_rsp_pdu_rel13_t *value = (nfapi_lbt_drs_rsp_pdu_rel13_t *)tlv; + return (pull32(ppReadPackedMsg, &value->handle, end) && + pull32(ppReadPackedMsg, &value->result, end)); } -static uint8_t unpack_lbt_indication_body_value(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) -{ - nfapi_lbt_dl_indication_body_t* value = (nfapi_lbt_dl_indication_body_t*)tlv; +static uint8_t unpack_lbt_indication_body_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end, nfapi_p7_codec_config_t *config) { + nfapi_lbt_dl_indication_body_t *value = (nfapi_lbt_dl_indication_body_t *)tlv; - if(pull16(ppReadPackedMsg, &value->number_of_pdus, end) == 0) - return 0; + if(pull16(ppReadPackedMsg, &value->number_of_pdus, end) == 0) + return 0; - if(value->number_of_pdus > NFAPI_LBT_IND_MAX_PDU) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s number of lbt dl ind pdu's exceed maxium (count:%d max:%d)\n", __FUNCTION__, value->number_of_pdus, NFAPI_LBT_IND_MAX_PDU); - return 0; - } + if(value->number_of_pdus > NFAPI_LBT_IND_MAX_PDU) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s number of lbt dl ind pdu's exceed maxium (count:%d max:%d)\n", __FUNCTION__, value->number_of_pdus, NFAPI_LBT_IND_MAX_PDU); + return 0; + } - if(value->number_of_pdus > 0) - { - value->lbt_indication_pdu_list = (nfapi_lbt_dl_indication_pdu_t*)nfapi_p7_allocate(sizeof(nfapi_lbt_dl_indication_pdu_t) * value->number_of_pdus, config); - if(value->lbt_indication_pdu_list == NULL) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s failed to allocate lbt dl ind config pdu list (count:%d)\n", __FUNCTION__, value->number_of_pdus); - return 0; - } - } - else - { - value->lbt_indication_pdu_list = 0; - } + if(value->number_of_pdus > 0) { + value->lbt_indication_pdu_list = (nfapi_lbt_dl_indication_pdu_t *)nfapi_p7_allocate(sizeof(nfapi_lbt_dl_indication_pdu_t) * value->number_of_pdus, config); - uint16_t i; - uint16_t total_number_of_pdus = value->number_of_pdus; - for(i = 0; i < total_number_of_pdus; ++i) - { - nfapi_lbt_dl_indication_pdu_t* pdu = &(value->lbt_indication_pdu_list[i]); + if(value->lbt_indication_pdu_list == NULL) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s failed to allocate lbt dl ind config pdu list (count:%d)\n", __FUNCTION__, value->number_of_pdus); + return 0; + } + } else { + value->lbt_indication_pdu_list = 0; + } - if(!(pull8(ppReadPackedMsg, &pdu->pdu_type, end) && - pull8(ppReadPackedMsg, &pdu->pdu_size, end))) - return 0; - - uint8_t *packedPduEnd = (*ppReadPackedMsg) + pdu->pdu_size - 2; + uint16_t i; + uint16_t total_number_of_pdus = value->number_of_pdus; - if(packedPduEnd > end) - return 0; + for(i = 0; i < total_number_of_pdus; ++i) { + nfapi_lbt_dl_indication_pdu_t *pdu = &(value->lbt_indication_pdu_list[i]); - switch(pdu->pdu_type) - { - case NFAPI_LBT_DL_RSP_PDSCH_PDU_TYPE: - { - unpack_tlv_t unpack_fns[] = - { - { NFAPI_LBT_PDSCH_RSP_PDU_REL13_TAG, &pdu->lbt_pdsch_rsp_pdu.lbt_pdsch_rsp_pdu_rel13, &unpack_lbt_pdsch_rsp_pdu_rel13_value}, - }; + if(!(pull8(ppReadPackedMsg, &pdu->pdu_type, end) && + pull8(ppReadPackedMsg, &pdu->pdu_size, end))) + return 0; - unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); - } - break; - case NFAPI_LBT_DL_RSP_DRS_PDU_TYPE: - { - unpack_tlv_t unpack_fns[] = - { - { NFAPI_LBT_DRS_RSP_PDU_REL13_TAG, &pdu->lbt_drs_rsp_pdu.lbt_drs_rsp_pdu_rel13, &unpack_lbt_drs_rsp_pdu_rel13_value}, - }; + uint8_t *packedPduEnd = (*ppReadPackedMsg) + pdu->pdu_size - 2; - unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); - } - break; - default: - NFAPI_TRACE(NFAPI_TRACE_ERROR, "LBT_DL.indication body invalid pdu type %d\n", pdu->pdu_type); - return 0; - } - } + if(packedPduEnd > end) + return 0; - return 1; + switch(pdu->pdu_type) { + case NFAPI_LBT_DL_RSP_PDSCH_PDU_TYPE: { + unpack_tlv_t unpack_fns[] = { + { NFAPI_LBT_PDSCH_RSP_PDU_REL13_TAG, &pdu->lbt_pdsch_rsp_pdu.lbt_pdsch_rsp_pdu_rel13, &unpack_lbt_pdsch_rsp_pdu_rel13_value}, + }; + unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); + } + break; + + case NFAPI_LBT_DL_RSP_DRS_PDU_TYPE: { + unpack_tlv_t unpack_fns[] = { + { NFAPI_LBT_DRS_RSP_PDU_REL13_TAG, &pdu->lbt_drs_rsp_pdu.lbt_drs_rsp_pdu_rel13, &unpack_lbt_drs_rsp_pdu_rel13_value}, + }; + unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); + } + break; + + default: + NFAPI_TRACE(NFAPI_TRACE_ERROR, "LBT_DL.indication body invalid pdu type %d\n", pdu->pdu_type); + return 0; + } + } + + return 1; } -static uint8_t unpack_lbt_dl_indication(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config) -{ - nfapi_lbt_dl_indication_t *pNfapiMsg = (nfapi_lbt_dl_indication_t*)msg; - - unpack_p7_tlv_t unpack_fns[] = - { - { NFAPI_LBT_DL_INDICATION_BODY_TAG, &pNfapiMsg->lbt_dl_indication_body, &unpack_lbt_indication_body_value}, - }; - - return (pull16(ppReadPackedMsg, &pNfapiMsg->sfn_sf, end) && - unpack_p7_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); +static uint8_t unpack_lbt_dl_indication(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t *config) { + nfapi_lbt_dl_indication_t *pNfapiMsg = (nfapi_lbt_dl_indication_t *)msg; + unpack_p7_tlv_t unpack_fns[] = { + { NFAPI_LBT_DL_INDICATION_BODY_TAG, &pNfapiMsg->lbt_dl_indication_body, &unpack_lbt_indication_body_value}, + }; + return (pull16(ppReadPackedMsg, &pNfapiMsg->sfn_sf, end) && + unpack_p7_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); } -static uint8_t unpack_nb_harq_indication_fdd_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_nb_harq_indication_fdd_rel13_t* value = (nfapi_nb_harq_indication_fdd_rel13_t*)tlv; - return (pull8(ppReadPackedMsg, &value->harq_tb1, end)); +static uint8_t unpack_nb_harq_indication_fdd_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_nb_harq_indication_fdd_rel13_t *value = (nfapi_nb_harq_indication_fdd_rel13_t *)tlv; + return (pull8(ppReadPackedMsg, &value->harq_tb1, end)); } -static uint8_t unpack_nb_harq_indication_body_value(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) -{ - nfapi_nb_harq_indication_body_t* value = (nfapi_nb_harq_indication_body_t*)tlv; - uint8_t* nbharqBodyEnd = *ppReadPackedMsg + value->tl.length; +static uint8_t unpack_nb_harq_indication_body_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end, nfapi_p7_codec_config_t *config) { + nfapi_nb_harq_indication_body_t *value = (nfapi_nb_harq_indication_body_t *)tlv; + uint8_t *nbharqBodyEnd = *ppReadPackedMsg + value->tl.length; - if(nbharqBodyEnd > end) - return 0; + if(nbharqBodyEnd > end) + return 0; - if(pull16(ppReadPackedMsg, &value->number_of_harqs, end) == 0) - return 0; + if(pull16(ppReadPackedMsg, &value->number_of_harqs, end) == 0) + return 0; - if(value->number_of_harqs > NFAPI_HARQ_IND_MAX_PDU) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s number of harq ind pdus exceed maxium (count:%d max:%d)\n", __FUNCTION__, value->number_of_harqs, NFAPI_HARQ_IND_MAX_PDU); - return 0; - } + if(value->number_of_harqs > NFAPI_HARQ_IND_MAX_PDU) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s number of harq ind pdus exceed maxium (count:%d max:%d)\n", __FUNCTION__, value->number_of_harqs, NFAPI_HARQ_IND_MAX_PDU); + return 0; + } - value->nb_harq_pdu_list = (nfapi_nb_harq_indication_pdu_t*)nfapi_p7_allocate(sizeof(nfapi_nb_harq_indication_pdu_t) * value->number_of_harqs, config); - if(value->nb_harq_pdu_list == NULL) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s failed to allocate harq ind pdu list (count:%d)\n", __FUNCTION__, value->number_of_harqs); - return 0; - } - - uint8_t i = 0; - for(i = 0; i < value->number_of_harqs; ++i) - { - nfapi_nb_harq_indication_pdu_t* pdu = &(value->nb_harq_pdu_list[i]); - if(pull16(ppReadPackedMsg, &pdu->instance_length, end) == 0) - return 0; + value->nb_harq_pdu_list = (nfapi_nb_harq_indication_pdu_t *)nfapi_p7_allocate(sizeof(nfapi_nb_harq_indication_pdu_t) * value->number_of_harqs, config); - uint8_t* harqPduInstanceEnd = *ppReadPackedMsg + pdu->instance_length; + if(value->nb_harq_pdu_list == NULL) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s failed to allocate harq ind pdu list (count:%d)\n", __FUNCTION__, value->number_of_harqs); + return 0; + } - unpack_tlv_t unpack_fns[] = - { - { NFAPI_RX_UE_INFORMATION_TAG, &pdu->rx_ue_information, unpack_rx_ue_information_value }, - { NFAPI_NB_HARQ_INDICATION_FDD_REL13_TAG, &pdu->nb_harq_indication_fdd_rel13, &unpack_nb_harq_indication_fdd_rel13_value}, - { NFAPI_UL_CQI_INFORMATION_TAG, &pdu->ul_cqi_information, &unpack_ul_cqi_information_value} - }; + uint8_t i = 0; - if(unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, harqPduInstanceEnd, 0, 0) == 0) - return 0; - - } + for(i = 0; i < value->number_of_harqs; ++i) { + nfapi_nb_harq_indication_pdu_t *pdu = &(value->nb_harq_pdu_list[i]); - return 1; + if(pull16(ppReadPackedMsg, &pdu->instance_length, end) == 0) + return 0; + + uint8_t *harqPduInstanceEnd = *ppReadPackedMsg + pdu->instance_length; + unpack_tlv_t unpack_fns[] = { + { NFAPI_RX_UE_INFORMATION_TAG, &pdu->rx_ue_information, unpack_rx_ue_information_value }, + { NFAPI_NB_HARQ_INDICATION_FDD_REL13_TAG, &pdu->nb_harq_indication_fdd_rel13, &unpack_nb_harq_indication_fdd_rel13_value}, + { NFAPI_UL_CQI_INFORMATION_TAG, &pdu->ul_cqi_information, &unpack_ul_cqi_information_value} + }; + + if(unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, harqPduInstanceEnd, 0, 0) == 0) + return 0; + } + + return 1; } -static uint8_t unpack_nb_harq_indication(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config) -{ - nfapi_nb_harq_indication_t *pNfapiMsg = (nfapi_nb_harq_indication_t*)msg; - - unpack_p7_tlv_t unpack_fns[] = - { - { NFAPI_NB_HARQ_INDICATION_BODY_TAG, &pNfapiMsg->nb_harq_indication_body, &unpack_nb_harq_indication_body_value}, - }; - - return (pull16(ppReadPackedMsg, &pNfapiMsg->sfn_sf, end) && - unpack_p7_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); +static uint8_t unpack_nb_harq_indication(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t *config) { + nfapi_nb_harq_indication_t *pNfapiMsg = (nfapi_nb_harq_indication_t *)msg; + unpack_p7_tlv_t unpack_fns[] = { + { NFAPI_NB_HARQ_INDICATION_BODY_TAG, &pNfapiMsg->nb_harq_indication_body, &unpack_nb_harq_indication_body_value}, + }; + return (pull16(ppReadPackedMsg, &pNfapiMsg->sfn_sf, end) && + unpack_p7_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); } -static uint8_t unpack_nrach_indication_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_nrach_indication_pdu_rel13_t* value = (nfapi_nrach_indication_pdu_rel13_t*)tlv; - - return (pull16(ppReadPackedMsg, &value->rnti, end) && - pull8(ppReadPackedMsg, &value->initial_sc, end) && - pull16(ppReadPackedMsg, &value->timing_advance, end) && - pull8(ppReadPackedMsg, &value->nrach_ce_level, end)); +static uint8_t unpack_nrach_indication_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_nrach_indication_pdu_rel13_t *value = (nfapi_nrach_indication_pdu_rel13_t *)tlv; + return (pull16(ppReadPackedMsg, &value->rnti, end) && + pull8(ppReadPackedMsg, &value->initial_sc, end) && + pull16(ppReadPackedMsg, &value->timing_advance, end) && + pull8(ppReadPackedMsg, &value->nrach_ce_level, end)); } -static uint8_t unpack_ue_release_resp(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config) -{ - nfapi_ue_release_response_t *pNfapiMsg = (nfapi_ue_release_response_t*)msg; - if(pull32(ppReadPackedMsg, &pNfapiMsg->error_code, end) == 0){ - return 0; - } - else{ - NFAPI_TRACE(NFAPI_TRACE_INFO, "ue_release_response:error_code = %d\n", pNfapiMsg->error_code); - } - return 1; +static uint8_t unpack_ue_release_resp(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t *config) { + nfapi_ue_release_response_t *pNfapiMsg = (nfapi_ue_release_response_t *)msg; + + if(pull32(ppReadPackedMsg, &pNfapiMsg->error_code, end) == 0) { + return 0; + } else { + NFAPI_TRACE(NFAPI_TRACE_INFO, "ue_release_response:error_code = %d\n", pNfapiMsg->error_code); + } + + return 1; } -static uint8_t unpack_nrach_indication_body_value(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) -{ - nfapi_nrach_indication_body_t* value = (nfapi_nrach_indication_body_t*)tlv; - uint8_t* nrachBodyEnd = *ppReadPackedMsg + value->tl.length; +static uint8_t unpack_nrach_indication_body_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end, nfapi_p7_codec_config_t *config) { + nfapi_nrach_indication_body_t *value = (nfapi_nrach_indication_body_t *)tlv; + uint8_t *nrachBodyEnd = *ppReadPackedMsg + value->tl.length; - if(nrachBodyEnd > end) - return 0; + if(nrachBodyEnd > end) + return 0; - if(pull8(ppReadPackedMsg, &value->number_of_initial_scs_detected, end) == 0) - return 0; + if(pull8(ppReadPackedMsg, &value->number_of_initial_scs_detected, end) == 0) + return 0; - if(value->number_of_initial_scs_detected > NFAPI_PREAMBLE_MAX_PDU) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s number of detected scs ind pdus exceed maxium (count:%d max:%d)\n", __FUNCTION__, value->number_of_initial_scs_detected, NFAPI_PREAMBLE_MAX_PDU); - return 0; - } + if(value->number_of_initial_scs_detected > NFAPI_PREAMBLE_MAX_PDU) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s number of detected scs ind pdus exceed maxium (count:%d max:%d)\n", __FUNCTION__, value->number_of_initial_scs_detected, NFAPI_PREAMBLE_MAX_PDU); + return 0; + } - value->nrach_pdu_list = (nfapi_nrach_indication_pdu_t*)nfapi_p7_allocate(sizeof(nfapi_nrach_indication_pdu_t) * value->number_of_initial_scs_detected, config); - if(value->nrach_pdu_list == NULL) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s failed to allocate nrach ind pdu list (count:%d)\n", __FUNCTION__, value->number_of_initial_scs_detected); - return 0; - } - - uint8_t i = 0; - for(i = 0; i < value->number_of_initial_scs_detected; ++i) - { - nfapi_nrach_indication_pdu_t* pdu = &(value->nrach_pdu_list[i]); + value->nrach_pdu_list = (nfapi_nrach_indication_pdu_t *)nfapi_p7_allocate(sizeof(nfapi_nrach_indication_pdu_t) * value->number_of_initial_scs_detected, config); - uint8_t* nrachPduInstanceEnd = *ppReadPackedMsg + 4 + 6; + if(value->nrach_pdu_list == NULL) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s failed to allocate nrach ind pdu list (count:%d)\n", __FUNCTION__, value->number_of_initial_scs_detected); + return 0; + } - unpack_tlv_t unpack_fns[] = - { - { NFAPI_NRACH_INDICATION_REL13_TAG, &pdu->nrach_indication_rel13, &unpack_nrach_indication_rel13_value}, - }; + uint8_t i = 0; - if(unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, nrachPduInstanceEnd, 0, 0) == 0) - return 0; - - } + for(i = 0; i < value->number_of_initial_scs_detected; ++i) { + nfapi_nrach_indication_pdu_t *pdu = &(value->nrach_pdu_list[i]); + uint8_t *nrachPduInstanceEnd = *ppReadPackedMsg + 4 + 6; + unpack_tlv_t unpack_fns[] = { + { NFAPI_NRACH_INDICATION_REL13_TAG, &pdu->nrach_indication_rel13, &unpack_nrach_indication_rel13_value}, + }; - return 1; + if(unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, nrachPduInstanceEnd, 0, 0) == 0) + return 0; + } + + return 1; } -static uint8_t unpack_nrach_indication(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config) -{ - nfapi_nrach_indication_t *pNfapiMsg = (nfapi_nrach_indication_t*)msg; - - unpack_p7_tlv_t unpack_fns[] = - { - { NFAPI_NRACH_INDICATION_BODY_TAG, &pNfapiMsg->nrach_indication_body, &unpack_nrach_indication_body_value}, - }; - - return (pull16(ppReadPackedMsg, &pNfapiMsg->sfn_sf, end) && - unpack_p7_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); +static uint8_t unpack_nrach_indication(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t *config) { + nfapi_nrach_indication_t *pNfapiMsg = (nfapi_nrach_indication_t *)msg; + unpack_p7_tlv_t unpack_fns[] = { + { NFAPI_NRACH_INDICATION_BODY_TAG, &pNfapiMsg->nrach_indication_body, &unpack_nrach_indication_body_value}, + }; + return (pull16(ppReadPackedMsg, &pNfapiMsg->sfn_sf, end) && + unpack_p7_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); } -static uint8_t unpack_nr_dl_node_sync(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config) -{ - nfapi_nr_dl_node_sync_t *pNfapiMsg = (nfapi_nr_dl_node_sync_t*)msg; - - unpack_p7_tlv_t unpack_fns[] = - { - }; - - return (pull32(ppReadPackedMsg, &pNfapiMsg->t1, end) && - pulls32(ppReadPackedMsg, &pNfapiMsg->delta_sfn_slot, end) && - unpack_p7_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); +static uint8_t unpack_nr_dl_node_sync(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t *config) { + nfapi_nr_dl_node_sync_t *pNfapiMsg = (nfapi_nr_dl_node_sync_t *)msg; + return (pull32(ppReadPackedMsg, &pNfapiMsg->t1, end) && + pulls32(ppReadPackedMsg, &pNfapiMsg->delta_sfn_slot, end) && + unpack_p7_tlv_list(NULL, 0, ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); } -static uint8_t unpack_dl_node_sync(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config) -{ - nfapi_dl_node_sync_t *pNfapiMsg = (nfapi_dl_node_sync_t*)msg; - - unpack_p7_tlv_t unpack_fns[] = - { - }; - - return (pull32(ppReadPackedMsg, &pNfapiMsg->t1, end) && - pulls32(ppReadPackedMsg, &pNfapiMsg->delta_sfn_sf, end) && - unpack_p7_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); +static uint8_t unpack_dl_node_sync(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t *config) { + nfapi_dl_node_sync_t *pNfapiMsg = (nfapi_dl_node_sync_t *)msg; + return (pull32(ppReadPackedMsg, &pNfapiMsg->t1, end) && + pulls32(ppReadPackedMsg, &pNfapiMsg->delta_sfn_sf, end) && + unpack_p7_tlv_list(NULL, 0, ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); } -static uint8_t unpack_nr_ul_node_sync(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config) -{ - nfapi_nr_ul_node_sync_t *pNfapiMsg = (nfapi_nr_ul_node_sync_t*)msg; - - unpack_p7_tlv_t unpack_fns[] = - { - }; - - return (pull32(ppReadPackedMsg, &pNfapiMsg->t1, end) && - pull32(ppReadPackedMsg, &pNfapiMsg->t2, end) && - pull32(ppReadPackedMsg, &pNfapiMsg->t3, end) && - unpack_p7_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); +static uint8_t unpack_nr_ul_node_sync(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t *config) { + nfapi_nr_ul_node_sync_t *pNfapiMsg = (nfapi_nr_ul_node_sync_t *)msg; + return (pull32(ppReadPackedMsg, &pNfapiMsg->t1, end) && + pull32(ppReadPackedMsg, &pNfapiMsg->t2, end) && + pull32(ppReadPackedMsg, &pNfapiMsg->t3, end) && + unpack_p7_tlv_list(NULL, 0, ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); } -static uint8_t unpack_ul_node_sync(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config) -{ - nfapi_ul_node_sync_t *pNfapiMsg = (nfapi_ul_node_sync_t*)msg; - - unpack_p7_tlv_t unpack_fns[] = - { - }; - - return (pull32(ppReadPackedMsg, &pNfapiMsg->t1, end) && - pull32(ppReadPackedMsg, &pNfapiMsg->t2, end) && - pull32(ppReadPackedMsg, &pNfapiMsg->t3, end) && - unpack_p7_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); +static uint8_t unpack_ul_node_sync(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t *config) { + nfapi_ul_node_sync_t *pNfapiMsg = (nfapi_ul_node_sync_t *)msg; + return (pull32(ppReadPackedMsg, &pNfapiMsg->t1, end) && + pull32(ppReadPackedMsg, &pNfapiMsg->t2, end) && + pull32(ppReadPackedMsg, &pNfapiMsg->t3, end) && + unpack_p7_tlv_list(NULL, 0, ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); } -static uint8_t unpack_timing_info(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config) -{ - nfapi_timing_info_t *pNfapiMsg = (nfapi_timing_info_t*)msg; - - unpack_p7_tlv_t unpack_fns[] = - { - }; - - return (pull32(ppReadPackedMsg, &pNfapiMsg->last_sfn_sf, end) && - pull32(ppReadPackedMsg, &pNfapiMsg->time_since_last_timing_info, end) && - pull32(ppReadPackedMsg, &pNfapiMsg->dl_config_jitter, end) && - pull32(ppReadPackedMsg, &pNfapiMsg->tx_request_jitter, end) && - pull32(ppReadPackedMsg, &pNfapiMsg->ul_config_jitter, end) && - pull32(ppReadPackedMsg, &pNfapiMsg->hi_dci0_jitter, end) && - pulls32(ppReadPackedMsg, &pNfapiMsg->dl_config_latest_delay, end) && - pulls32(ppReadPackedMsg, &pNfapiMsg->tx_request_latest_delay, end) && - pulls32(ppReadPackedMsg, &pNfapiMsg->ul_config_latest_delay, end) && - pulls32(ppReadPackedMsg, &pNfapiMsg->hi_dci0_latest_delay, end) && - pulls32(ppReadPackedMsg, &pNfapiMsg->dl_config_earliest_arrival, end) && - pulls32(ppReadPackedMsg, &pNfapiMsg->tx_request_earliest_arrival, end) && - pulls32(ppReadPackedMsg, &pNfapiMsg->ul_config_earliest_arrival, end) && - pulls32(ppReadPackedMsg, &pNfapiMsg->hi_dci0_earliest_arrival, end) && - unpack_p7_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); +static uint8_t unpack_timing_info(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t *config) { + nfapi_timing_info_t *pNfapiMsg = (nfapi_timing_info_t *)msg; + return (pull32(ppReadPackedMsg, &pNfapiMsg->last_sfn_sf, end) && + pull32(ppReadPackedMsg, &pNfapiMsg->time_since_last_timing_info, end) && + pull32(ppReadPackedMsg, &pNfapiMsg->dl_config_jitter, end) && + pull32(ppReadPackedMsg, &pNfapiMsg->tx_request_jitter, end) && + pull32(ppReadPackedMsg, &pNfapiMsg->ul_config_jitter, end) && + pull32(ppReadPackedMsg, &pNfapiMsg->hi_dci0_jitter, end) && + pulls32(ppReadPackedMsg, &pNfapiMsg->dl_config_latest_delay, end) && + pulls32(ppReadPackedMsg, &pNfapiMsg->tx_request_latest_delay, end) && + pulls32(ppReadPackedMsg, &pNfapiMsg->ul_config_latest_delay, end) && + pulls32(ppReadPackedMsg, &pNfapiMsg->hi_dci0_latest_delay, end) && + pulls32(ppReadPackedMsg, &pNfapiMsg->dl_config_earliest_arrival, end) && + pulls32(ppReadPackedMsg, &pNfapiMsg->tx_request_earliest_arrival, end) && + pulls32(ppReadPackedMsg, &pNfapiMsg->ul_config_earliest_arrival, end) && + pulls32(ppReadPackedMsg, &pNfapiMsg->hi_dci0_earliest_arrival, end) && + unpack_p7_tlv_list(NULL, 0, ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); } -static uint8_t unpack_nr_timing_info(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config) -{ - nfapi_nr_timing_info_t *pNfapiMsg = (nfapi_nr_timing_info_t*)msg; - - unpack_p7_tlv_t unpack_fns[] = - { - }; - - return (pull32(ppReadPackedMsg, &pNfapiMsg->last_sfn, end) && - pull32(ppReadPackedMsg, &pNfapiMsg->last_slot, end) && - pull32(ppReadPackedMsg, &pNfapiMsg->time_since_last_timing_info, end) && - pull32(ppReadPackedMsg, &pNfapiMsg->dl_tti_jitter, end) && - pull32(ppReadPackedMsg, &pNfapiMsg->tx_data_request_jitter, end) && - pull32(ppReadPackedMsg, &pNfapiMsg->ul_tti_jitter, end) && - pull32(ppReadPackedMsg, &pNfapiMsg->ul_dci_jitter, end) && - pulls32(ppReadPackedMsg, &pNfapiMsg->dl_tti_latest_delay, end) && - pulls32(ppReadPackedMsg, &pNfapiMsg->tx_data_request_latest_delay, end) && - pulls32(ppReadPackedMsg, &pNfapiMsg->ul_tti_latest_delay, end) && - pulls32(ppReadPackedMsg, &pNfapiMsg->ul_dci_latest_delay, end) && - pulls32(ppReadPackedMsg, &pNfapiMsg->dl_tti_earliest_arrival, end) && - pulls32(ppReadPackedMsg, &pNfapiMsg->tx_data_request_earliest_arrival, end) && - pulls32(ppReadPackedMsg, &pNfapiMsg->ul_tti_earliest_arrival, end) && - pulls32(ppReadPackedMsg, &pNfapiMsg->ul_dci_earliest_arrival, end) && - unpack_p7_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); +static uint8_t unpack_nr_timing_info(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t *config) { + nfapi_nr_timing_info_t *pNfapiMsg = (nfapi_nr_timing_info_t *)msg; + return (pull32(ppReadPackedMsg, &pNfapiMsg->last_sfn, end) && + pull32(ppReadPackedMsg, &pNfapiMsg->last_slot, end) && + pull32(ppReadPackedMsg, &pNfapiMsg->time_since_last_timing_info, end) && + pull32(ppReadPackedMsg, &pNfapiMsg->dl_tti_jitter, end) && + pull32(ppReadPackedMsg, &pNfapiMsg->tx_data_request_jitter, end) && + pull32(ppReadPackedMsg, &pNfapiMsg->ul_tti_jitter, end) && + pull32(ppReadPackedMsg, &pNfapiMsg->ul_dci_jitter, end) && + pulls32(ppReadPackedMsg, &pNfapiMsg->dl_tti_latest_delay, end) && + pulls32(ppReadPackedMsg, &pNfapiMsg->tx_data_request_latest_delay, end) && + pulls32(ppReadPackedMsg, &pNfapiMsg->ul_tti_latest_delay, end) && + pulls32(ppReadPackedMsg, &pNfapiMsg->ul_dci_latest_delay, end) && + pulls32(ppReadPackedMsg, &pNfapiMsg->dl_tti_earliest_arrival, end) && + pulls32(ppReadPackedMsg, &pNfapiMsg->tx_data_request_earliest_arrival, end) && + pulls32(ppReadPackedMsg, &pNfapiMsg->ul_tti_earliest_arrival, end) && + pulls32(ppReadPackedMsg, &pNfapiMsg->ul_dci_earliest_arrival, end) && + unpack_p7_tlv_list(NULL, 0, ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); } // unpack length check -static int check_unpack_length(nfapi_message_id_e msgId, uint32_t unpackedBufLen) -{ - int retLen = 0; +static int check_unpack_length(nfapi_message_id_e msgId, uint32_t unpackedBufLen) { + int retLen = 0; - switch (msgId) - { - case NFAPI_DL_CONFIG_REQUEST: - if (unpackedBufLen >= sizeof(nfapi_dl_config_request_t)) - retLen = sizeof(nfapi_dl_config_request_t); - break; + switch (msgId) { + case NFAPI_DL_CONFIG_REQUEST: + if (unpackedBufLen >= sizeof(nfapi_dl_config_request_t)) + retLen = sizeof(nfapi_dl_config_request_t); - case NFAPI_UL_CONFIG_REQUEST: - if (unpackedBufLen >= sizeof(nfapi_ul_config_request_t)) - retLen = sizeof(nfapi_ul_config_request_t); - break; + break; - case NFAPI_SUBFRAME_INDICATION: - if (unpackedBufLen >= sizeof(nfapi_subframe_indication_t)) - retLen = sizeof(nfapi_subframe_indication_t); - break; + case NFAPI_UL_CONFIG_REQUEST: + if (unpackedBufLen >= sizeof(nfapi_ul_config_request_t)) + retLen = sizeof(nfapi_ul_config_request_t); - case NFAPI_HI_DCI0_REQUEST: - if (unpackedBufLen >= sizeof(nfapi_hi_dci0_request_t)) - retLen = sizeof(nfapi_hi_dci0_request_t); - break; + break; - case NFAPI_TX_REQUEST: - if (unpackedBufLen >= sizeof(nfapi_tx_request_t)) - retLen = sizeof(nfapi_tx_request_t); - break; + case NFAPI_SUBFRAME_INDICATION: + if (unpackedBufLen >= sizeof(nfapi_subframe_indication_t)) + retLen = sizeof(nfapi_subframe_indication_t); - case NFAPI_HARQ_INDICATION: - if (unpackedBufLen >= sizeof(nfapi_harq_indication_t)) - retLen = sizeof(nfapi_harq_indication_t); - break; + break; - case NFAPI_CRC_INDICATION: - if (unpackedBufLen >= sizeof(nfapi_crc_indication_t)) - retLen = sizeof(nfapi_crc_indication_t); - break; + case NFAPI_HI_DCI0_REQUEST: + if (unpackedBufLen >= sizeof(nfapi_hi_dci0_request_t)) + retLen = sizeof(nfapi_hi_dci0_request_t); - case NFAPI_RX_ULSCH_INDICATION: - if (unpackedBufLen >= sizeof(nfapi_rx_indication_t)) - retLen = sizeof(nfapi_rx_indication_t); - break; + break; - case NFAPI_RACH_INDICATION: - if (unpackedBufLen >= sizeof(nfapi_rach_indication_t)) - retLen = sizeof(nfapi_rach_indication_t); - break; + case NFAPI_TX_REQUEST: + if (unpackedBufLen >= sizeof(nfapi_tx_request_t)) + retLen = sizeof(nfapi_tx_request_t); - case NFAPI_SRS_INDICATION: - if (unpackedBufLen >= sizeof(nfapi_srs_indication_t)) - retLen = sizeof(nfapi_srs_indication_t); - break; + break; - case NFAPI_RX_SR_INDICATION: - if (unpackedBufLen >= sizeof(nfapi_sr_indication_t)) - retLen = sizeof(nfapi_sr_indication_t); - break; + case NFAPI_HARQ_INDICATION: + if (unpackedBufLen >= sizeof(nfapi_harq_indication_t)) + retLen = sizeof(nfapi_harq_indication_t); - case NFAPI_RX_CQI_INDICATION: - if (unpackedBufLen >= sizeof(nfapi_cqi_indication_t)) - retLen = sizeof(nfapi_cqi_indication_t); - break; + break; - case NFAPI_LBT_DL_CONFIG_REQUEST: - if (unpackedBufLen >= sizeof(nfapi_lbt_dl_config_request_t)) - retLen = sizeof(nfapi_lbt_dl_config_request_t); - break; + case NFAPI_CRC_INDICATION: + if (unpackedBufLen >= sizeof(nfapi_crc_indication_t)) + retLen = sizeof(nfapi_crc_indication_t); - case NFAPI_LBT_DL_INDICATION: - if (unpackedBufLen >= sizeof(nfapi_lbt_dl_indication_t)) - retLen = sizeof(nfapi_lbt_dl_indication_t); - break; - - case NFAPI_NB_HARQ_INDICATION: - if (unpackedBufLen >= sizeof(nfapi_nb_harq_indication_t)) - retLen = sizeof(nfapi_nb_harq_indication_t); - break; - - case NFAPI_NRACH_INDICATION: - if (unpackedBufLen >= sizeof(nfapi_nrach_indication_t)) - retLen = sizeof(nfapi_nrach_indication_t); - break; - - case NFAPI_DL_NODE_SYNC: - if (unpackedBufLen >= sizeof(nfapi_dl_node_sync_t)) - retLen = sizeof(nfapi_dl_node_sync_t); - break; + break; - case NFAPI_UL_NODE_SYNC: - if (unpackedBufLen >= sizeof(nfapi_ul_node_sync_t)) - retLen = sizeof(nfapi_ul_node_sync_t); - break; + case NFAPI_RX_ULSCH_INDICATION: + if (unpackedBufLen >= sizeof(nfapi_rx_indication_t)) + retLen = sizeof(nfapi_rx_indication_t); - case NFAPI_TIMING_INFO: - if (unpackedBufLen >= sizeof(nfapi_timing_info_t)) - retLen = sizeof(nfapi_timing_info_t); - break; + break; - case NFAPI_UE_RELEASE_REQUEST: - if (unpackedBufLen >= sizeof(nfapi_ue_release_request_t)) - retLen = sizeof(nfapi_ue_release_request_t); - break; + case NFAPI_RACH_INDICATION: + if (unpackedBufLen >= sizeof(nfapi_rach_indication_t)) + retLen = sizeof(nfapi_rach_indication_t); - case NFAPI_UE_RELEASE_RESPONSE: - if (unpackedBufLen >= sizeof(nfapi_ue_release_response_t)) - retLen = sizeof(nfapi_ue_release_response_t); - break; + break; - default: - NFAPI_TRACE(NFAPI_TRACE_ERROR, "Unknown message ID %d\n", msgId); - break; - } + case NFAPI_SRS_INDICATION: + if (unpackedBufLen >= sizeof(nfapi_srs_indication_t)) + retLen = sizeof(nfapi_srs_indication_t); - return retLen; + break; + + case NFAPI_RX_SR_INDICATION: + if (unpackedBufLen >= sizeof(nfapi_sr_indication_t)) + retLen = sizeof(nfapi_sr_indication_t); + + break; + + case NFAPI_RX_CQI_INDICATION: + if (unpackedBufLen >= sizeof(nfapi_cqi_indication_t)) + retLen = sizeof(nfapi_cqi_indication_t); + + break; + + case NFAPI_LBT_DL_CONFIG_REQUEST: + if (unpackedBufLen >= sizeof(nfapi_lbt_dl_config_request_t)) + retLen = sizeof(nfapi_lbt_dl_config_request_t); + + break; + + case NFAPI_LBT_DL_INDICATION: + if (unpackedBufLen >= sizeof(nfapi_lbt_dl_indication_t)) + retLen = sizeof(nfapi_lbt_dl_indication_t); + + break; + + case NFAPI_NB_HARQ_INDICATION: + if (unpackedBufLen >= sizeof(nfapi_nb_harq_indication_t)) + retLen = sizeof(nfapi_nb_harq_indication_t); + + break; + + case NFAPI_NRACH_INDICATION: + if (unpackedBufLen >= sizeof(nfapi_nrach_indication_t)) + retLen = sizeof(nfapi_nrach_indication_t); + + break; + + case NFAPI_DL_NODE_SYNC: + if (unpackedBufLen >= sizeof(nfapi_dl_node_sync_t)) + retLen = sizeof(nfapi_dl_node_sync_t); + + break; + + case NFAPI_UL_NODE_SYNC: + if (unpackedBufLen >= sizeof(nfapi_ul_node_sync_t)) + retLen = sizeof(nfapi_ul_node_sync_t); + + break; + + case NFAPI_TIMING_INFO: + if (unpackedBufLen >= sizeof(nfapi_timing_info_t)) + retLen = sizeof(nfapi_timing_info_t); + + break; + + case NFAPI_UE_RELEASE_REQUEST: + if (unpackedBufLen >= sizeof(nfapi_ue_release_request_t)) + retLen = sizeof(nfapi_ue_release_request_t); + + break; + + case NFAPI_UE_RELEASE_RESPONSE: + if (unpackedBufLen >= sizeof(nfapi_ue_release_response_t)) + retLen = sizeof(nfapi_ue_release_response_t); + + break; + + default: + NFAPI_TRACE(NFAPI_TRACE_ERROR, "Unknown message ID %d\n", msgId); + break; + } + + return retLen; } -static int check_nr_unpack_length(nfapi_message_id_e msgId, uint32_t unpackedBufLen) -{ - int retLen = 0; +static int check_nr_unpack_length(nfapi_message_id_e msgId, uint32_t unpackedBufLen) { + int retLen = 0; - switch (msgId) - { - case NFAPI_NR_PHY_MSG_TYPE_DL_TTI_REQUEST: - if (unpackedBufLen >= sizeof(nfapi_nr_dl_tti_request_t)) - retLen = sizeof(nfapi_nr_dl_tti_request_t); - break; + switch (msgId) { + case NFAPI_NR_PHY_MSG_TYPE_DL_TTI_REQUEST: + if (unpackedBufLen >= sizeof(nfapi_nr_dl_tti_request_t)) + retLen = sizeof(nfapi_nr_dl_tti_request_t); - case NFAPI_NR_PHY_MSG_TYPE_UL_TTI_REQUEST: - if (unpackedBufLen >= sizeof(nfapi_nr_ul_tti_request_t)) - retLen = sizeof(nfapi_nr_ul_tti_request_t); - break; + break; - case NFAPI_SUBFRAME_INDICATION: - if (unpackedBufLen >= sizeof(nfapi_subframe_indication_t)) - retLen = sizeof(nfapi_subframe_indication_t); - break; + case NFAPI_NR_PHY_MSG_TYPE_UL_TTI_REQUEST: + if (unpackedBufLen >= sizeof(nfapi_nr_ul_tti_request_t)) + retLen = sizeof(nfapi_nr_ul_tti_request_t); - case NFAPI_NR_PHY_MSG_TYPE_UL_DCI_REQUEST: - if (unpackedBufLen >= sizeof(nfapi_nr_ul_dci_request_t)) - retLen = sizeof(nfapi_nr_ul_dci_request_t); - break; + break; - case NFAPI_NR_PHY_MSG_TYPE_TX_DATA_REQUEST: - if (unpackedBufLen >= sizeof(nfapi_nr_tx_data_request_t)) - retLen = sizeof(nfapi_nr_tx_data_request_t); - break; + case NFAPI_SUBFRAME_INDICATION: + if (unpackedBufLen >= sizeof(nfapi_subframe_indication_t)) + retLen = sizeof(nfapi_subframe_indication_t); - case NFAPI_HARQ_INDICATION: - if (unpackedBufLen >= sizeof(nfapi_harq_indication_t)) - retLen = sizeof(nfapi_harq_indication_t); - break; + break; - case NFAPI_CRC_INDICATION: - if (unpackedBufLen >= sizeof(nfapi_crc_indication_t)) - retLen = sizeof(nfapi_crc_indication_t); - break; + case NFAPI_NR_PHY_MSG_TYPE_UL_DCI_REQUEST: + if (unpackedBufLen >= sizeof(nfapi_nr_ul_dci_request_t)) + retLen = sizeof(nfapi_nr_ul_dci_request_t); - case NFAPI_RX_ULSCH_INDICATION: - if (unpackedBufLen >= sizeof(nfapi_rx_indication_t)) - retLen = sizeof(nfapi_rx_indication_t); - break; + break; - case NFAPI_RACH_INDICATION: - if (unpackedBufLen >= sizeof(nfapi_rach_indication_t)) - retLen = sizeof(nfapi_rach_indication_t); - break; + case NFAPI_NR_PHY_MSG_TYPE_TX_DATA_REQUEST: + if (unpackedBufLen >= sizeof(nfapi_nr_tx_data_request_t)) + retLen = sizeof(nfapi_nr_tx_data_request_t); - case NFAPI_SRS_INDICATION: - if (unpackedBufLen >= sizeof(nfapi_srs_indication_t)) - retLen = sizeof(nfapi_srs_indication_t); - break; + break; - case NFAPI_RX_SR_INDICATION: - if (unpackedBufLen >= sizeof(nfapi_sr_indication_t)) - retLen = sizeof(nfapi_sr_indication_t); - break; + case NFAPI_HARQ_INDICATION: + if (unpackedBufLen >= sizeof(nfapi_harq_indication_t)) + retLen = sizeof(nfapi_harq_indication_t); - case NFAPI_RX_CQI_INDICATION: - if (unpackedBufLen >= sizeof(nfapi_cqi_indication_t)) - retLen = sizeof(nfapi_cqi_indication_t); - break; + break; - case NFAPI_LBT_DL_CONFIG_REQUEST: - if (unpackedBufLen >= sizeof(nfapi_lbt_dl_config_request_t)) - retLen = sizeof(nfapi_lbt_dl_config_request_t); - break; + case NFAPI_CRC_INDICATION: + if (unpackedBufLen >= sizeof(nfapi_crc_indication_t)) + retLen = sizeof(nfapi_crc_indication_t); - case NFAPI_LBT_DL_INDICATION: - if (unpackedBufLen >= sizeof(nfapi_lbt_dl_indication_t)) - retLen = sizeof(nfapi_lbt_dl_indication_t); - break; - - case NFAPI_NB_HARQ_INDICATION: - if (unpackedBufLen >= sizeof(nfapi_nb_harq_indication_t)) - retLen = sizeof(nfapi_nb_harq_indication_t); - break; - - case NFAPI_NRACH_INDICATION: - if (unpackedBufLen >= sizeof(nfapi_nrach_indication_t)) - retLen = sizeof(nfapi_nrach_indication_t); - break; - - case NFAPI_NR_PHY_MSG_TYPE_DL_NODE_SYNC: - if (unpackedBufLen >= sizeof(nfapi_nr_dl_node_sync_t)) - retLen = sizeof(nfapi_nr_dl_node_sync_t); - break; + break; - case NFAPI_NR_PHY_MSG_TYPE_UL_NODE_SYNC: - if (unpackedBufLen >= sizeof(nfapi_nr_ul_node_sync_t)) - retLen = sizeof(nfapi_nr_ul_node_sync_t); - break; + case NFAPI_RX_ULSCH_INDICATION: + if (unpackedBufLen >= sizeof(nfapi_rx_indication_t)) + retLen = sizeof(nfapi_rx_indication_t); - case NFAPI_TIMING_INFO: - if (unpackedBufLen >= sizeof(nfapi_timing_info_t)) - retLen = sizeof(nfapi_timing_info_t); - break; + break; - case NFAPI_UE_RELEASE_REQUEST: - if (unpackedBufLen >= sizeof(nfapi_ue_release_request_t)) - retLen = sizeof(nfapi_ue_release_request_t); - break; + case NFAPI_RACH_INDICATION: + if (unpackedBufLen >= sizeof(nfapi_rach_indication_t)) + retLen = sizeof(nfapi_rach_indication_t); - case NFAPI_UE_RELEASE_RESPONSE: - if (unpackedBufLen >= sizeof(nfapi_ue_release_response_t)) - retLen = sizeof(nfapi_ue_release_response_t); - break; + break; - default: - NFAPI_TRACE(NFAPI_TRACE_ERROR, "Unknown message ID %d\n", msgId); - break; - } + case NFAPI_SRS_INDICATION: + if (unpackedBufLen >= sizeof(nfapi_srs_indication_t)) + retLen = sizeof(nfapi_srs_indication_t); - return retLen; + break; + + case NFAPI_RX_SR_INDICATION: + if (unpackedBufLen >= sizeof(nfapi_sr_indication_t)) + retLen = sizeof(nfapi_sr_indication_t); + + break; + + case NFAPI_RX_CQI_INDICATION: + if (unpackedBufLen >= sizeof(nfapi_cqi_indication_t)) + retLen = sizeof(nfapi_cqi_indication_t); + + break; + + case NFAPI_LBT_DL_CONFIG_REQUEST: + if (unpackedBufLen >= sizeof(nfapi_lbt_dl_config_request_t)) + retLen = sizeof(nfapi_lbt_dl_config_request_t); + + break; + + case NFAPI_LBT_DL_INDICATION: + if (unpackedBufLen >= sizeof(nfapi_lbt_dl_indication_t)) + retLen = sizeof(nfapi_lbt_dl_indication_t); + + break; + + case NFAPI_NB_HARQ_INDICATION: + if (unpackedBufLen >= sizeof(nfapi_nb_harq_indication_t)) + retLen = sizeof(nfapi_nb_harq_indication_t); + + break; + + case NFAPI_NRACH_INDICATION: + if (unpackedBufLen >= sizeof(nfapi_nrach_indication_t)) + retLen = sizeof(nfapi_nrach_indication_t); + + break; + + case NFAPI_NR_PHY_MSG_TYPE_DL_NODE_SYNC: + if (unpackedBufLen >= sizeof(nfapi_nr_dl_node_sync_t)) + retLen = sizeof(nfapi_nr_dl_node_sync_t); + + break; + + case NFAPI_NR_PHY_MSG_TYPE_UL_NODE_SYNC: + if (unpackedBufLen >= sizeof(nfapi_nr_ul_node_sync_t)) + retLen = sizeof(nfapi_nr_ul_node_sync_t); + + break; + + case NFAPI_TIMING_INFO: + if (unpackedBufLen >= sizeof(nfapi_timing_info_t)) + retLen = sizeof(nfapi_timing_info_t); + + break; + + case NFAPI_UE_RELEASE_REQUEST: + if (unpackedBufLen >= sizeof(nfapi_ue_release_request_t)) + retLen = sizeof(nfapi_ue_release_request_t); + + break; + + case NFAPI_UE_RELEASE_RESPONSE: + if (unpackedBufLen >= sizeof(nfapi_ue_release_response_t)) + retLen = sizeof(nfapi_ue_release_response_t); + + break; + + default: + NFAPI_TRACE(NFAPI_TRACE_ERROR, "Unknown message ID %d\n", msgId); + break; + } + + return retLen; } // Main unpack functions - public -int nfapi_p7_message_header_unpack(void *pMessageBuf, uint32_t messageBufLen, void *pUnpackedBuf, uint32_t unpackedBufLen, nfapi_p7_codec_config_t* config) -{ - nfapi_p7_message_header_t *pMessageHeader = pUnpackedBuf; - uint8_t *pReadPackedMessage = pMessageBuf; - uint8_t *end = pMessageBuf + messageBufLen; +int nfapi_p7_message_header_unpack(void *pMessageBuf, uint32_t messageBufLen, void *pUnpackedBuf, uint32_t unpackedBufLen, nfapi_p7_codec_config_t *config) { + nfapi_p7_message_header_t *pMessageHeader = pUnpackedBuf; + uint8_t *pReadPackedMessage = pMessageBuf; + uint8_t *end = pMessageBuf + messageBufLen; - if (pMessageBuf == NULL || pUnpackedBuf == NULL) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "P7 header unpack supplied pointers are null\n"); - return -1; - } + if (pMessageBuf == NULL || pUnpackedBuf == NULL) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "P7 header unpack supplied pointers are null\n"); + return -1; + } - if (messageBufLen < NFAPI_P7_HEADER_LENGTH || unpackedBufLen < sizeof(nfapi_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; - } + if (messageBufLen < NFAPI_P7_HEADER_LENGTH || unpackedBufLen < sizeof(nfapi_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; + } - // process the header - if(!(pull16(&pReadPackedMessage, &pMessageHeader->phy_id, end) && - pull16(&pReadPackedMessage, &pMessageHeader->message_id, end) && - pull16(&pReadPackedMessage, &pMessageHeader->message_length, end) && - pull16(&pReadPackedMessage, &pMessageHeader->m_segment_sequence, end) && - pull32(&pReadPackedMessage, &pMessageHeader->checksum, end) && - pull32(&pReadPackedMessage, &pMessageHeader->transmit_timestamp, end))) - return -1; + // process the header + if(!(pull16(&pReadPackedMessage, &pMessageHeader->phy_id, end) && + pull16(&pReadPackedMessage, &pMessageHeader->message_id, end) && + pull16(&pReadPackedMessage, &pMessageHeader->message_length, end) && + pull16(&pReadPackedMessage, &pMessageHeader->m_segment_sequence, end) && + pull32(&pReadPackedMessage, &pMessageHeader->checksum, end) && + pull32(&pReadPackedMessage, &pMessageHeader->transmit_timestamp, end))) + return -1; - return 0; + return 0; } -int nfapi_p7_message_unpack(void *pMessageBuf, uint32_t messageBufLen, void *pUnpackedBuf, uint32_t unpackedBufLen, nfapi_p7_codec_config_t* config) -{ - int result = 0; - nfapi_p7_message_header_t *pMessageHeader = (nfapi_p7_message_header_t*)pUnpackedBuf; - uint8_t *pReadPackedMessage = pMessageBuf; - uint8_t *end = pMessageBuf + messageBufLen; +int nfapi_p7_message_unpack(void *pMessageBuf, uint32_t messageBufLen, void *pUnpackedBuf, uint32_t unpackedBufLen, nfapi_p7_codec_config_t *config) { + int result = 0; + nfapi_p7_message_header_t *pMessageHeader = (nfapi_p7_message_header_t *)pUnpackedBuf; + uint8_t *pReadPackedMessage = pMessageBuf; + uint8_t *end = pMessageBuf + messageBufLen; - if (pMessageBuf == NULL || pUnpackedBuf == NULL) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "P7 unpack supplied pointers are null\n"); - return -1; - } + if (pMessageBuf == NULL || pUnpackedBuf == NULL) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "P7 unpack supplied pointers are null\n"); + return -1; + } + + if (messageBufLen < NFAPI_P7_HEADER_LENGTH || unpackedBufLen < sizeof(nfapi_p7_message_header_t)) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "P7 unpack supplied message buffer is too small %d, %d\n", messageBufLen, unpackedBufLen); + return -1; + } - if (messageBufLen < NFAPI_P7_HEADER_LENGTH || unpackedBufLen < sizeof(nfapi_p7_message_header_t)) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "P7 unpack supplied message buffer is too small %d, %d\n", messageBufLen, unpackedBufLen); - return -1; - } /* uint8_t *ptr = pMessageBuf; - printf("\n Read P7 message unpack: "); - while(ptr < end){ - printf(" %d ", *ptr); - ptr++; - } - printf("\n"); -*/ - // clean the supplied buffer for - tag value blanking - (void)memset(pUnpackedBuf, 0, unpackedBufLen); + printf("\n Read P7 message unpack: "); + while(ptr < end){ + printf(" %d ", *ptr); + ptr++; + } + printf("\n"); + */ + // clean the supplied buffer for - tag value blanking + (void)memset(pUnpackedBuf, 0, unpackedBufLen); - // process the header - if(!(pull16(&pReadPackedMessage, &pMessageHeader->phy_id, end) && - pull16(&pReadPackedMessage, &pMessageHeader->message_id, end) && - pull16(&pReadPackedMessage, &pMessageHeader->message_length, end) && - pull16(&pReadPackedMessage, &pMessageHeader->m_segment_sequence, end) && - pull32(&pReadPackedMessage, &pMessageHeader->checksum, end) && - pull32(&pReadPackedMessage, &pMessageHeader->transmit_timestamp, end))) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "P7 unpack header failed\n"); - return -1; - } + // process the header + if(!(pull16(&pReadPackedMessage, &pMessageHeader->phy_id, end) && + pull16(&pReadPackedMessage, &pMessageHeader->message_id, end) && + pull16(&pReadPackedMessage, &pMessageHeader->message_length, end) && + pull16(&pReadPackedMessage, &pMessageHeader->m_segment_sequence, end) && + pull32(&pReadPackedMessage, &pMessageHeader->checksum, end) && + pull32(&pReadPackedMessage, &pMessageHeader->transmit_timestamp, end))) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "P7 unpack header failed\n"); + return -1; + } - 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; - } + 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; + } - /* - if(check_unpack_length(pMessageHeader->message_id, unpackedBufLen) == 0) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "P7 unpack unpack buffer is not large enough \n"); - return -1; - } - */ + /* + if(check_unpack_length(pMessageHeader->message_id, unpackedBufLen) == 0) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "P7 unpack unpack buffer is not large enough \n"); + return -1; + } + */ - // look for the specific message - switch (pMessageHeader->message_id) - { - case NFAPI_DL_CONFIG_REQUEST: - if (check_unpack_length(NFAPI_DL_CONFIG_REQUEST, unpackedBufLen)) - result = unpack_dl_config_request(&pReadPackedMessage, end, pMessageHeader, config); - else - return -1; - break; + // look for the specific message + switch (pMessageHeader->message_id) { + case NFAPI_DL_CONFIG_REQUEST: + if (check_unpack_length(NFAPI_DL_CONFIG_REQUEST, unpackedBufLen)) + result = unpack_dl_config_request(&pReadPackedMessage, end, pMessageHeader, config); + else + return -1; - case NFAPI_UL_CONFIG_REQUEST: - if (check_unpack_length(NFAPI_UL_CONFIG_REQUEST, unpackedBufLen)) - result = unpack_ul_config_request(&pReadPackedMessage, end, pMessageHeader, config); - else - return -1; - break; - case NFAPI_TX_REQUEST: - if (check_unpack_length(NFAPI_TX_REQUEST, unpackedBufLen)) - result = unpack_tx_request(&pReadPackedMessage, end, pMessageHeader, config); - else - return -1; - break; - case NFAPI_HI_DCI0_REQUEST: - if (check_unpack_length(NFAPI_HI_DCI0_REQUEST, unpackedBufLen)) - result = unpack_hi_dci0_request(&pReadPackedMessage, end, pMessageHeader, config); - else - return -1; - break; + break; - case NFAPI_UE_RELEASE_REQUEST: - if (check_unpack_length(NFAPI_UE_RELEASE_REQUEST, unpackedBufLen)) - result = unpack_ue_release_request(&pReadPackedMessage, end, pMessageHeader, config); - else - return -1; - break; + case NFAPI_UL_CONFIG_REQUEST: + if (check_unpack_length(NFAPI_UL_CONFIG_REQUEST, unpackedBufLen)) + result = unpack_ul_config_request(&pReadPackedMessage, end, pMessageHeader, config); + else + return -1; - case NFAPI_HARQ_INDICATION: - if (check_unpack_length(NFAPI_HARQ_INDICATION, unpackedBufLen)) - result = unpack_harq_indication(&pReadPackedMessage, end, pMessageHeader, config); - else - return -1; - break; + break; - case NFAPI_CRC_INDICATION: - if (check_unpack_length(NFAPI_CRC_INDICATION, unpackedBufLen)) - result = unpack_crc_indication(&pReadPackedMessage,end , pMessageHeader, config); - else - return -1; - break; + case NFAPI_TX_REQUEST: + if (check_unpack_length(NFAPI_TX_REQUEST, unpackedBufLen)) + result = unpack_tx_request(&pReadPackedMessage, end, pMessageHeader, config); + else + return -1; - case NFAPI_RX_ULSCH_INDICATION: - if (check_unpack_length(NFAPI_RX_ULSCH_INDICATION, unpackedBufLen)) - result = unpack_rx_indication(&pReadPackedMessage, end, pMessageHeader, config); - else - return -1; - break; + break; - case NFAPI_RACH_INDICATION: - if (check_unpack_length(NFAPI_RACH_INDICATION, unpackedBufLen)) - result = unpack_rach_indication(&pReadPackedMessage, end, pMessageHeader, config); - else - return -1; - break; + case NFAPI_HI_DCI0_REQUEST: + if (check_unpack_length(NFAPI_HI_DCI0_REQUEST, unpackedBufLen)) + result = unpack_hi_dci0_request(&pReadPackedMessage, end, pMessageHeader, config); + else + return -1; - case NFAPI_SRS_INDICATION: - if (check_unpack_length(NFAPI_SRS_INDICATION, unpackedBufLen)) - result = unpack_srs_indication(&pReadPackedMessage, end, pMessageHeader, config); - else - return -1; - break; + break; - case NFAPI_RX_SR_INDICATION: - if (check_unpack_length(NFAPI_RX_SR_INDICATION, unpackedBufLen)) - result = unpack_sr_indication(&pReadPackedMessage, end, pMessageHeader, config); - else - return -1; - break; + case NFAPI_UE_RELEASE_REQUEST: + if (check_unpack_length(NFAPI_UE_RELEASE_REQUEST, unpackedBufLen)) + result = unpack_ue_release_request(&pReadPackedMessage, end, pMessageHeader, config); + else + return -1; - case NFAPI_RX_CQI_INDICATION: - if (check_unpack_length(NFAPI_RX_CQI_INDICATION, unpackedBufLen)) - result = unpack_cqi_indication(&pReadPackedMessage, end, pMessageHeader, config); - else - return -1; - break; + break; - case NFAPI_LBT_DL_CONFIG_REQUEST: - if (check_unpack_length(NFAPI_LBT_DL_CONFIG_REQUEST, unpackedBufLen)) - result = unpack_lbt_dl_config_request(&pReadPackedMessage, end, pMessageHeader, config); - else - return -1; - break; + case NFAPI_HARQ_INDICATION: + if (check_unpack_length(NFAPI_HARQ_INDICATION, unpackedBufLen)) + result = unpack_harq_indication(&pReadPackedMessage, end, pMessageHeader, config); + else + return -1; - case NFAPI_LBT_DL_INDICATION: - if (check_unpack_length(NFAPI_LBT_DL_INDICATION, unpackedBufLen)) - result = unpack_lbt_dl_indication(&pReadPackedMessage, end, pMessageHeader, config); - else - return -1; - break; - - case NFAPI_NB_HARQ_INDICATION: - if (check_unpack_length(NFAPI_NB_HARQ_INDICATION, unpackedBufLen)) - result = unpack_nb_harq_indication(&pReadPackedMessage, end, pMessageHeader, config); - else - return -1; - break; - - case NFAPI_NRACH_INDICATION: - if (check_unpack_length(NFAPI_NRACH_INDICATION, unpackedBufLen)) - result = unpack_nrach_indication(&pReadPackedMessage, end, pMessageHeader, config); - else - return -1; - break; - - case NFAPI_DL_NODE_SYNC: - if (check_unpack_length(NFAPI_DL_NODE_SYNC, unpackedBufLen)) - result = unpack_dl_node_sync(&pReadPackedMessage, end, pMessageHeader, config); - else - return -1; - break; + break; - case NFAPI_UL_NODE_SYNC: - if (check_unpack_length(NFAPI_UL_NODE_SYNC, unpackedBufLen)) - result = unpack_ul_node_sync(&pReadPackedMessage, end , pMessageHeader, config); - else - return -1; - break; + case NFAPI_CRC_INDICATION: + if (check_unpack_length(NFAPI_CRC_INDICATION, unpackedBufLen)) + result = unpack_crc_indication(&pReadPackedMessage,end, pMessageHeader, config); + else + return -1; - case NFAPI_TIMING_INFO: - if (check_unpack_length(NFAPI_TIMING_INFO, unpackedBufLen)) - result = unpack_timing_info(&pReadPackedMessage, end, pMessageHeader, config); - else - return -1; - break; + break; - case NFAPI_UE_RELEASE_RESPONSE: - if (check_unpack_length(NFAPI_UE_RELEASE_RESPONSE, unpackedBufLen)) - result = unpack_ue_release_resp(&pReadPackedMessage, end, pMessageHeader, config); - else - return -1; - break; + case NFAPI_RX_ULSCH_INDICATION: + if (check_unpack_length(NFAPI_RX_ULSCH_INDICATION, unpackedBufLen)) + result = unpack_rx_indication(&pReadPackedMessage, end, pMessageHeader, config); + else + return -1; - default: + break; - if(pMessageHeader->message_id >= NFAPI_VENDOR_EXT_MSG_MIN && - pMessageHeader->message_id <= NFAPI_VENDOR_EXT_MSG_MAX) - { - if(config && config->unpack_p7_vendor_extension) - { - result = (config->unpack_p7_vendor_extension)(pMessageHeader, &pReadPackedMessage, end, config); - } - else - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s VE NFAPI message ID %d. No ve decoder provided\n", __FUNCTION__, pMessageHeader->message_id); - } - } - else - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s NFAPI Unknown message ID %d\n", __FUNCTION__, pMessageHeader->message_id); - } - break; - } + case NFAPI_RACH_INDICATION: + if (check_unpack_length(NFAPI_RACH_INDICATION, unpackedBufLen)) + result = unpack_rach_indication(&pReadPackedMessage, end, pMessageHeader, config); + else + return -1; - if(result == 0) - return -1; - else - return 0; + break; + + case NFAPI_SRS_INDICATION: + if (check_unpack_length(NFAPI_SRS_INDICATION, unpackedBufLen)) + result = unpack_srs_indication(&pReadPackedMessage, end, pMessageHeader, config); + else + return -1; + + break; + + case NFAPI_RX_SR_INDICATION: + if (check_unpack_length(NFAPI_RX_SR_INDICATION, unpackedBufLen)) + result = unpack_sr_indication(&pReadPackedMessage, end, pMessageHeader, config); + else + return -1; + + break; + + case NFAPI_RX_CQI_INDICATION: + if (check_unpack_length(NFAPI_RX_CQI_INDICATION, unpackedBufLen)) + result = unpack_cqi_indication(&pReadPackedMessage, end, pMessageHeader, config); + else + return -1; + + break; + + case NFAPI_LBT_DL_CONFIG_REQUEST: + if (check_unpack_length(NFAPI_LBT_DL_CONFIG_REQUEST, unpackedBufLen)) + result = unpack_lbt_dl_config_request(&pReadPackedMessage, end, pMessageHeader, config); + else + return -1; + + break; + + case NFAPI_LBT_DL_INDICATION: + if (check_unpack_length(NFAPI_LBT_DL_INDICATION, unpackedBufLen)) + result = unpack_lbt_dl_indication(&pReadPackedMessage, end, pMessageHeader, config); + else + return -1; + + break; + + case NFAPI_NB_HARQ_INDICATION: + if (check_unpack_length(NFAPI_NB_HARQ_INDICATION, unpackedBufLen)) + result = unpack_nb_harq_indication(&pReadPackedMessage, end, pMessageHeader, config); + else + return -1; + + break; + + case NFAPI_NRACH_INDICATION: + if (check_unpack_length(NFAPI_NRACH_INDICATION, unpackedBufLen)) + result = unpack_nrach_indication(&pReadPackedMessage, end, pMessageHeader, config); + else + return -1; + + break; + + case NFAPI_DL_NODE_SYNC: + if (check_unpack_length(NFAPI_DL_NODE_SYNC, unpackedBufLen)) + result = unpack_dl_node_sync(&pReadPackedMessage, end, pMessageHeader, config); + else + return -1; + + break; + + case NFAPI_UL_NODE_SYNC: + if (check_unpack_length(NFAPI_UL_NODE_SYNC, unpackedBufLen)) + result = unpack_ul_node_sync(&pReadPackedMessage, end, pMessageHeader, config); + else + return -1; + + break; + + case NFAPI_TIMING_INFO: + if (check_unpack_length(NFAPI_TIMING_INFO, unpackedBufLen)) + result = unpack_timing_info(&pReadPackedMessage, end, pMessageHeader, config); + else + return -1; + + break; + + case NFAPI_UE_RELEASE_RESPONSE: + if (check_unpack_length(NFAPI_UE_RELEASE_RESPONSE, unpackedBufLen)) + result = unpack_ue_release_resp(&pReadPackedMessage, end, pMessageHeader, config); + else + return -1; + + break; + + default: + if(pMessageHeader->message_id >= NFAPI_VENDOR_EXT_MSG_MIN && + pMessageHeader->message_id <= NFAPI_VENDOR_EXT_MSG_MAX) { + if(config && config->unpack_p7_vendor_extension) { + result = (config->unpack_p7_vendor_extension)(pMessageHeader, &pReadPackedMessage, end, config); + } else { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s VE NFAPI message ID %d. No ve decoder provided\n", __FUNCTION__, pMessageHeader->message_id); + } + } else { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s NFAPI Unknown message ID %d\n", __FUNCTION__, pMessageHeader->message_id); + } + + break; + } + + if(result == 0) + return -1; + else + return 0; } -int nfapi_nr_p7_message_unpack(void *pMessageBuf, uint32_t messageBufLen, void *pUnpackedBuf, uint32_t unpackedBufLen, nfapi_p7_codec_config_t* config) -{ - int result = 0; - nfapi_p7_message_header_t *pMessageHeader = (nfapi_p7_message_header_t*)pUnpackedBuf; - uint8_t *pReadPackedMessage = pMessageBuf; - uint8_t *end = pMessageBuf + messageBufLen; +int nfapi_nr_p7_message_unpack(void *pMessageBuf, uint32_t messageBufLen, void *pUnpackedBuf, uint32_t unpackedBufLen, nfapi_p7_codec_config_t *config) { + int result = 0; + nfapi_p7_message_header_t *pMessageHeader = (nfapi_p7_message_header_t *)pUnpackedBuf; + uint8_t *pReadPackedMessage = pMessageBuf; + uint8_t *end = pMessageBuf + messageBufLen; - if (pMessageBuf == NULL || pUnpackedBuf == NULL) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "P7 unpack supplied pointers are null\n"); - return -1; - } + if (pMessageBuf == NULL || pUnpackedBuf == NULL) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "P7 unpack supplied pointers are null\n"); + return -1; + } + + if (messageBufLen < NFAPI_P7_HEADER_LENGTH || unpackedBufLen < sizeof(nfapi_p7_message_header_t)) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "P7 unpack supplied message buffer is too small %d, %d\n", messageBufLen, unpackedBufLen); + return -1; + } - if (messageBufLen < NFAPI_P7_HEADER_LENGTH || unpackedBufLen < sizeof(nfapi_p7_message_header_t)) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "P7 unpack supplied message buffer is too small %d, %d\n", messageBufLen, unpackedBufLen); - return -1; - } /* uint8_t *ptr = pMessageBuf; - printf("\n Read P7 message unpack: "); - while(ptr < end){ - printf(" %d ", *ptr); - ptr++; - } - printf("\n"); -*/ - // clean the supplied buffer for - tag value blanking - (void)memset(pUnpackedBuf, 0, unpackedBufLen); + printf("\n Read P7 message unpack: "); + while(ptr < end){ + printf(" %d ", *ptr); + ptr++; + } + printf("\n"); + */ + // clean the supplied buffer for - tag value blanking + (void)memset(pUnpackedBuf, 0, unpackedBufLen); - // process the header - if(!(pull16(&pReadPackedMessage, &pMessageHeader->phy_id, end) && - pull16(&pReadPackedMessage, &pMessageHeader->message_id, end) && - pull16(&pReadPackedMessage, &pMessageHeader->message_length, end) && - pull16(&pReadPackedMessage, &pMessageHeader->m_segment_sequence, end) && - pull32(&pReadPackedMessage, &pMessageHeader->checksum, end) && - pull32(&pReadPackedMessage, &pMessageHeader->transmit_timestamp, end))) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "P7 unpack header failed\n"); - return -1; - } + // process the header + if(!(pull16(&pReadPackedMessage, &pMessageHeader->phy_id, end) && + pull16(&pReadPackedMessage, &pMessageHeader->message_id, end) && + pull16(&pReadPackedMessage, &pMessageHeader->message_length, end) && + pull16(&pReadPackedMessage, &pMessageHeader->m_segment_sequence, end) && + pull32(&pReadPackedMessage, &pMessageHeader->checksum, end) && + pull32(&pReadPackedMessage, &pMessageHeader->transmit_timestamp, end))) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "P7 unpack header failed\n"); + return -1; + } - 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; - } + 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; + } - /* - if(check_unpack_length(pMessageHeader->message_id, unpackedBufLen) == 0) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "P7 unpack unpack buffer is not large enough \n"); - return -1; - } - */ + /* + if(check_unpack_length(pMessageHeader->message_id, unpackedBufLen) == 0) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "P7 unpack unpack buffer is not large enough \n"); + return -1; + } + */ - // look for the specific message - switch (pMessageHeader->message_id) - { - case NFAPI_NR_PHY_MSG_TYPE_DL_TTI_REQUEST: - if (check_nr_unpack_length(NFAPI_NR_PHY_MSG_TYPE_DL_TTI_REQUEST, unpackedBufLen)) - result = unpack_dl_tti_request(&pReadPackedMessage, end, pMessageHeader, config); - else - return -1; - break; + // look for the specific message + switch (pMessageHeader->message_id) { + case NFAPI_NR_PHY_MSG_TYPE_DL_TTI_REQUEST: + if (check_nr_unpack_length(NFAPI_NR_PHY_MSG_TYPE_DL_TTI_REQUEST, unpackedBufLen)) + result = unpack_dl_tti_request(&pReadPackedMessage, end, pMessageHeader, config); + else + return -1; - case NFAPI_NR_PHY_MSG_TYPE_UL_TTI_REQUEST: - if (check_nr_unpack_length(NFAPI_NR_PHY_MSG_TYPE_UL_TTI_REQUEST, unpackedBufLen)) - result = unpack_ul_tti_request(&pReadPackedMessage, end, pMessageHeader, config); - else - return -1; - break; - case NFAPI_NR_PHY_MSG_TYPE_TX_DATA_REQUEST: - if (check_nr_unpack_length(NFAPI_NR_PHY_MSG_TYPE_TX_DATA_REQUEST, unpackedBufLen)) - result = unpack_tx_data_request(&pReadPackedMessage, end, pMessageHeader, config); - else - return -1; - break; - case NFAPI_NR_PHY_MSG_TYPE_UL_DCI_REQUEST: - if (check_nr_unpack_length(NFAPI_NR_PHY_MSG_TYPE_UL_DCI_REQUEST, unpackedBufLen)) - result = unpack_ul_dci_request(&pReadPackedMessage, end, pMessageHeader, config); - else - return -1; - break; - - case NFAPI_UE_RELEASE_REQUEST: - if (check_nr_unpack_length(NFAPI_UE_RELEASE_REQUEST, unpackedBufLen)) - result = unpack_ue_release_request(&pReadPackedMessage, end, pMessageHeader, config); - else - return -1; - break; + break; - case NFAPI_HARQ_INDICATION: - if (check_nr_unpack_length(NFAPI_HARQ_INDICATION, unpackedBufLen)) - result = unpack_harq_indication(&pReadPackedMessage, end, pMessageHeader, config); - else - return -1; - break; + case NFAPI_NR_PHY_MSG_TYPE_UL_TTI_REQUEST: + if (check_nr_unpack_length(NFAPI_NR_PHY_MSG_TYPE_UL_TTI_REQUEST, unpackedBufLen)) + result = unpack_ul_tti_request(&pReadPackedMessage, end, pMessageHeader, config); + else + return -1; - case NFAPI_CRC_INDICATION: - if (check_nr_unpack_length(NFAPI_CRC_INDICATION, unpackedBufLen)) - result = unpack_crc_indication(&pReadPackedMessage,end , pMessageHeader, config); - else - return -1; - break; + break; - case NFAPI_RX_ULSCH_INDICATION: - if (check_nr_unpack_length(NFAPI_RX_ULSCH_INDICATION, unpackedBufLen)) - result = unpack_rx_indication(&pReadPackedMessage, end, pMessageHeader, config); - else - return -1; - break; + case NFAPI_NR_PHY_MSG_TYPE_TX_DATA_REQUEST: + if (check_nr_unpack_length(NFAPI_NR_PHY_MSG_TYPE_TX_DATA_REQUEST, unpackedBufLen)) + result = unpack_tx_data_request(&pReadPackedMessage, end, pMessageHeader, config); + else + return -1; - case NFAPI_RACH_INDICATION: - if (check_nr_unpack_length(NFAPI_RACH_INDICATION, unpackedBufLen)) - result = unpack_rach_indication(&pReadPackedMessage, end, pMessageHeader, config); - else - return -1; - break; + break; - case NFAPI_SRS_INDICATION: - if (check_nr_unpack_length(NFAPI_SRS_INDICATION, unpackedBufLen)) - result = unpack_srs_indication(&pReadPackedMessage, end, pMessageHeader, config); - else - return -1; - break; + case NFAPI_NR_PHY_MSG_TYPE_UL_DCI_REQUEST: + if (check_nr_unpack_length(NFAPI_NR_PHY_MSG_TYPE_UL_DCI_REQUEST, unpackedBufLen)) + result = unpack_ul_dci_request(&pReadPackedMessage, end, pMessageHeader, config); + else + return -1; - case NFAPI_RX_SR_INDICATION: - if (check_nr_unpack_length(NFAPI_RX_SR_INDICATION, unpackedBufLen)) - result = unpack_sr_indication(&pReadPackedMessage, end, pMessageHeader, config); - else - return -1; - break; + break; - case NFAPI_RX_CQI_INDICATION: - if (check_nr_unpack_length(NFAPI_RX_CQI_INDICATION, unpackedBufLen)) - result = unpack_cqi_indication(&pReadPackedMessage, end, pMessageHeader, config); - else - return -1; - break; + case NFAPI_UE_RELEASE_REQUEST: + if (check_nr_unpack_length(NFAPI_UE_RELEASE_REQUEST, unpackedBufLen)) + result = unpack_ue_release_request(&pReadPackedMessage, end, pMessageHeader, config); + else + return -1; - case NFAPI_LBT_DL_CONFIG_REQUEST: - if (check_nr_unpack_length(NFAPI_LBT_DL_CONFIG_REQUEST, unpackedBufLen)) - result = unpack_lbt_dl_config_request(&pReadPackedMessage, end, pMessageHeader, config); - else - return -1; - break; + break; - case NFAPI_LBT_DL_INDICATION: - if (check_nr_unpack_length(NFAPI_LBT_DL_INDICATION, unpackedBufLen)) - result = unpack_lbt_dl_indication(&pReadPackedMessage, end, pMessageHeader, config); - else - return -1; - break; - - case NFAPI_NB_HARQ_INDICATION: - if (check_nr_unpack_length(NFAPI_NB_HARQ_INDICATION, unpackedBufLen)) - result = unpack_nb_harq_indication(&pReadPackedMessage, end, pMessageHeader, config); - else - return -1; - break; - - case NFAPI_NRACH_INDICATION: - if (check_nr_unpack_length(NFAPI_NRACH_INDICATION, unpackedBufLen)) - result = unpack_nrach_indication(&pReadPackedMessage, end, pMessageHeader, config); - else - return -1; - break; - - case NFAPI_NR_PHY_MSG_TYPE_DL_NODE_SYNC: - if (check_nr_unpack_length(NFAPI_NR_PHY_MSG_TYPE_DL_NODE_SYNC, unpackedBufLen)) - result = unpack_nr_dl_node_sync(&pReadPackedMessage, end, pMessageHeader, config); - else - return -1; - break; + case NFAPI_HARQ_INDICATION: + if (check_nr_unpack_length(NFAPI_HARQ_INDICATION, unpackedBufLen)) + result = unpack_harq_indication(&pReadPackedMessage, end, pMessageHeader, config); + else + return -1; - case NFAPI_NR_PHY_MSG_TYPE_UL_NODE_SYNC: - if (check_nr_unpack_length(NFAPI_NR_PHY_MSG_TYPE_UL_NODE_SYNC, unpackedBufLen)) - result = unpack_nr_ul_node_sync(&pReadPackedMessage, end , pMessageHeader, config); - else - return -1; - break; + break; - case NFAPI_TIMING_INFO: - if (check_nr_unpack_length(NFAPI_TIMING_INFO, unpackedBufLen)) - result = unpack_nr_timing_info(&pReadPackedMessage, end, pMessageHeader, config); - else - return -1; - break; + case NFAPI_CRC_INDICATION: + if (check_nr_unpack_length(NFAPI_CRC_INDICATION, unpackedBufLen)) + result = unpack_crc_indication(&pReadPackedMessage,end, pMessageHeader, config); + else + return -1; - case NFAPI_UE_RELEASE_RESPONSE: - if (check_nr_unpack_length(NFAPI_UE_RELEASE_RESPONSE, unpackedBufLen)) - result = unpack_ue_release_resp(&pReadPackedMessage, end, pMessageHeader, config); - else - return -1; - break; + break; - default: + case NFAPI_RX_ULSCH_INDICATION: + if (check_nr_unpack_length(NFAPI_RX_ULSCH_INDICATION, unpackedBufLen)) + result = unpack_rx_indication(&pReadPackedMessage, end, pMessageHeader, config); + else + return -1; - if(pMessageHeader->message_id >= NFAPI_VENDOR_EXT_MSG_MIN && - pMessageHeader->message_id <= NFAPI_VENDOR_EXT_MSG_MAX) - { - if(config && config->unpack_p7_vendor_extension) - { - result = (config->unpack_p7_vendor_extension)(pMessageHeader, &pReadPackedMessage, end, config); - } - else - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s VE NFAPI message ID %d. No ve decoder provided\n", __FUNCTION__, pMessageHeader->message_id); - } - } - else - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s NFAPI Unknown message ID %d\n", __FUNCTION__, pMessageHeader->message_id); - } - break; - } + break; - if(result == 0) - return -1; - else - return 0; + case NFAPI_RACH_INDICATION: + if (check_nr_unpack_length(NFAPI_RACH_INDICATION, unpackedBufLen)) + result = unpack_rach_indication(&pReadPackedMessage, end, pMessageHeader, config); + else + return -1; + + break; + + case NFAPI_SRS_INDICATION: + if (check_nr_unpack_length(NFAPI_SRS_INDICATION, unpackedBufLen)) + result = unpack_srs_indication(&pReadPackedMessage, end, pMessageHeader, config); + else + return -1; + + break; + + case NFAPI_RX_SR_INDICATION: + if (check_nr_unpack_length(NFAPI_RX_SR_INDICATION, unpackedBufLen)) + result = unpack_sr_indication(&pReadPackedMessage, end, pMessageHeader, config); + else + return -1; + + break; + + case NFAPI_RX_CQI_INDICATION: + if (check_nr_unpack_length(NFAPI_RX_CQI_INDICATION, unpackedBufLen)) + result = unpack_cqi_indication(&pReadPackedMessage, end, pMessageHeader, config); + else + return -1; + + break; + + case NFAPI_LBT_DL_CONFIG_REQUEST: + if (check_nr_unpack_length(NFAPI_LBT_DL_CONFIG_REQUEST, unpackedBufLen)) + result = unpack_lbt_dl_config_request(&pReadPackedMessage, end, pMessageHeader, config); + else + return -1; + + break; + + case NFAPI_LBT_DL_INDICATION: + if (check_nr_unpack_length(NFAPI_LBT_DL_INDICATION, unpackedBufLen)) + result = unpack_lbt_dl_indication(&pReadPackedMessage, end, pMessageHeader, config); + else + return -1; + + break; + + case NFAPI_NB_HARQ_INDICATION: + if (check_nr_unpack_length(NFAPI_NB_HARQ_INDICATION, unpackedBufLen)) + result = unpack_nb_harq_indication(&pReadPackedMessage, end, pMessageHeader, config); + else + return -1; + + break; + + case NFAPI_NRACH_INDICATION: + if (check_nr_unpack_length(NFAPI_NRACH_INDICATION, unpackedBufLen)) + result = unpack_nrach_indication(&pReadPackedMessage, end, pMessageHeader, config); + else + return -1; + + break; + + case NFAPI_NR_PHY_MSG_TYPE_DL_NODE_SYNC: + if (check_nr_unpack_length(NFAPI_NR_PHY_MSG_TYPE_DL_NODE_SYNC, unpackedBufLen)) + result = unpack_nr_dl_node_sync(&pReadPackedMessage, end, pMessageHeader, config); + else + return -1; + + break; + + case NFAPI_NR_PHY_MSG_TYPE_UL_NODE_SYNC: + if (check_nr_unpack_length(NFAPI_NR_PHY_MSG_TYPE_UL_NODE_SYNC, unpackedBufLen)) + result = unpack_nr_ul_node_sync(&pReadPackedMessage, end, pMessageHeader, config); + else + return -1; + + break; + + case NFAPI_TIMING_INFO: + if (check_nr_unpack_length(NFAPI_TIMING_INFO, unpackedBufLen)) + result = unpack_nr_timing_info(&pReadPackedMessage, end, pMessageHeader, config); + else + return -1; + + break; + + case NFAPI_UE_RELEASE_RESPONSE: + if (check_nr_unpack_length(NFAPI_UE_RELEASE_RESPONSE, unpackedBufLen)) + result = unpack_ue_release_resp(&pReadPackedMessage, end, pMessageHeader, config); + else + return -1; + + break; + + default: + if(pMessageHeader->message_id >= NFAPI_VENDOR_EXT_MSG_MIN && + pMessageHeader->message_id <= NFAPI_VENDOR_EXT_MSG_MAX) { + if(config && config->unpack_p7_vendor_extension) { + result = (config->unpack_p7_vendor_extension)(pMessageHeader, &pReadPackedMessage, end, config); + } else { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s VE NFAPI message ID %d. No ve decoder provided\n", __FUNCTION__, pMessageHeader->message_id); + } + } else { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s NFAPI Unknown message ID %d\n", __FUNCTION__, pMessageHeader->message_id); + } + + break; + } + + if(result == 0) + return -1; + else + return 0; } diff --git a/openair1/PHY/CODING/3gpplte_sse.c b/openair1/PHY/CODING/3gpplte_sse.c index fffd04ea3c..393b0f4a5d 100644 --- a/openair1/PHY/CODING/3gpplte_sse.c +++ b/openair1/PHY/CODING/3gpplte_sse.c @@ -373,10 +373,10 @@ char interleave_compact_byte(short *base_interleaver,unsigned char *input, unsig short *ptr_intl=base_interleaver; #if defined(__x86_64) || defined(__i386__) #ifndef __AVX2__ - __m128i tmp; + __m128i tmp={0}; uint16_t *systematic2_ptr=(uint16_t *) output; #else - __m256i tmp; + __m256i tmp={0}; uint32_t *systematic2_ptr=(uint32_t *) output; #endif #elif defined(__arm__) diff --git a/openair1/PHY/CODING/3gpplte_turbo_decoder_sse_16bit.c b/openair1/PHY/CODING/3gpplte_turbo_decoder_sse_16bit.c index 50fae438b7..c9d2579314 100644 --- a/openair1/PHY/CODING/3gpplte_turbo_decoder_sse_16bit.c +++ b/openair1/PHY/CODING/3gpplte_turbo_decoder_sse_16bit.c @@ -1105,7 +1105,7 @@ uint8_t phy_threegpplte_turbo_decoder16(int16_t *y, uint8_t temp; #if defined(__x86_64__) || defined(__i386__) __m128i *yp128; - __m128i tmp, zeros=_mm_setzero_si128(); + __m128i tmp={0}, zeros=_mm_setzero_si128(); __m128i tmpe; #elif defined(__arm__) int16x8_t *yp128; diff --git a/openair1/PHY/CODING/3gpplte_turbo_decoder_sse_8bit.c b/openair1/PHY/CODING/3gpplte_turbo_decoder_sse_8bit.c index bc1c0dac56..264b25deca 100644 --- a/openair1/PHY/CODING/3gpplte_turbo_decoder_sse_8bit.c +++ b/openair1/PHY/CODING/3gpplte_turbo_decoder_sse_8bit.c @@ -819,7 +819,7 @@ uint8_t phy_threegpplte_turbo_decoder8(int16_t *y, #if defined(__x86_64__) || defined(__i386__) __m128i *yp128; __m128i tmp128[(n+8)>>3]; - __m128i tmp, zeros=_mm_setzero_si128(); + __m128i tmp={0}, zeros=_mm_setzero_si128(); #elif defined(__arm__) int8x16_t *yp128; int8x16_t tmp128[(n+8)>>3]; diff --git a/openair1/PHY/LTE_ESTIMATION/lte_ul_channel_estimation.c b/openair1/PHY/LTE_ESTIMATION/lte_ul_channel_estimation.c index 0ce716ef20..c867292942 100644 --- a/openair1/PHY/LTE_ESTIMATION/lte_ul_channel_estimation.c +++ b/openair1/PHY/LTE_ESTIMATION/lte_ul_channel_estimation.c @@ -35,7 +35,6 @@ static int16_t ru_90c[2*128] = {32767, 0,32766, -402,32758, -804,32746, -1206,32 #define SCALE 0x3FFF static const short conjugate[8]__attribute__((aligned(16))) = {-1,1,-1,1,-1,1,-1,1}; -//static const short conjugate2[8]__attribute__((aligned(16))) = {1,-1,1,-1,1,-1,1,-1}; extern unsigned short dftsizes[34]; extern int16_t *ul_ref_sigs_rx[30][2][34]; diff --git a/openair1/PHY/LTE_UE_TRANSPORT/dlsch_demodulation.c b/openair1/PHY/LTE_UE_TRANSPORT/dlsch_demodulation.c index 556a9f2d23..d793536b93 100644 --- a/openair1/PHY/LTE_UE_TRANSPORT/dlsch_demodulation.c +++ b/openair1/PHY/LTE_UE_TRANSPORT/dlsch_demodulation.c @@ -1234,7 +1234,7 @@ void dlsch_channel_compensation(int **rxdataF_ext, unsigned short rb; unsigned char aatx,aarx,symbol_mod,pilots=0; __m128i *dl_ch128,*dl_ch128_2,*dl_ch_mag128,*dl_ch_mag128b,*rxdataF128,*rxdataF_comp128,*rho128; - __m128i mmtmpD0,mmtmpD1,mmtmpD2,mmtmpD3,QAM_amp128; + __m128i mmtmpD0,mmtmpD1,mmtmpD2,mmtmpD3,QAM_amp128={0}; symbol_mod = (symbol>=(7-frame_parms->Ncp)) ? symbol-(7-frame_parms->Ncp) : symbol; if ((symbol_mod == 0) || (symbol_mod == (4-frame_parms->Ncp))) { @@ -1657,11 +1657,11 @@ void dlsch_channel_compensation_core(int **rxdataF_ext, int length_mod8 = 0; int length2; __m128i *dl_ch128,*dl_ch_mag128,*dl_ch_mag128b, *dl_ch128_2, *rxdataF128,*rxdataF_comp128,*rho128; - __m128i mmtmpD0,mmtmpD1,mmtmpD2,mmtmpD3,QAM_amp128; + __m128i mmtmpD0,mmtmpD1,mmtmpD2,mmtmpD3,QAM_amp128={0}; int aatx = 0, aarx = 0; for (aatx=0; aatxrxdataF_comp0; int **rxdataF_comp1 = pdsch_vars->rxdataF_comp1[harq_pid][round]; unsigned char *pmi_ext = pdsch_vars->pmi_ext; - __m128i mmtmpD0,mmtmpD1,mmtmpD2,mmtmpD3,QAM_amp0_128,QAM_amp1_128; + __m128i mmtmpD0,mmtmpD1,mmtmpD2,mmtmpD3,QAM_amp0_128={0},QAM_amp1_128={0}; symbol_mod = (symbol>=(7-frame_parms->Ncp)) ? symbol-(7-frame_parms->Ncp) : symbol; if ((symbol_mod == 0) || (symbol_mod == (4-frame_parms->Ncp))) diff --git a/openair1/PHY/LTE_UE_TRANSPORT/pmch_ue.c b/openair1/PHY/LTE_UE_TRANSPORT/pmch_ue.c index 69aa1c06a3..3c22c64a9e 100644 --- a/openair1/PHY/LTE_UE_TRANSPORT/pmch_ue.c +++ b/openair1/PHY/LTE_UE_TRANSPORT/pmch_ue.c @@ -328,7 +328,7 @@ void mch_channel_compensation(int **rxdataF_ext, int aarx,nre,i; #if defined(__x86_64__) || defined(__i386__) __m128i *dl_ch128,*dl_ch_mag128,*dl_ch_mag128b,*rxdataF128,*rxdataF_comp128; - __m128i mmtmpD0,mmtmpD1,mmtmpD2,mmtmpD3,QAM_amp128,QAM_amp128b; + __m128i mmtmpD0,mmtmpD1,mmtmpD2,mmtmpD3,QAM_amp128={0},QAM_amp128b={0}; #elif defined(__arm__) #endif @@ -455,7 +455,7 @@ void mch_channel_compensation_khz_1dot25(int **rxdataF_ext, int aarx,nre,i; #if defined(__x86_64__) || defined(__i386__) __m128i *dl_ch128,*dl_ch_mag128,*dl_ch_mag128b,*rxdataF128,*rxdataF_comp128; - __m128i mmtmpD0,mmtmpD1,mmtmpD2,mmtmpD3,QAM_amp128,QAM_amp128b; + __m128i mmtmpD0,mmtmpD1,mmtmpD2,mmtmpD3,QAM_amp128={0},QAM_amp128b={0}; #elif defined(__arm__) #endif /*if ((symbol == 2) || (symbol == 6) || (symbol == 10)) diff --git a/openair1/PHY/LTE_UE_TRANSPORT/ulsch_coding.c b/openair1/PHY/LTE_UE_TRANSPORT/ulsch_coding.c index de1c3891da..ae3ebbce9d 100644 --- a/openair1/PHY/LTE_UE_TRANSPORT/ulsch_coding.c +++ b/openair1/PHY/LTE_UE_TRANSPORT/ulsch_coding.c @@ -52,8 +52,7 @@ -void free_ue_ulsch(LTE_UE_ULSCH_t *ulsch) -{ +void free_ue_ulsch(LTE_UE_ULSCH_t *ulsch) { int i; int r; @@ -68,6 +67,7 @@ void free_ue_ulsch(LTE_UE_ULSCH_t *ulsch) free16(ulsch->harq_processes[i]->b,MAX_ULSCH_PAYLOAD_BYTES); ulsch->harq_processes[i]->b = NULL; } + for (r=0; rharq_processes[i]->c[r]) { free16(ulsch->harq_processes[i]->c[r],((r==0)?8:0) + 3+768); @@ -79,51 +79,47 @@ void free_ue_ulsch(LTE_UE_ULSCH_t *ulsch) ulsch->harq_processes[i] = NULL; } } + free16(ulsch,sizeof(LTE_UE_ULSCH_t)); } - } -LTE_UE_ULSCH_t *new_ue_ulsch(unsigned char N_RB_UL, uint8_t abstraction_flag) -{ - +LTE_UE_ULSCH_t *new_ue_ulsch(unsigned char N_RB_UL, uint8_t abstraction_flag) { LTE_UE_ULSCH_t *ulsch; unsigned char exit_flag = 0,i,j,r; unsigned char bw_scaling =1; switch (N_RB_UL) { - case 6: - bw_scaling =16; - break; + case 6: + bw_scaling =16; + break; - case 25: - bw_scaling =4; - break; + case 25: + bw_scaling =4; + break; - case 50: - bw_scaling =2; - break; - - default: - bw_scaling =1; - break; + case 50: + bw_scaling =2; + break; + + default: + bw_scaling =1; + break; } ulsch = (LTE_UE_ULSCH_t *)malloc16(sizeof(LTE_UE_ULSCH_t)); if (ulsch) { memset(ulsch,0,sizeof(LTE_UE_ULSCH_t)); - ulsch->Mlimit = 4; for (i=0; i<8; i++) { - ulsch->harq_processes[i] = (LTE_UL_UE_HARQ_t *)malloc16(sizeof(LTE_UL_UE_HARQ_t)); // printf("ulsch->harq_processes[%d] %p\n",i,ulsch->harq_processes[i]); if (ulsch->harq_processes[i]) { memset(ulsch->harq_processes[i], 0, sizeof(LTE_UL_UE_HARQ_t)); - ulsch->harq_processes[i]->b = (unsigned char*)malloc16(MAX_ULSCH_PAYLOAD_BYTES/bw_scaling); + ulsch->harq_processes[i]->b = (unsigned char *)malloc16(MAX_ULSCH_PAYLOAD_BYTES/bw_scaling); if (ulsch->harq_processes[i]->b) memset(ulsch->harq_processes[i]->b,0,MAX_ULSCH_PAYLOAD_BYTES/bw_scaling); @@ -134,7 +130,7 @@ LTE_UE_ULSCH_t *new_ue_ulsch(unsigned char N_RB_UL, uint8_t abstraction_flag) if (abstraction_flag==0) { for (r=0; rharq_processes[i]->c[r] = (unsigned char*)malloc16(((r==0)?8:0) + 3+768); // account for filler in first segment and CRCs for multiple segment case + ulsch->harq_processes[i]->c[r] = (unsigned char *)malloc16(((r==0)?8:0) + 3+768); // account for filler in first segment and CRCs for multiple segment case if (ulsch->harq_processes[i]->c[r]) memset(ulsch->harq_processes[i]->c[r],0,((r==0)?8:0) + 3+768); @@ -167,8 +163,6 @@ LTE_UE_ULSCH_t *new_ue_ulsch(unsigned char N_RB_UL, uint8_t abstraction_flag) LOG_E(PHY,"new_ue_ulsch exit flag, size of %d , %zu\n",exit_flag, sizeof(LTE_UE_ULSCH_t)); free_ue_ulsch(ulsch); return(NULL); - - } @@ -179,15 +173,12 @@ uint32_t ulsch_encoding(uint8_t *a, uint8_t subframe_rx, uint8_t tmode, uint8_t control_only_flag, - uint8_t Nbundled) -{ - + uint8_t Nbundled) { time_stats_t *seg_stats=&ue->ulsch_segmentation_stats; time_stats_t *rm_stats=&ue->ulsch_rate_matching_stats; time_stats_t *te_stats=&ue->ulsch_turbo_encoding_stats; time_stats_t *i_stats=&ue->ulsch_interleaving_stats; time_stats_t *m_stats=&ue->ulsch_multiplexing_stats; - // uint16_t offset; uint32_t crc=1; uint32_t A; @@ -237,7 +228,6 @@ uint32_t ulsch_encoding(uint8_t *a, VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_ULSCH_ENCODING_FILL_CQI, VCD_FUNCTION_IN); rnti = ue->pdcch_vars[ue->current_thread_id[subframe_rx]][eNB_id]->crnti; fill_CQI(ulsch,meas,0,harq_pid,ue->frame_parms.N_RB_DL,rnti, tmode,ue->sinr_eff); - LOG_D(PHY,"ULSCH Encoding rnti %x \n", rnti); print_CQI(ulsch->o,ulsch->uci_format,0,ue->frame_parms.N_RB_DL); @@ -246,6 +236,7 @@ uint32_t ulsch_encoding(uint8_t *a, //LOG_I(PHY,"XXX saving pmi for DL %x\n",pmi2hex_2Ar1(((wideband_cqi_rank1_2A_5MHz *)ulsch->o)->pmi)); dlsch[0]->pmi_alloc = ((wideband_cqi_rank1_2A_5MHz *)ulsch->o)->pmi; } + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_ULSCH_ENCODING_FILL_CQI, VCD_FUNCTION_OUT); } @@ -268,17 +259,15 @@ uint32_t ulsch_encoding(uint8_t *a, if (control_only_flag == 0) { A=ulsch->harq_processes[harq_pid]->TBS; Q_m = get_Qm_ul(ulsch->harq_processes[harq_pid]->mcs); - ulsch->harq_processes[harq_pid]->control_only = 0; - #ifdef DEBUG_ULSCH_CODING printf("[PHY][UE] ULSCH coding : A %d, Qm %d, mcs %d, harq_pid %d, round %d, RV %d\n", - ulsch->harq_processes[harq_pid]->TBS, - Q_m, - ulsch->harq_processes[harq_pid]->mcs, - harq_pid, - ulsch->harq_processes[harq_pid]->round, - ulsch->harq_processes[harq_pid]->rvidx); + ulsch->harq_processes[harq_pid]->TBS, + Q_m, + ulsch->harq_processes[harq_pid]->mcs, + harq_pid, + ulsch->harq_processes[harq_pid]->round, + ulsch->harq_processes[harq_pid]->rvidx); for (i=0; iharq_processes[harq_pid]->O_ACK; i++) printf("ulsch_coding: o_ACK[%d] %d\n",i,ulsch->o_ACK[i]); @@ -301,16 +290,13 @@ uint32_t ulsch_encoding(uint8_t *a, #endif if (ulsch->harq_processes[harq_pid]->round == 0) { // this is a new packet - start_meas(seg_stats); // Add 24-bit crc (polynomial A) to payload crc = crc24a(a, A)>>8; - - a[A>>3] = ((uint8_t*)&crc)[2]; - a[1+(A>>3)] = ((uint8_t*)&crc)[1]; - a[2+(A>>3)] = ((uint8_t*)&crc)[0]; - + a[A>>3] = ((uint8_t *)&crc)[2]; + a[1+(A>>3)] = ((uint8_t *)&crc)[1]; + a[2+(A>>3)] = ((uint8_t *)&crc)[0]; ulsch->harq_processes[harq_pid]->B = A+24; ulsch->harq_processes[harq_pid]->b = a; lte_segmentation(ulsch->harq_processes[harq_pid]->b, @@ -322,7 +308,6 @@ uint32_t ulsch_encoding(uint8_t *a, &ulsch->harq_processes[harq_pid]->Kplus, &ulsch->harq_processes[harq_pid]->Kminus, &ulsch->harq_processes[harq_pid]->F); - stop_meas(seg_stats); for (r=0; rharq_processes[harq_pid]->C; r++) { @@ -332,25 +317,20 @@ uint32_t ulsch_encoding(uint8_t *a, Kr = ulsch->harq_processes[harq_pid]->Kplus; Kr_bytes = Kr>>3; - #ifdef DEBUG_ULSCH_CODING printf("Generating Code Segment %d (%d bits)\n",r,Kr); // generate codewords - printf("bits_per_codeword (Kr)= %d\n",Kr); printf("N_RB = %d\n",ulsch->harq_processes[harq_pid]->nb_rb); printf("Ncp %d\n",frame_parms->Ncp); printf("Qm %d\n",Q_m); #endif - // offset=0; - - start_meas(te_stats); encoder(ulsch->harq_processes[harq_pid]->c[r], - Kr>>3, - &ulsch->harq_processes[harq_pid]->d[r][96], - (r==0) ? ulsch->harq_processes[harq_pid]->F : 0 + Kr>>3, + &ulsch->harq_processes[harq_pid]->d[r][96], + (r==0) ? ulsch->harq_processes[harq_pid]->F : 0 ); stop_meas(te_stats); #ifdef DEBUG_ULSCH_CODING @@ -366,7 +346,6 @@ uint32_t ulsch_encoding(uint8_t *a, ulsch->harq_processes[harq_pid]->w[r]); stop_meas(i_stats); } - } if (ulsch->harq_processes[harq_pid]->C == 0) { @@ -392,7 +371,6 @@ uint32_t ulsch_encoding(uint8_t *a, ulsch->harq_processes[harq_pid]->sumKr = sumKr; // Compute Q_ri (p. 23 36-212) - Qprime = ulsch->O_RI*ulsch->harq_processes[harq_pid]->Msc_initial*ulsch->harq_processes[harq_pid]->Nsymb_initial * ulsch->beta_offset_ri_times8; if (Qprime > 0) { @@ -407,7 +385,6 @@ uint32_t ulsch_encoding(uint8_t *a, Q_RI = Q_m*Qprime; Qprime_RI = Qprime; - // Compute Q_ack (p. 23 36-212) Qprime = ulsch->harq_processes[harq_pid]->O_ACK*ulsch->harq_processes[harq_pid]->Msc_initial*ulsch->harq_processes[harq_pid]->Nsymb_initial * ulsch->beta_offset_harqack_times8; @@ -423,20 +400,18 @@ uint32_t ulsch_encoding(uint8_t *a, Q_ACK = Qprime * Q_m; Qprime_ACK = Qprime; - LOG_D(PHY,"UE (%x/%d) O_ACK %d, Mcs_initial %d, Nsymb_initial %d, beta_offset_harqack*8 %d, sum Kr %d, Qprime_ACK %d, Q_ACK %d\n", - rnti, harq_pid, - ulsch->harq_processes[harq_pid]->O_ACK, - ulsch->harq_processes[harq_pid]->Msc_initial, - ulsch->harq_processes[harq_pid]->Nsymb_initial, - ulsch->beta_offset_harqack_times8, - sumKr, - Qprime_ACK, - Q_ACK); + rnti, harq_pid, + ulsch->harq_processes[harq_pid]->O_ACK, + ulsch->harq_processes[harq_pid]->Msc_initial, + ulsch->harq_processes[harq_pid]->Nsymb_initial, + ulsch->beta_offset_harqack_times8, + sumKr, + Qprime_ACK, + Q_ACK); // Compute Q_cqi, assume O>11, p. 26 36-212 if (control_only_flag == 0) { - if (ulsch->O < 12) L=0; else @@ -446,13 +421,13 @@ uint32_t ulsch_encoding(uint8_t *a, Qprime = (ulsch->O + L) * ulsch->harq_processes[harq_pid]->Msc_initial*ulsch->harq_processes[harq_pid]->Nsymb_initial * ulsch->beta_offset_cqi_times8; else Qprime = 0; - LOG_D(PHY,"Qprime %d, O_RI %d + %d, Msc %d, Nym %d beta %d\n", - Qprime, - ulsch->O, L, - ulsch->harq_processes[harq_pid]->Msc_initial, - ulsch->harq_processes[harq_pid]->Nsymb_initial, - ulsch->beta_offset_cqi_times8); + LOG_D(PHY,"Qprime %d, O_RI %d + %d, Msc %d, Nym %d beta %d\n", + Qprime, + ulsch->O, L, + ulsch->harq_processes[harq_pid]->Msc_initial, + ulsch->harq_processes[harq_pid]->Nsymb_initial, + ulsch->beta_offset_cqi_times8); if (Qprime > 0) { if ((Qprime % (8*sumKr)) > 0) @@ -463,31 +438,29 @@ uint32_t ulsch_encoding(uint8_t *a, G = ulsch->harq_processes[harq_pid]->nb_rb * (12 * Q_m) * (ulsch->Nsymb_pusch); LOG_D(PHY,"G: rb %d * ( 12 * Qm %d ) * nsymb %d, Qprime %d, O_RI %d\n", ulsch->harq_processes[harq_pid]->nb_rb, Q_m, ulsch->Nsymb_pusch, Qprime, ulsch->O_RI); + if (Qprime > (G - ulsch->O_RI)) Qprime = G - ulsch->O_RI; Q_CQI = Q_m * Qprime; Qprime_CQI = Qprime; - - - G = G - Q_RI - Q_CQI; - LOG_D(PHY,"new G: %d, Q_RI %d Q_CQI %d\n", G , Q_RI , Q_CQI); + LOG_D(PHY,"new G: %d, Q_RI %d Q_CQI %d\n", G, Q_RI, Q_CQI); ulsch->harq_processes[harq_pid]->G = G; -/* - LOG_I(PHY,"ULSCH Encoding G %d, Q_RI %d (O_RI%d, Msc_initial %d, Nsymb_initial%d, beta_offset_ri_times8 %d), Q_CQI %d, Q_ACK %d \n",G,Q_RI,ulsch->O_RI,ulsch->harq_processes[harq_pid]->Msc_initial,ulsch->harq_processes[harq_pid]->Nsymb_initial,ulsch->beta_offset_ri_times8,Q_CQI,Q_ACK); + /* + LOG_I(PHY,"ULSCH Encoding G %d, Q_RI %d (O_RI%d, Msc_initial %d, Nsymb_initial%d, beta_offset_ri_times8 %d), Q_CQI %d, Q_ACK %d \n",G,Q_RI,ulsch->O_RI,ulsch->harq_processes[harq_pid]->Msc_initial,ulsch->harq_processes[harq_pid]->Nsymb_initial,ulsch->beta_offset_ri_times8,Q_CQI,Q_ACK); - LOG_I(PHY,"ULSCH Encoding (Nid_cell %d, rnti %x): harq_pid %d round %d, RV %d, mcs %d, O_RI %d, O_ACK %d, G %d\n", - frame_parms->Nid_cell,ulsch->rnti, - harq_pid, - ulsch->harq_processes[harq_pid]->round, - ulsch->harq_processes[harq_pid]->rvidx, - ulsch->harq_processes[harq_pid]->mcs, - ulsch->O_RI, - ulsch->harq_processes[harq_pid]->O_ACK, - G); -*/ + LOG_I(PHY,"ULSCH Encoding (Nid_cell %d, rnti %x): harq_pid %d round %d, RV %d, mcs %d, O_RI %d, O_ACK %d, G %d\n", + frame_parms->Nid_cell,ulsch->rnti, + harq_pid, + ulsch->harq_processes[harq_pid]->round, + ulsch->harq_processes[harq_pid]->rvidx, + ulsch->harq_processes[harq_pid]->mcs, + ulsch->O_RI, + ulsch->harq_processes[harq_pid]->O_ACK, + G); + */ if ((int)G < 0) { LOG_E(PHY,"FATAL: ulsch_coding.c G < 0 (%d) : Q_RI %d, Q_CQI %d, O %d, betaCQI_times8 %d)\n",G,Q_RI,Q_CQI,ulsch->O,ulsch->beta_offset_cqi_times8); @@ -495,26 +468,21 @@ uint32_t ulsch_encoding(uint8_t *a, return(-1); } - // Data and control multiplexing (5.2.2.7 36-212) - H = G + Q_CQI; Hprime = H/Q_m; - - // Fill in the "e"-sequence from 36-212, V8.6 2009-03, p. 16-17 (for each "e") and concatenate the // outputs for each code segment, see Section 5.1.5 p.20 for (r=0; rharq_processes[harq_pid]->C; r++) { #ifdef DEBUG_ULSCH_CODING printf("Rate Matching, Code segment %d (coded bits (G) %d,unpunctured/repeated bits per code segment %d,mod_order %d, nb_rb %d)...\n", - r, - G, - Kr*3, - Q_m,ulsch->harq_processes[harq_pid]->nb_rb); + r, + G, + Kr*3, + Q_m,ulsch->harq_processes[harq_pid]->nb_rb); #endif - start_meas(rm_stats); r_offset += lte_rate_matching_turbo(ulsch->harq_processes[harq_pid]->RTC[r], G, @@ -529,7 +497,7 @@ uint32_t ulsch_encoding(uint8_t *a, 1, r, ulsch->harq_processes[harq_pid]->nb_rb); - //ulsch->harq_processes[harq_pid]->mcs); // r + //ulsch->harq_processes[harq_pid]->mcs); // r stop_meas(rm_stats); #ifdef DEBUG_ULSCH_CODING @@ -544,7 +512,6 @@ uint32_t ulsch_encoding(uint8_t *a, Hprime = H/Q_m; } - // Do CQI coding if ((ulsch->O>1) && (ulsch->O < 12)) { LOG_E(PHY,"short CQI sizes not supported yet\n"); @@ -558,23 +525,18 @@ uint32_t ulsch_encoding(uint8_t *a, printf("crc(cqi) tx : %x\n",crc); #endif memset((void *)&ulsch->o_d[0],LTE_NULL,96); - ccodelte_encode(ulsch->O, 1, o_flip, &ulsch->o_d[96], 0); - - o_RCC = sub_block_interleaving_cc(8+ulsch->O, &ulsch->o_d[96], ulsch->o_w); - lte_rate_matching_cc(o_RCC, Q_CQI, ulsch->o_w, ulsch->q); - } i=0; @@ -582,29 +544,29 @@ uint32_t ulsch_encoding(uint8_t *a, // Do RI coding if (ulsch->O_RI == 1) { switch (Q_m) { - case 2: - ulsch->q_RI[0] = ulsch->o_RI[0]; - ulsch->q_RI[1] = PUSCH_y;//ulsch->o_RI[0]; - len_RI=2; - break; + case 2: + ulsch->q_RI[0] = ulsch->o_RI[0]; + ulsch->q_RI[1] = PUSCH_y;//ulsch->o_RI[0]; + len_RI=2; + break; - case 4: - ulsch->q_RI[0] = ulsch->o_RI[0]; - ulsch->q_RI[1] = PUSCH_y;//1; - ulsch->q_RI[2] = PUSCH_x;//ulsch->o_RI[0]; - ulsch->q_RI[3] = PUSCH_x;//1; - len_RI=4; - break; + case 4: + ulsch->q_RI[0] = ulsch->o_RI[0]; + ulsch->q_RI[1] = PUSCH_y;//1; + ulsch->q_RI[2] = PUSCH_x;//ulsch->o_RI[0]; + ulsch->q_RI[3] = PUSCH_x;//1; + len_RI=4; + break; - case 6: - ulsch->q_RI[0] = ulsch->o_RI[0]; - ulsch->q_RI[1] = PUSCH_y;//1; - ulsch->q_RI[2] = PUSCH_x;//1; - ulsch->q_RI[3] = PUSCH_x;//ulsch->o_RI[0]; - ulsch->q_RI[4] = PUSCH_x;//1; - ulsch->q_RI[5] = PUSCH_x;//1; - len_RI=6; - break; + case 6: + ulsch->q_RI[0] = ulsch->o_RI[0]; + ulsch->q_RI[1] = PUSCH_y;//1; + ulsch->q_RI[2] = PUSCH_x;//1; + ulsch->q_RI[3] = PUSCH_x;//ulsch->o_RI[0]; + ulsch->q_RI[4] = PUSCH_x;//1; + ulsch->q_RI[5] = PUSCH_x;//1; + len_RI=6; + break; } } else if (ulsch->O_RI>1) { LOG_E(PHY,"RI cannot be more than 1 bit yet\n"); @@ -616,35 +578,35 @@ uint32_t ulsch_encoding(uint8_t *a, wACK_idx = (ulsch->bundling==0) ? 4 : ((Nbundled-1)&3); #ifdef DEBUG_ULSCH_CODING printf("ulsch_coding.c: Bundling %d, Nbundled %d, wACK_idx %d\n", - ulsch->bundling,Nbundled,wACK_idx); + ulsch->bundling,Nbundled,wACK_idx); #endif // 1-bit ACK/NAK if (ulsch->harq_processes[harq_pid]->O_ACK == 1) { switch (Q_m) { - case 2: - ulsch->q_ACK[0] = (ulsch->o_ACK[0]+wACK[wACK_idx][0])&1; - ulsch->q_ACK[1] = (ulsch->bundling==0)? PUSCH_y : ((ulsch->o_ACK[0]+wACK[wACK_idx][1])&1);//ulsch->o_ACK[0]; - len_ACK = 2; - break; + case 2: + ulsch->q_ACK[0] = (ulsch->o_ACK[0]+wACK[wACK_idx][0])&1; + ulsch->q_ACK[1] = (ulsch->bundling==0)? PUSCH_y : ((ulsch->o_ACK[0]+wACK[wACK_idx][1])&1);//ulsch->o_ACK[0]; + len_ACK = 2; + break; - case 4: - ulsch->q_ACK[0] = (ulsch->o_ACK[0]+wACK[wACK_idx][0])&1; - ulsch->q_ACK[1] = (ulsch->bundling==0)? PUSCH_y : ((ulsch->o_ACK[0]+wACK[wACK_idx][1])&1); - ulsch->q_ACK[2] = PUSCH_x; - ulsch->q_ACK[3] = PUSCH_x; - len_ACK = 4; - break; + case 4: + ulsch->q_ACK[0] = (ulsch->o_ACK[0]+wACK[wACK_idx][0])&1; + ulsch->q_ACK[1] = (ulsch->bundling==0)? PUSCH_y : ((ulsch->o_ACK[0]+wACK[wACK_idx][1])&1); + ulsch->q_ACK[2] = PUSCH_x; + ulsch->q_ACK[3] = PUSCH_x; + len_ACK = 4; + break; - case 6: - ulsch->q_ACK[0] = (ulsch->o_ACK[0]+wACK[wACK_idx][0])&1; - ulsch->q_ACK[1] = (ulsch->bundling==0)? PUSCH_y : ((ulsch->o_ACK[0]+wACK[wACK_idx][1])&1); - ulsch->q_ACK[2] = PUSCH_x; - ulsch->q_ACK[3] = PUSCH_x; - ulsch->q_ACK[4] = PUSCH_x; - ulsch->q_ACK[6] = PUSCH_x; - len_ACK = 6; - break; + case 6: + ulsch->q_ACK[0] = (ulsch->o_ACK[0]+wACK[wACK_idx][0])&1; + ulsch->q_ACK[1] = (ulsch->bundling==0)? PUSCH_y : ((ulsch->o_ACK[0]+wACK[wACK_idx][1])&1); + ulsch->q_ACK[2] = PUSCH_x; + ulsch->q_ACK[3] = PUSCH_x; + ulsch->q_ACK[4] = PUSCH_x; + ulsch->q_ACK[6] = PUSCH_x; + len_ACK = 6; + break; } } @@ -653,56 +615,53 @@ uint32_t ulsch_encoding(uint8_t *a, ack_parity = (ulsch->o_ACK[0]+ulsch->o_ACK[1])&1; switch (Q_m) { - case 2: - ulsch->q_ACK[0] = (ulsch->o_ACK[0]+wACK[wACK_idx][0])&1; - ulsch->q_ACK[1] = (ulsch->o_ACK[1]+wACK[wACK_idx][0])&1; - ulsch->q_ACK[2] = (ack_parity+wACK[wACK_idx][0])&1; - ulsch->q_ACK[3] = (ulsch->o_ACK[0]+wACK[wACK_idx][1])&1; - ulsch->q_ACK[4] = (ulsch->o_ACK[1]+wACK[wACK_idx][1])&1; - ulsch->q_ACK[5] = (ack_parity+wACK[wACK_idx][1])&1; - len_ACK = 6; - break; + case 2: + ulsch->q_ACK[0] = (ulsch->o_ACK[0]+wACK[wACK_idx][0])&1; + ulsch->q_ACK[1] = (ulsch->o_ACK[1]+wACK[wACK_idx][0])&1; + ulsch->q_ACK[2] = (ack_parity+wACK[wACK_idx][0])&1; + ulsch->q_ACK[3] = (ulsch->o_ACK[0]+wACK[wACK_idx][1])&1; + ulsch->q_ACK[4] = (ulsch->o_ACK[1]+wACK[wACK_idx][1])&1; + ulsch->q_ACK[5] = (ack_parity+wACK[wACK_idx][1])&1; + len_ACK = 6; + break; - case 4: - ulsch->q_ACK[0] = (ulsch->o_ACK[0]+wACK[wACK_idx][0])&1; - ulsch->q_ACK[1] = (ulsch->o_ACK[1]+wACK[wACK_idx][0])&1; - ulsch->q_ACK[2] = PUSCH_x; - ulsch->q_ACK[3] = PUSCH_x;//1; - ulsch->q_ACK[4] = (ack_parity+wACK[wACK_idx][0])&1; - ulsch->q_ACK[5] = (ulsch->o_ACK[0]+wACK[wACK_idx][1])&1; - ulsch->q_ACK[6] = PUSCH_x; - ulsch->q_ACK[7] = PUSCH_x;//1; - ulsch->q_ACK[8] = (ulsch->o_ACK[1]+wACK[wACK_idx][1])&1; - ulsch->q_ACK[9] = (ack_parity+wACK[wACK_idx][1])&1; - ulsch->q_ACK[10] = PUSCH_x; - ulsch->q_ACK[11] = PUSCH_x;//1; - len_ACK = 12; - break; + case 4: + ulsch->q_ACK[0] = (ulsch->o_ACK[0]+wACK[wACK_idx][0])&1; + ulsch->q_ACK[1] = (ulsch->o_ACK[1]+wACK[wACK_idx][0])&1; + ulsch->q_ACK[2] = PUSCH_x; + ulsch->q_ACK[3] = PUSCH_x;//1; + ulsch->q_ACK[4] = (ack_parity+wACK[wACK_idx][0])&1; + ulsch->q_ACK[5] = (ulsch->o_ACK[0]+wACK[wACK_idx][1])&1; + ulsch->q_ACK[6] = PUSCH_x; + ulsch->q_ACK[7] = PUSCH_x;//1; + ulsch->q_ACK[8] = (ulsch->o_ACK[1]+wACK[wACK_idx][1])&1; + ulsch->q_ACK[9] = (ack_parity+wACK[wACK_idx][1])&1; + ulsch->q_ACK[10] = PUSCH_x; + ulsch->q_ACK[11] = PUSCH_x;//1; + len_ACK = 12; + break; - case 6: - ulsch->q_ACK[0] = (ulsch->o_ACK[0]+wACK[wACK_idx][0])&1; - ulsch->q_ACK[1] = (ulsch->o_ACK[1]+wACK[wACK_idx][0])&1; - ulsch->q_ACK[2] = PUSCH_x; - ulsch->q_ACK[3] = PUSCH_x; - ulsch->q_ACK[4] = PUSCH_x; - ulsch->q_ACK[5] = PUSCH_x; - - ulsch->q_ACK[6] = (ack_parity+wACK[wACK_idx][0])&1; - ulsch->q_ACK[7] = (ulsch->o_ACK[0]+wACK[wACK_idx][1])&1; - ulsch->q_ACK[8] = PUSCH_x; - ulsch->q_ACK[9] = PUSCH_x; - ulsch->q_ACK[10] = PUSCH_x; - ulsch->q_ACK[11] = PUSCH_x; - - ulsch->q_ACK[12] = (ulsch->o_ACK[1]+wACK[wACK_idx][1])&1; - ulsch->q_ACK[13] = (ack_parity+wACK[wACK_idx][1])&1; - ulsch->q_ACK[14] = PUSCH_x; - ulsch->q_ACK[15] = PUSCH_x; - ulsch->q_ACK[16] = PUSCH_x; - ulsch->q_ACK[17] = PUSCH_x; - len_ACK = 18; - - break; + case 6: + ulsch->q_ACK[0] = (ulsch->o_ACK[0]+wACK[wACK_idx][0])&1; + ulsch->q_ACK[1] = (ulsch->o_ACK[1]+wACK[wACK_idx][0])&1; + ulsch->q_ACK[2] = PUSCH_x; + ulsch->q_ACK[3] = PUSCH_x; + ulsch->q_ACK[4] = PUSCH_x; + ulsch->q_ACK[5] = PUSCH_x; + ulsch->q_ACK[6] = (ack_parity+wACK[wACK_idx][0])&1; + ulsch->q_ACK[7] = (ulsch->o_ACK[0]+wACK[wACK_idx][1])&1; + ulsch->q_ACK[8] = PUSCH_x; + ulsch->q_ACK[9] = PUSCH_x; + ulsch->q_ACK[10] = PUSCH_x; + ulsch->q_ACK[11] = PUSCH_x; + ulsch->q_ACK[12] = (ulsch->o_ACK[1]+wACK[wACK_idx][1])&1; + ulsch->q_ACK[13] = (ack_parity+wACK[wACK_idx][1])&1; + ulsch->q_ACK[14] = PUSCH_x; + ulsch->q_ACK[15] = PUSCH_x; + ulsch->q_ACK[16] = PUSCH_x; + ulsch->q_ACK[17] = PUSCH_x; + len_ACK = 18; + break; } } @@ -712,23 +671,17 @@ uint32_t ulsch_encoding(uint8_t *a, return(-1); } - // channel multiplexing/interleaving - start_meas(m_stats); Hpp = Hprime + Q_RI; - Cmux = ulsch->Nsymb_pusch; Rmux = Hpp*Q_m/Cmux; Rmux_prime = Rmux/Q_m; - Qprime_RI = Q_RI / Q_m; Qprime_ACK = Q_ACK / Q_m; Qprime_CQI = Q_CQI / Q_m; - // printf("Qprime_CQI = %d\n",Qprime_CQI); // RI BITS - memset(y,LTE_NULL,Q_m*Hpp); if (frame_parms->Ncp == 0) @@ -747,10 +700,8 @@ uint32_t ulsch_encoding(uint8_t *a, } j=(j+3)&3; - } - // CQI and Data bits j=0; /* @@ -775,7 +726,6 @@ uint32_t ulsch_encoding(uint8_t *a, */ for (i=0; ie[iprime]; + y[1+j2] = ulsch->e[1+iprime]; + j2+=2; + } - for (iprime=0; iprime<(Hprime-Qprime_CQI)<<1; iprime+=2) { - while (y[j2] != LTE_NULL) j2+=2; + break; - y[j2] = ulsch->e[iprime]; - y[1+j2] = ulsch->e[1+iprime]; - j2+=2; - } + case 4: + for (iprime=0; iprime<(Hprime-Qprime_CQI)<<2; iprime+=4) { + while (y[j2] != LTE_NULL) j2+=4; - break; + y[j2] = ulsch->e[iprime]; + y[1+j2] = ulsch->e[1+iprime]; + y[2+j2] = ulsch->e[2+iprime]; + y[3+j2] = ulsch->e[3+iprime]; + j2+=4; + } - case 4: - for (iprime=0; iprime<(Hprime-Qprime_CQI)<<2; iprime+=4) { - while (y[j2] != LTE_NULL) j2+=4; + break; - y[j2] = ulsch->e[iprime]; - y[1+j2] = ulsch->e[1+iprime]; - y[2+j2] = ulsch->e[2+iprime]; - y[3+j2] = ulsch->e[3+iprime]; - j2+=4; - } + case 6: + for (iprime=0; iprime<(Hprime-Qprime_CQI)*6; iprime+=6) { + while (y[j2] != LTE_NULL) j2+=6; - break; - - case 6: - for (iprime=0; iprime<(Hprime-Qprime_CQI)*6; iprime+=6) { - while (y[j2] != LTE_NULL) j2+=6; - - y[j2] = ulsch->e[iprime]; - y[1+j2] = ulsch->e[1+iprime]; - y[2+j2] = ulsch->e[2+iprime]; - y[3+j2] = ulsch->e[3+iprime]; - y[4+j2] = ulsch->e[4+iprime]; - y[5+j2] = ulsch->e[5+iprime]; - j2+=6; - } - - break; + y[j2] = ulsch->e[iprime]; + y[1+j2] = ulsch->e[1+iprime]; + y[2+j2] = ulsch->e[2+iprime]; + y[3+j2] = ulsch->e[3+iprime]; + y[4+j2] = ulsch->e[4+iprime]; + y[5+j2] = ulsch->e[5+iprime]; + j2+=6; + } + break; } // HARQ-ACK Bits (Note these overwrite some bits) @@ -848,57 +795,56 @@ uint32_t ulsch_encoding(uint8_t *a, y[q+(Q_m*((r*Cmux) + columnset[j]))] = ulsch->q_ACK[(q+(Q_m*i))%len_ACK]; #ifdef DEBUG_ULSCH_CODING printf("ulsch_coding.c: ACK %d => y[%d]=%d (i %d, r*Cmux %d, columnset %d)\n",q+(Q_m*i), - q+(Q_m*((r*Cmux) + columnset[j])),ulsch->q_ACK[(q+(Q_m*i))%len_ACK], - i,r*Cmux,columnset[j]); + q+(Q_m*((r*Cmux) + columnset[j])),ulsch->q_ACK[(q+(Q_m*i))%len_ACK], + i,r*Cmux,columnset[j]); #endif } j=(j+3)&3; - } // write out buffer j=0; switch (Q_m) { - case 2: - for (i=0; ih[j++] = *yptr++; - ulsch->h[j++] = *yptr++; - } + case 2: + for (i=0; ih[j++] = *yptr++; + ulsch->h[j++] = *yptr++; + } - break; + break; - case 4: - for (i=0; ih[j++] = *yptr++; - ulsch->h[j++] = *yptr++; - ulsch->h[j++] = *yptr++; - ulsch->h[j++] = *yptr++; - } + case 4: + for (i=0; ih[j++] = *yptr++; + ulsch->h[j++] = *yptr++; + ulsch->h[j++] = *yptr++; + ulsch->h[j++] = *yptr++; + } - break; + break; - case 6: - for (i=0; ih[j++] = *yptr++; - ulsch->h[j++] = *yptr++; - ulsch->h[j++] = *yptr++; - ulsch->h[j++] = *yptr++; - ulsch->h[j++] = *yptr++; - ulsch->h[j++] = *yptr++; - } + case 6: + for (i=0; ih[j++] = *yptr++; + ulsch->h[j++] = *yptr++; + ulsch->h[j++] = *yptr++; + ulsch->h[j++] = *yptr++; + ulsch->h[j++] = *yptr++; + ulsch->h[j++] = *yptr++; + } - break; + break; - default: - break; + default: + break; } stop_meas(m_stats); diff --git a/openair1/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c b/openair1/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c index 7a4555d254..42f411a5a9 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c +++ b/openair1/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c @@ -629,7 +629,7 @@ void nr_ulsch_channel_compensation(int **rxdataF_ext, unsigned char aatx,aarx; char nb_antennas_ue_tx = 1; __m128i *ul_ch128,*ul_ch128_2,*ul_ch_mag128,*ul_ch_mag128b,*rxdataF128,*rxdataF_comp128,*rho128; - __m128i mmtmpD0,mmtmpD1,mmtmpD2,mmtmpD3,QAM_amp128,QAM_amp128b; + __m128i mmtmpD0,mmtmpD1,mmtmpD2,mmtmpD3,QAM_amp128={0},QAM_amp128b={0}; QAM_amp128b = _mm_setzero_si128(); for (aatx=0; aatxMdlharq; i++) { if (dlsch->harq_processes[i]) { @@ -105,7 +103,7 @@ void free_nr_ue_dlsch(NR_UE_DLSCH_t **dlschptr,uint8_t N_RB_DL) free16(dlsch->harq_processes[i]->d[r],(5*8448)*sizeof(short)); dlsch->harq_processes[i]->d[r] = NULL; } - + for (r=0; rharq_processes[i]->w[r]) { free16(dlsch->harq_processes[i]->w[r],(5*8448)*sizeof(short)); @@ -113,7 +111,7 @@ void free_nr_ue_dlsch(NR_UE_DLSCH_t **dlschptr,uint8_t N_RB_DL) } for (r=0; rharq_processes[i]->p_nrLDPC_procBuf[r]){ + if (dlsch->harq_processes[i]->p_nrLDPC_procBuf[r]) { nrLDPC_free_mem(dlsch->harq_processes[i]->p_nrLDPC_procBuf[r]); dlsch->harq_processes[i]->p_nrLDPC_procBuf[r] = NULL; } @@ -123,27 +121,23 @@ void free_nr_ue_dlsch(NR_UE_DLSCH_t **dlschptr,uint8_t N_RB_DL) dlsch->harq_processes[i] = NULL; } } - + free16(dlsch,sizeof(NR_UE_DLSCH_t)); dlsch = NULL; } } -NR_UE_DLSCH_t *new_nr_ue_dlsch(uint8_t Kmimo,uint8_t Mdlharq,uint32_t Nsoft,uint8_t max_ldpc_iterations,uint16_t N_RB_DL, uint8_t abstraction_flag) -{ - +NR_UE_DLSCH_t *new_nr_ue_dlsch(uint8_t Kmimo,uint8_t Mdlharq,uint32_t Nsoft,uint8_t max_ldpc_iterations,uint16_t N_RB_DL, uint8_t abstraction_flag) { NR_UE_DLSCH_t *dlsch; uint8_t exit_flag = 0,i,r; - uint16_t a_segments = MAX_NUM_NR_DLSCH_SEGMENTS; //number of segments to be allocated if (N_RB_DL != 273) { a_segments = a_segments*N_RB_DL; a_segments = (a_segments/273)+1; - } + } uint16_t dlsch_bytes = a_segments*1056; // allocated bytes per segment - dlsch = (NR_UE_DLSCH_t *)malloc16(sizeof(NR_UE_DLSCH_t)); if (dlsch) { @@ -154,7 +148,7 @@ NR_UE_DLSCH_t *new_nr_ue_dlsch(uint8_t Kmimo,uint8_t Mdlharq,uint32_t Nsoft,uint dlsch->Nsoft = Nsoft; dlsch->Mlimit = 4; dlsch->max_ldpc_iterations = max_ldpc_iterations; - + for (i=0; iharq_processes[i] = (NR_DL_UE_HARQ_t *)malloc16(sizeof(NR_DL_UE_HARQ_t)); @@ -162,7 +156,7 @@ NR_UE_DLSCH_t *new_nr_ue_dlsch(uint8_t Kmimo,uint8_t Mdlharq,uint32_t Nsoft,uint memset(dlsch->harq_processes[i],0,sizeof(NR_DL_UE_HARQ_t)); init_downlink_harq_status(dlsch->harq_processes[i]); dlsch->harq_processes[i]->first_tx=1; - dlsch->harq_processes[i]->b = (uint8_t*)malloc16(dlsch_bytes); + dlsch->harq_processes[i]->b = (uint8_t *)malloc16(dlsch_bytes); if (dlsch->harq_processes[i]->b) memset(dlsch->harq_processes[i]->b,0,dlsch_bytes); @@ -170,23 +164,23 @@ NR_UE_DLSCH_t *new_nr_ue_dlsch(uint8_t Kmimo,uint8_t Mdlharq,uint32_t Nsoft,uint exit_flag=3; if (abstraction_flag == 0) { - for (r=0; rharq_processes[i]->p_nrLDPC_procBuf[r] = nrLDPC_init_mem(); - dlsch->harq_processes[i]->c[r] = (uint8_t*)malloc16(1056); + dlsch->harq_processes[i]->c[r] = (uint8_t *)malloc16(1056); if (dlsch->harq_processes[i]->c[r]) memset(dlsch->harq_processes[i]->c[r],0,1056); else exit_flag=2; - dlsch->harq_processes[i]->d[r] = (short*)malloc16((5*8448)*sizeof(short)); + dlsch->harq_processes[i]->d[r] = (short *)malloc16((5*8448)*sizeof(short)); if (dlsch->harq_processes[i]->d[r]) memset(dlsch->harq_processes[i]->d[r],0,(5*8448)*sizeof(short)); else exit_flag=2; - dlsch->harq_processes[i]->w[r] = (short*)malloc16((5*8448)*sizeof(short)); + dlsch->harq_processes[i]->w[r] = (short *)malloc16((5*8448)*sizeof(short)); if (dlsch->harq_processes[i]->w[r]) memset(dlsch->harq_processes[i]->w[r],0,(5*8448)*sizeof(short)); @@ -205,19 +199,16 @@ NR_UE_DLSCH_t *new_nr_ue_dlsch(uint8_t Kmimo,uint8_t Mdlharq,uint32_t Nsoft,uint LOG_D(PHY,"new_ue_dlsch with size %zu: exit_flag = %u\n",sizeof(NR_DL_UE_HARQ_t), exit_flag); free_nr_ue_dlsch(&dlsch,N_RB_DL); - return(NULL); } -void nr_dlsch_unscrambling(int16_t* llr, - uint32_t size, - uint8_t q, - uint32_t Nid, - uint32_t n_RNTI) { - +void nr_dlsch_unscrambling(int16_t *llr, + uint32_t size, + uint8_t q, + uint32_t Nid, + uint32_t n_RNTI) { uint8_t reset; uint32_t x1, x2, s=0; - reset = 1; x2 = (n_RNTI<<15) + (q<<14) + Nid; @@ -226,10 +217,10 @@ void nr_dlsch_unscrambling(int16_t* llr, s = lte_gold_generic(&x1, &x2, reset); reset = 0; } + if (((s>>(i&0x1f))&1)==1) llr[i] = -llr[i]; } - } uint32_t nr_dlsch_decoding(PHY_VARS_NR_UE *phy_vars_ue, @@ -244,9 +235,7 @@ uint32_t nr_dlsch_decoding(PHY_VARS_NR_UE *phy_vars_ue, uint8_t nr_slot_rx, uint8_t harq_pid, uint8_t is_crnti, - uint8_t llr8_flag) -{ - + uint8_t llr8_flag) { #if UE_TIMING_TRACE time_stats_t *dlsch_rate_unmatching_stats=&phy_vars_ue->dlsch_rate_unmatching_stats; time_stats_t *dlsch_turbo_decoding_stats=&phy_vars_ue->dlsch_turbo_decoding_stats; @@ -260,48 +249,43 @@ uint32_t nr_dlsch_decoding(PHY_VARS_NR_UE *phy_vars_ue, uint8_t crc_type; int8_t llrProcBuf[NR_LDPC_MAX_NUM_LLR] __attribute__ ((aligned(32))); t_nrLDPC_dec_params decParams; - t_nrLDPC_dec_params* p_decParams = &decParams; + t_nrLDPC_dec_params *p_decParams = &decParams; t_nrLDPC_time_stats procTime = {0}; - t_nrLDPC_time_stats* p_procTime =&procTime ; - + t_nrLDPC_time_stats *p_procTime =&procTime ; + if (!harq_process) { LOG_E(PHY,"dlsch_decoding.c: NULL harq_process pointer\n"); return(dlsch->max_ldpc_iterations + 1); } - t_nrLDPC_procBuf** p_nrLDPC_procBuf = harq_process->p_nrLDPC_procBuf; + t_nrLDPC_procBuf **p_nrLDPC_procBuf = harq_process->p_nrLDPC_procBuf; // HARQ stats phy_vars_ue->dl_stats[harq_process->round]++; - int16_t z [68*384]; int8_t l [68*384]; //__m128i l; //int16_t inv_d [68*384]; uint8_t kc; uint8_t Ilbrm = 1; - uint32_t Tbslbrm;// = 950984; uint16_t nb_rb;// = 30; double Coderate;// = 0.0; - uint8_t dmrs_Type = harq_process->dmrsConfigType; AssertFatal(dmrs_Type == 0 || dmrs_Type == 1, "Illegal dmrs_type %d\n", dmrs_Type); uint8_t nb_re_dmrs; + if (dmrs_Type==NFAPI_NR_DMRS_TYPE1) { nb_re_dmrs = 6*harq_process->n_dmrs_cdm_groups; - } - else { + } else { nb_re_dmrs = 4*harq_process->n_dmrs_cdm_groups; } + uint16_t dmrs_length = get_num_dmrs(harq_process->dlDmrsSymbPos); - uint32_t i,j; + __m128i *pv = (__m128i *)&z; + __m128i *pl = (__m128i *)&l; + vcd_signal_dumper_dump_function_by_name(VCD_SIGNAL_DUMPER_FUNCTIONS_DLSCH_SEGMENTATION, VCD_FUNCTION_IN); - __m128i *pv = (__m128i*)&z; - __m128i *pl = (__m128i*)&l; - - vcd_signal_dumper_dump_function_by_name(VCD_SIGNAL_DUMPER_FUNCTIONS_DLSCH_SEGMENTATION, VCD_FUNCTION_IN); - //NR_DL_UE_HARQ_t *harq_process = dlsch->harq_processes[0]; if (!dlsch_llr) { @@ -318,42 +302,31 @@ uint32_t nr_dlsch_decoding(PHY_VARS_NR_UE *phy_vars_ue, printf("dlsch_decoding.c: Illegal slot index %d\n",nr_slot_rx); return(dlsch->max_ldpc_iterations + 1); }*/ - /*if (harq_process->harq_ack.ack != 2) { LOG_D(PHY, "[UE %d] DLSCH @ SF%d : ACK bit is %d instead of DTX even before PDSCH is decoded!\n", phy_vars_ue->Mod_id, nr_slot_rx, harq_process->harq_ack.ack); }*/ - // nb_rb = dlsch->nb_rb; - /* if (nb_rb > frame_parms->N_RB_DL) { printf("dlsch_decoding.c: Illegal nb_rb %d\n",nb_rb); return(max_ldpc_iterations + 1); }*/ - /*harq_pid = dlsch->current_harq_pid[proc->thread_id]; if (harq_pid >= 8) { printf("dlsch_decoding.c: Illegal harq_pid %d\n",harq_pid); return(max_ldpc_iterations + 1); } */ - nb_rb = harq_process->nb_rb; - harq_process->trials[harq_process->round]++; - uint16_t nb_rb_oh = 0; // it was not computed at UE side even before and set to 0 in nr_compute_tbs - harq_process->TBS = nr_compute_tbs(harq_process->Qm,harq_process->R,nb_rb,nb_symb_sch,nb_re_dmrs*dmrs_length, nb_rb_oh, 0, harq_process->Nl); - A = harq_process->TBS; ret = dlsch->max_ldpc_iterations + 1; dlsch->last_iteration_cnt = ret; - harq_process->G = nr_get_G(nb_rb, nb_symb_sch, nb_re_dmrs, dmrs_length, harq_process->Qm,harq_process->Nl); G = harq_process->G; - LOG_D(PHY,"DLSCH Decoding, harq_pid %d TBS %d (%d) G %d nb_re_dmrs %d mcs %d Nl %d nb_symb_sch %d nb_rb %d\n",harq_pid,A,A/8,G, nb_re_dmrs,harq_process->mcs, harq_process->Nl, nb_symb_sch,nb_rb); if ((harq_process->R)<1024) @@ -361,41 +334,36 @@ uint32_t nr_dlsch_decoding(PHY_VARS_NR_UE *phy_vars_ue, else Coderate = (float) (harq_process->R) /(float) 2048; - if ((A <=292) || ((A <= NR_MAX_PDSCH_TBS) && (Coderate <= 0.6667)) || Coderate <= 0.25) - { + if ((A <=292) || ((A <= NR_MAX_PDSCH_TBS) && (Coderate <= 0.6667)) || Coderate <= 0.25) { p_decParams->BG = 2; kc = 52; - if (Coderate < 0.3333){ + + if (Coderate < 0.3333) { p_decParams->R = 15; - } - else if (Coderate <0.6667){ + } else if (Coderate <0.6667) { p_decParams->R = 13; - } - else { + } else { p_decParams->R = 23; } - } - else{ + } else { p_decParams->BG = 1; kc = 68; - if (Coderate < 0.6667){ + + if (Coderate < 0.6667) { p_decParams->R = 13; - } - else if (Coderate <0.8889){ + } else if (Coderate <0.8889) { p_decParams->R = 23; - } - else { + } else { p_decParams->R = 89; } } - if (harq_process->round == 0) { - // This is a new packet, so compute quantities regarding segmentation - if (A > NR_MAX_PDSCH_TBS) - harq_process->B = A+24; - else - harq_process->B = A+16; + // This is a new packet, so compute quantities regarding segmentation + if (A > NR_MAX_PDSCH_TBS) + harq_process->B = A+24; + else + harq_process->B = A+16; nr_segmentation(NULL, NULL, @@ -406,29 +374,24 @@ uint32_t nr_dlsch_decoding(PHY_VARS_NR_UE *phy_vars_ue, &harq_process->F, p_decParams->BG); - if (LOG_DEBUGFLAG(DEBUG_DLSCH_DECOD) && (!frame%100)) - LOG_I(PHY,"K %d C %d Z %d nl %d \n", harq_process->K, harq_process->C, p_decParams->Z, harq_process->Nl); + if (LOG_DEBUGFLAG(DEBUG_DLSCH_DECOD) && (!frame%100)) + LOG_I(PHY,"K %d C %d Z %d nl %d \n", harq_process->K, harq_process->C, p_decParams->Z, harq_process->Nl); } - - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_DLSCH_SEGMENTATION, VCD_FUNCTION_OUT); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_DLSCH_SEGMENTATION, VCD_FUNCTION_OUT); p_decParams->Z = harq_process->Z; //printf("dlsch decoding nr segmentation Z %d\n", p_decParams->Z); - //printf("coderate %f kc %d \n", Coderate, kc); - p_decParams->numMaxIter = dlsch->max_ldpc_iterations; p_decParams->outMode= 0; - err_flag = 0; r_offset = 0; - uint16_t a_segments = MAX_NUM_NR_DLSCH_SEGMENTS; //number of segments to be allocated if (nb_rb != 273) { a_segments = a_segments*nb_rb; a_segments = a_segments/273 +1; - } + } if (harq_process->C > a_segments) { LOG_E(PHY,"Illegal harq_process->C %d > %d\n",harq_process->C,a_segments); @@ -438,41 +401,29 @@ uint32_t nr_dlsch_decoding(PHY_VARS_NR_UE *phy_vars_ue, if (LOG_DEBUGFLAG(DEBUG_DLSCH_DECOD)) LOG_I(PHY,"Segmentation: C %d, K %d\n",harq_process->C,harq_process->K); - opp_enabled=1; - Kr = harq_process->K; // [hna] overwrites this line "Kr = p_decParams->Z*kb" Kr_bytes = Kr>>3; K_bits_F = Kr-harq_process->F; for (r=0; rC; r++) { - //printf("start rx segment %d\n",r); E = nr_get_E(G, harq_process->C, harq_process->Qm, harq_process->Nl, r); - #if UE_TIMING_TRACE start_meas(dlsch_deinterleaving_stats); #endif - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_DLSCH_DEINTERLEAVING, VCD_FUNCTION_IN); - - nr_deinterleaving_ldpc(E, harq_process->Qm, harq_process->w[r], // [hna] w is e dlsch_llr+r_offset); - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_DLSCH_DEINTERLEAVING, VCD_FUNCTION_OUT); - - #if UE_TIMING_TRACE stop_meas(dlsch_deinterleaving_stats); #endif - #if UE_TIMING_TRACE start_meas(dlsch_rate_unmatching_stats); #endif - LOG_D(PHY,"HARQ_PID %d Rate Matching Segment %d (coded bits %d,E %d, F %d,unpunctured/repeated bits %d, TBS %d, mod_order %d, nb_rb %d, Nl %d, rv %d, round %d)...\n", harq_pid,r, G,E,harq_process->F, Kr*3, @@ -482,8 +433,6 @@ uint32_t nr_dlsch_decoding(PHY_VARS_NR_UE *phy_vars_ue, harq_process->Nl, harq_process->rvidx, harq_process->round); - - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_DLSCH_RATE_MATCHING, VCD_FUNCTION_IN); if ((harq_process->Nl)<4) @@ -491,7 +440,6 @@ uint32_t nr_dlsch_decoding(PHY_VARS_NR_UE *phy_vars_ue, else Tbslbrm = nr_compute_tbslbrm(harq_process->mcs_table,nb_rb,4); - if (nr_rate_matching_ldpc_rx(Ilbrm, Tbslbrm, p_decParams->BG, @@ -504,14 +452,13 @@ uint32_t nr_dlsch_decoding(PHY_VARS_NR_UE *phy_vars_ue, E, harq_process->F, Kr-harq_process->F-2*(p_decParams->Z))==-1) { - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_DLSCH_RATE_MATCHING, VCD_FUNCTION_OUT); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_DLSCH_RATE_MATCHING, VCD_FUNCTION_OUT); #if UE_TIMING_TRACE stop_meas(dlsch_rate_unmatching_stats); #endif LOG_E(PHY,"dlsch_decoding.c: Problem in rate_matching\n"); return(dlsch->max_ldpc_iterations + 1); } else { - #if UE_TIMING_TRACE stop_meas(dlsch_rate_unmatching_stats); #endif @@ -519,38 +466,33 @@ uint32_t nr_dlsch_decoding(PHY_VARS_NR_UE *phy_vars_ue, r_offset += E; - if (LOG_DEBUGFLAG(DEBUG_DLSCH_DECOD)) - { - LOG_I(PHY,"decoder input(segment %u) :",r); - for (int i=0;id[r][i]); - LOG_D(PHY,"\n"); - } + if (LOG_DEBUGFLAG(DEBUG_DLSCH_DECOD)) { + LOG_I(PHY,"decoder input(segment %u) :",r); + + for (int i=0; id[r][i]); + + LOG_D(PHY,"\n"); + } memset(harq_process->c[r],0,Kr_bytes); - - if (harq_process->C == 1){ + if (harq_process->C == 1) { if (A > NR_MAX_PDSCH_TBS) - crc_type = CRC24_A; - else - crc_type = CRC16; - - length_dec = harq_process->B; + crc_type = CRC24_A; + else + crc_type = CRC16; - } - else{ + length_dec = harq_process->B; + } else { crc_type = CRC24_B; length_dec = (harq_process->B+24*harq_process->C)/harq_process->C; } if (err_flag == 0) { - #if UE_TIMING_TRACE start_meas(dlsch_turbo_decoding_stats); #endif - - //set first 2*Z_c bits to zeros memset(&z[0],0,2*harq_process->Z*sizeof(int16_t)); //set Filler bits @@ -559,61 +501,56 @@ uint32_t nr_dlsch_decoding(PHY_VARS_NR_UE *phy_vars_ue, memcpy((&z[0]+2*harq_process->Z),harq_process->d[r],(K_bits_F-2*harq_process->Z)*sizeof(int16_t)); //skip filler bits memcpy((&z[0]+Kr),harq_process->d[r]+(Kr-2*harq_process->Z),(kc*harq_process->Z-Kr)*sizeof(int16_t)); + //Saturate coded bits before decoding into 8 bits values - for (i=0, j=0; j < ((kc*harq_process->Z)>>4)+1; i+=2, j++) - { + for (i=0, j=0; j < ((kc*harq_process->Z)>>4)+1; i+=2, j++) { pl[j] = _mm_packs_epi16(pv[i],pv[i+1]); } - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_DLSCH_LDPC, VCD_FUNCTION_IN); - no_iteration_ldpc = nrLDPC_decoder(p_decParams, - (int8_t*)&pl[0], - llrProcBuf, - p_nrLDPC_procBuf[r], - p_procTime); + (int8_t *)&pl[0], + llrProcBuf, + p_nrLDPC_procBuf[r], + p_procTime); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_DLSCH_LDPC, VCD_FUNCTION_OUT); // Fixme: correct type is unsigned, but nrLDPC_decoder and all called behind use signed int - if (check_crc((uint8_t*)llrProcBuf,length_dec,harq_process->F,crc_type)) { + if (check_crc((uint8_t *)llrProcBuf,length_dec,harq_process->F,crc_type)) { LOG_D(PHY,"Segment %u CRC OK\n\033[0m",r); + if (r==0) { - for (int i=0;i<10;i++) LOG_D(PHY,"byte %d : %x\n",i,((uint8_t*)llrProcBuf)[i]); + for (int i=0; i<10; i++) LOG_D(PHY,"byte %d : %x\n",i,((uint8_t *)llrProcBuf)[i]); } //Temporary hack no_iteration_ldpc = dlsch->max_ldpc_iterations; ret = no_iteration_ldpc; - } - else { + } else { LOG_D(PHY,"CRC NOT OK\n\033[0m"); } - nb_total_decod++; - if (no_iteration_ldpc > dlsch->max_ldpc_iterations){ + + if (no_iteration_ldpc > dlsch->max_ldpc_iterations) { nb_error_decod++; } - for (int m=0; m < Kr>>3; m ++) - { + for (int m=0; m < Kr>>3; m ++) { harq_process->c[r][m]= (uint8_t) llrProcBuf[m]; } - if (LOG_DEBUGFLAG(DEBUG_DLSCH_DECOD)) - { - for (int k=0;k>3;k++) + if (LOG_DEBUGFLAG(DEBUG_DLSCH_DECOD)) { + for (int k=0; k>3; k++) LOG_D(PHY,"output decoder [%d] = 0x%02x \n", k, harq_process->c[r][k]); - LOG_D(PHY,"no_iterations_ldpc %d (ret %u)\n",no_iteration_ldpc,ret); - } + LOG_D(PHY,"no_iterations_ldpc %d (ret %u)\n",no_iteration_ldpc,ret); + } #if UE_TIMING_TRACE stop_meas(dlsch_turbo_decoding_stats); #endif } - if ((err_flag == 0) && (ret>=(1+dlsch->max_ldpc_iterations))) {// a Code segment is in error so break; LOG_D(PHY,"AbsSubframe %d.%d CRC failed, segment %d/%d \n",frame%1024,nr_slot_rx,r,harq_process->C-1); @@ -623,8 +560,7 @@ uint32_t nr_dlsch_decoding(PHY_VARS_NR_UE *phy_vars_ue, if (err_flag == 1) { LOG_D(PHY,"[UE %d] DLSCH: Setting NAK for SFN/SF %d/%d (pid %d, status %d, round %d, TBS %d, mcs %d) Kr %d r %d harq_process->round %d\n", - phy_vars_ue->Mod_id, frame, nr_slot_rx, harq_pid,harq_process->status, harq_process->round,harq_process->TBS,harq_process->mcs,Kr,r,harq_process->round); - + phy_vars_ue->Mod_id, frame, nr_slot_rx, harq_pid,harq_process->status, harq_process->round,harq_process->TBS,harq_process->mcs,Kr,r,harq_process->round); harq_process->harq_ack.ack = 0; harq_process->harq_ack.harq_id = harq_pid; harq_process->harq_ack.send_harq_status = 1; @@ -636,72 +572,64 @@ uint32_t nr_dlsch_decoding(PHY_VARS_NR_UE *phy_vars_ue, phy_vars_ue->dl_stats[4]++; } - if(is_crnti) - { - LOG_D(PHY,"[UE %d] DLSCH: Setting NACK for nr_slot_rx %d (pid %d, pid status %d, round %d/Max %d, TBS %d)\n", - phy_vars_ue->Mod_id,nr_slot_rx,harq_pid,harq_process->status,harq_process->round,dlsch->Mdlharq,harq_process->TBS); + if(is_crnti) { + LOG_D(PHY,"[UE %d] DLSCH: Setting NACK for nr_slot_rx %d (pid %d, pid status %d, round %d/Max %d, TBS %d)\n", + phy_vars_ue->Mod_id,nr_slot_rx,harq_pid,harq_process->status,harq_process->round,dlsch->Mdlharq,harq_process->TBS); } return((1 + dlsch->max_ldpc_iterations)); } else { - LOG_D(PHY,"[UE %d] DLSCH: Setting ACK for nr_slot_rx %d TBS %d mcs %d nb_rb %d harq_process->round %d\n", - phy_vars_ue->Mod_id,nr_slot_rx,harq_process->TBS,harq_process->mcs,harq_process->nb_rb, harq_process->round); - + phy_vars_ue->Mod_id,nr_slot_rx,harq_process->TBS,harq_process->mcs,harq_process->nb_rb, harq_process->round); harq_process->status = SCH_IDLE; harq_process->round = 0; harq_process->harq_ack.ack = 1; harq_process->harq_ack.harq_id = harq_pid; harq_process->harq_ack.send_harq_status = 1; - + //LOG_D(PHY,"[UE %d] DLSCH: Setting ACK for SFN/SF %d/%d (pid %d, status %d, round %d, TBS %d, mcs %d)\n", - // phy_vars_ue->Mod_id, frame, subframe, harq_pid, harq_process->status, harq_process->round,harq_process->TBS,harq_process->mcs); + // phy_vars_ue->Mod_id, frame, subframe, harq_pid, harq_process->status, harq_process->round,harq_process->TBS,harq_process->mcs); - if(is_crnti) - { - LOG_D(PHY,"[UE %d] DLSCH: Setting ACK for nr_slot_rx %d (pid %d, round %d, TBS %d)\n",phy_vars_ue->Mod_id,nr_slot_rx,harq_pid,harq_process->round,harq_process->TBS); + if(is_crnti) { + LOG_D(PHY,"[UE %d] DLSCH: Setting ACK for nr_slot_rx %d (pid %d, round %d, TBS %d)\n",phy_vars_ue->Mod_id,nr_slot_rx,harq_pid,harq_process->round,harq_process->TBS); } - //LOG_D(PHY,"[UE %d] DLSCH: Setting ACK for subframe %d (pid %d, round %d)\n",phy_vars_ue->Mod_id,subframe,harq_pid,harq_process->round); + //LOG_D(PHY,"[UE %d] DLSCH: Setting ACK for subframe %d (pid %d, round %d)\n",phy_vars_ue->Mod_id,subframe,harq_pid,harq_process->round); } // Reassembly of Transport block here offset = 0; Kr = harq_process->K; Kr_bytes = Kr>>3; - - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_DLSCH_COMBINE_SEG, VCD_FUNCTION_IN); for (r=0; rC; r++) { - memcpy(harq_process->b+offset, - harq_process->c[r], - Kr_bytes - (harq_process->F>>3) - ((harq_process->C>1)?3:0)); + harq_process->c[r], + Kr_bytes - (harq_process->F>>3) - ((harq_process->C>1)?3:0)); offset += (Kr_bytes - (harq_process->F>>3) - ((harq_process->C>1)?3:0)); - if (LOG_DEBUGFLAG(DEBUG_DLSCH_DECOD)) - { + if (LOG_DEBUGFLAG(DEBUG_DLSCH_DECOD)) { LOG_D(PHY,"Segment %u : Kr= %u bytes\n",r,Kr_bytes); LOG_D(PHY,"copied %d bytes to b sequence (harq_pid %d)\n", - (Kr_bytes - (harq_process->F>>3)-((harq_process->C>1)?3:0)),harq_pid); + (Kr_bytes - (harq_process->F>>3)-((harq_process->C>1)?3:0)),harq_pid); LOG_D(PHY,"b[0] = %p,c[%d] = %p\n", - (void *)(uint64_t)(harq_process->b[offset]), - harq_process->F>>3, - (void *)(uint64_t)(harq_process->c[r]) ); - if (frame%100 == 0){ - LOG_D (PHY, "Printing 60 first payload bytes at frame: %d ", frame); - for (int i = 0; i <60 ; i++){ //Kr_bytes - LOG_D(PHY, "[%d] : %x ", i, harq_process->b[i]); - } + (void *)(uint64_t)(harq_process->b[offset]), + harq_process->F>>3, + (void *)(uint64_t)(harq_process->c[r]) ); + + if (frame%100 == 0) { + LOG_D (PHY, "Printing 60 first payload bytes at frame: %d ", frame); + + for (int i = 0; i <60 ; i++) { //Kr_bytes + LOG_D(PHY, "[%d] : %x ", i, harq_process->b[i]); } } + } } VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_DLSCH_COMBINE_SEG, VCD_FUNCTION_OUT); - dlsch->last_iteration_cnt = ret; - return(ret); } @@ -718,9 +646,7 @@ uint32_t nr_dlsch_decoding_mthread(PHY_VARS_NR_UE *phy_vars_ue, uint8_t nr_slot_rx, uint8_t harq_pid, uint8_t is_crnti, - uint8_t llr8_flag) -{ - + uint8_t llr8_flag) { #if UE_TIMING_TRACE time_stats_t *dlsch_rate_unmatching_stats=&phy_vars_ue->dlsch_rate_unmatching_stats; time_stats_t *dlsch_turbo_decoding_stats=&phy_vars_ue->dlsch_turbo_decoding_stats; @@ -738,15 +664,17 @@ uint32_t nr_dlsch_decoding_mthread(PHY_VARS_NR_UE *phy_vars_ue, uint8_t r_thread; uint32_t Er, Gp,GpmodC;*/ t_nrLDPC_dec_params decParams; - t_nrLDPC_dec_params* p_decParams = &decParams; + t_nrLDPC_dec_params *p_decParams = &decParams; t_nrLDPC_time_stats procTime; - t_nrLDPC_time_stats* p_procTime =&procTime ; + t_nrLDPC_time_stats *p_procTime =&procTime ; int8_t llrProcBuf[NR_LDPC_MAX_NUM_LLR] __attribute__ ((aligned(32))); - if (!harq_process) { + + if (!harq_process) { LOG_E(PHY,"dlsch_decoding.c: NULL harq_process pointer\n"); return(dlsch->max_ldpc_iterations); } - t_nrLDPC_procBuf* p_nrLDPC_procBuf = harq_process->p_nrLDPC_procBuf[0]; + + t_nrLDPC_procBuf *p_nrLDPC_procBuf = harq_process->p_nrLDPC_procBuf[0]; uint8_t Nl=4; int16_t z [68*384]; int8_t l [68*384]; @@ -756,22 +684,19 @@ uint32_t nr_dlsch_decoding_mthread(PHY_VARS_NR_UE *phy_vars_ue, uint16_t nb_rb = 30; double Coderate = 0.0; uint8_t dmrs_type = harq_process->dmrsConfigType; - uint8_t nb_re_dmrs; + if (dmrs_type == NFAPI_NR_DMRS_TYPE1) nb_re_dmrs = 6*harq_process->n_dmrs_cdm_groups; else nb_re_dmrs = 4*harq_process->n_dmrs_cdm_groups; - uint16_t length_dmrs = get_num_dmrs(harq_process->dlDmrsSymbPos); - + uint16_t length_dmrs = get_num_dmrs(harq_process->dlDmrsSymbPos); uint32_t i,j; - - __m128i *pv = (__m128i*)&z; - __m128i *pl = (__m128i*)&l; + __m128i *pv = (__m128i *)&z; + __m128i *pl = (__m128i *)&l; notifiedFIFO_t nf; initNotifiedFIFO(&nf); - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_DLSCH_SEGMENTATION, VCD_FUNCTION_IN); if (!dlsch_llr) { @@ -779,217 +704,188 @@ uint32_t nr_dlsch_decoding_mthread(PHY_VARS_NR_UE *phy_vars_ue, return(dlsch->max_ldpc_iterations); } - - if (!frame_parms) { LOG_E(PHY,"dlsch_decoding.c: NULL frame_parms pointer\n"); return(dlsch->max_ldpc_iterations); } - /* if (nr_slot_rx> (frame_parms->slots_per_frame-1)) { - printf("dlsch_decoding.c: Illegal slot index %d\n",nr_slot_rx); - return(dlsch->max_ldpc_iterations); - } - - if (dlsch->harq_ack[nr_slot_rx].ack != 2) { - LOG_D(PHY, "[UE %d] DLSCH @ SF%d : ACK bit is %d instead of DTX even before PDSCH is decoded!\n", - phy_vars_ue->Mod_id, nr_slot_rx, dlsch->harq_ack[nr_slot_rx].ack); - }*/ + /* if (nr_slot_rx> (frame_parms->slots_per_frame-1)) { + printf("dlsch_decoding.c: Illegal slot index %d\n",nr_slot_rx); + return(dlsch->max_ldpc_iterations); + } + if (dlsch->harq_ack[nr_slot_rx].ack != 2) { + LOG_D(PHY, "[UE %d] DLSCH @ SF%d : ACK bit is %d instead of DTX even before PDSCH is decoded!\n", + phy_vars_ue->Mod_id, nr_slot_rx, dlsch->harq_ack[nr_slot_rx].ack); + }*/ /* if (nb_rb > frame_parms->N_RB_DL) { printf("dlsch_decoding.c: Illegal nb_rb %d\n",nb_rb); return(max_ldpc_iterations); }*/ - /*harq_pid = dlsch->current_harq_pid[proc->thread_id]; if (harq_pid >= 8) { printf("dlsch_decoding.c: Illegal harq_pid %d\n",harq_pid); return(max_ldpc_iterations); } */ - nb_rb = harq_process->nb_rb; harq_process->trials[harq_process->round]++; - // HARQ stats phy_vars_ue->dl_stats[harq_process->round]++; - uint16_t nb_rb_oh = 0; // it was not computed at UE side even before and set to 0 in nr_compute_tbs - harq_process->TBS = nr_compute_tbs(harq_process->Qm,harq_process->R,nb_rb,nb_symb_sch,nb_re_dmrs*length_dmrs, nb_rb_oh, 0, harq_process->Nl); - A = harq_process->TBS; - ret = dlsch->max_ldpc_iterations + 1; dlsch->last_iteration_cnt = ret; - harq_process->G = nr_get_G(nb_rb, nb_symb_sch, nb_re_dmrs, length_dmrs, harq_process->Qm,harq_process->Nl); - G = harq_process->G; - - LOG_D(PHY,"DLSCH Decoding main, harq_pid %d TBS %d G %d, nb_re_dmrs %d, length_dmrs %d mcs %d Nl %d nb_symb_sch %d nb_rb %d\n",harq_pid,A,G, nb_re_dmrs, length_dmrs, harq_process->mcs, harq_process->Nl, nb_symb_sch,nb_rb); - + LOG_D(PHY,"DLSCH Decoding main, harq_pid %d TBS %d G %d, nb_re_dmrs %d, length_dmrs %d mcs %d Nl %d nb_symb_sch %d nb_rb %d\n",harq_pid,A,G, nb_re_dmrs, length_dmrs, harq_process->mcs, + harq_process->Nl, nb_symb_sch,nb_rb); proc->decoder_main_available = 1; proc->decoder_thread_available = 0; proc->decoder_thread_available1 = 0; - if ((harq_process->R)<1024) Coderate = (float) (harq_process->R) /(float) 1024; else Coderate = (float) (harq_process->R) /(float) 2048; - if ((A <= 292) || ((A <= NR_MAX_PDSCH_TBS) && (Coderate <= 0.6667)) || Coderate <= 0.25) - { + if ((A <= 292) || ((A <= NR_MAX_PDSCH_TBS) && (Coderate <= 0.6667)) || Coderate <= 0.25) { p_decParams->BG = 2; kc = 52; - if (Coderate < 0.3333){ + + if (Coderate < 0.3333) { p_decParams->R = 15; - } - else if (Coderate <0.6667){ + } else if (Coderate <0.6667) { p_decParams->R = 13; - } - else { + } else { p_decParams->R = 23; } - } - else{ + } else { p_decParams->BG = 1; kc = 68; - if (Coderate < 0.6667){ + + if (Coderate < 0.6667) { p_decParams->R = 13; - } - else if (Coderate <0.8889){ + } else if (Coderate <0.8889) { p_decParams->R = 23; - } - else { + } else { p_decParams->R = 89; } } if (harq_process->round == 0) { - // This is a new packet, so compute quantities regarding segmentation + // This is a new packet, so compute quantities regarding segmentation if (A > NR_MAX_PDSCH_TBS) - harq_process->B = A+24; - else - harq_process->B = A+16; + harq_process->B = A+24; + else + harq_process->B = A+16; - nr_segmentation(NULL, - NULL, - harq_process->B, - &harq_process->C, - &harq_process->K, - &harq_process->Z, - &harq_process->F, - p_decParams->BG); - - - } - - p_decParams->Z = harq_process->Z; + nr_segmentation(NULL, + NULL, + harq_process->B, + &harq_process->C, + &harq_process->K, + &harq_process->Z, + &harq_process->F, + p_decParams->BG); + } + p_decParams->Z = harq_process->Z; p_decParams->numMaxIter = dlsch->max_ldpc_iterations; p_decParams->outMode= 0; - err_flag = 0; r_offset = 0; - uint16_t a_segments = MAX_NUM_NR_DLSCH_SEGMENTS; //number of segments to be allocated if (nb_rb != 273) { a_segments = a_segments*nb_rb; a_segments = a_segments/273 +1; - } + } if (harq_process->C > a_segments) { LOG_E(PHY,"Illegal harq_process->C %d > %d\n",harq_process->C,a_segments); return((1+dlsch->max_ldpc_iterations)); } + if (LOG_DEBUGFLAG(DEBUG_DLSCH_DECOD)) LOG_D(PHY,"Segmentation: C %d, K %d\n",harq_process->C,harq_process->K); - notifiedFIFO_elt_t *res_dl; opp_enabled=1; + if (harq_process->C>1) { - for (int nb_seg =1 ; nb_segC; nb_seg++){ - if ( (res_dl=tryPullTpool(&nf, &pool_dl)) != NULL ) { - pushNotifiedFIFO_nothreadSafe(&freeBlocks_dl,res_dl); - } + for (int nb_seg =1 ; nb_segC; nb_seg++) { + if ( (res_dl=tryPullTpool(&nf, &pool_dl)) != NULL ) { + pushNotifiedFIFO_nothreadSafe(&freeBlocks_dl,res_dl); + } - AssertFatal((msgToPush_dl=pullNotifiedFIFO_nothreadSafe(&freeBlocks_dl)) != NULL,"chained list failure"); - nr_rxtx_thread_data_t *curMsg=(nr_rxtx_thread_data_t *)NotifiedFifoData(msgToPush_dl); - curMsg->UE=phy_vars_ue; - - nbDlProcessing++; + AssertFatal((msgToPush_dl=pullNotifiedFIFO_nothreadSafe(&freeBlocks_dl)) != NULL,"chained list failure"); + nr_rxtx_thread_data_t *curMsg=(nr_rxtx_thread_data_t *)NotifiedFifoData(msgToPush_dl); + curMsg->UE=phy_vars_ue; + nbDlProcessing++; + memset(&curMsg->proc, 0, sizeof(curMsg->proc)); + curMsg->proc.frame_rx = proc->frame_rx; + curMsg->proc.nr_slot_rx = proc->nr_slot_rx; + curMsg->proc.thread_id = proc->thread_id; + curMsg->proc.num_seg = nb_seg; + curMsg->proc.eNB_id= eNB_id; + curMsg->proc.harq_pid=harq_pid; + curMsg->proc.llr8_flag = llr8_flag; + msgToPush_dl->key= (nr_slot_rx%2) ? (nb_seg+30): nb_seg; + pushTpool(&pool_dl, msgToPush_dl); + /*Qm= harq_process->Qm; + Nl=harq_process->Nl; + r_thread = harq_process->C/2-1; + C= harq_process->C; + + Gp = G/Nl/Qm; + GpmodC = Gp%C; - memset(&curMsg->proc, 0, sizeof(curMsg->proc)); - curMsg->proc.frame_rx = proc->frame_rx; - curMsg->proc.nr_slot_rx = proc->nr_slot_rx; - curMsg->proc.thread_id = proc->thread_id; - curMsg->proc.num_seg = nb_seg; + if (r_thread < (C-(GpmodC))) + Er = Nl*Qm * (Gp/C); + else + Er = Nl*Qm * ((GpmodC==0?0:1) + (Gp/C)); + printf("mthread Er %d\n", Er); - curMsg->proc.eNB_id= eNB_id; - curMsg->proc.harq_pid=harq_pid; - curMsg->proc.llr8_flag = llr8_flag; + printf("mthread instance_cnt_dlsch_td %d\n", proc->instance_cnt_dlsch_td);*/ + } - msgToPush_dl->key= (nr_slot_rx%2) ? (nb_seg+30): nb_seg; - pushTpool(&pool_dl, msgToPush_dl); - - /*Qm= harq_process->Qm; - Nl=harq_process->Nl; - r_thread = harq_process->C/2-1; - C= harq_process->C; - - Gp = G/Nl/Qm; - GpmodC = Gp%C; - - - if (r_thread < (C-(GpmodC))) - Er = Nl*Qm * (Gp/C); - else - Er = Nl*Qm * ((GpmodC==0?0:1) + (Gp/C)); - printf("mthread Er %d\n", Er); - - printf("mthread instance_cnt_dlsch_td %d\n", proc->instance_cnt_dlsch_td);*/ - } - //proc->decoder_main_available = 1; + //proc->decoder_main_available = 1; } - r = 0; - if (r==0) r_offset =0; + r = 0; - Kr = harq_process->K; - Kr_bytes = Kr>>3; - K_bits_F = Kr-harq_process->F; + if (r==0) r_offset =0; - E = nr_get_E(G, harq_process->C, harq_process->Qm, harq_process->Nl, r); - - /* - printf("Subblock deinterleaving, dlsch_llr %p, w %p\n", - dlsch_llr+r_offset, - &harq_process->w[r]); - */ + Kr = harq_process->K; + Kr_bytes = Kr>>3; + K_bits_F = Kr-harq_process->F; + E = nr_get_E(G, harq_process->C, harq_process->Qm, harq_process->Nl, r); + /* + printf("Subblock deinterleaving, dlsch_llr %p, w %p\n", + dlsch_llr+r_offset, + &harq_process->w[r]); + */ #if UE_TIMING_TRACE - start_meas(dlsch_deinterleaving_stats); + start_meas(dlsch_deinterleaving_stats); #endif - nr_deinterleaving_ldpc(E, - harq_process->Qm, - harq_process->w[r], - dlsch_llr+r_offset); + nr_deinterleaving_ldpc(E, + harq_process->Qm, + harq_process->w[r], + dlsch_llr+r_offset); - if (LOG_DEBUGFLAG(DEBUG_DLSCH_DECOD)) - for (int i =0; i<16; i++) - LOG_D(PHY,"rx output deinterleaving w[%d]= %d r_offset %u\n", i,harq_process->w[r][i], r_offset); + if (LOG_DEBUGFLAG(DEBUG_DLSCH_DECOD)) + for (int i =0; i<16; i++) + LOG_D(PHY,"rx output deinterleaving w[%d]= %d r_offset %u\n", i,harq_process->w[r][i], r_offset); #if UE_TIMING_TRACE - stop_meas(dlsch_deinterleaving_stats); + stop_meas(dlsch_deinterleaving_stats); #endif - #if UE_TIMING_TRACE - start_meas(dlsch_rate_unmatching_stats); + start_meas(dlsch_rate_unmatching_stats); #endif if (LOG_DEBUGFLAG(DEBUG_DLSCH_DECOD)) @@ -1002,136 +898,126 @@ uint32_t nr_dlsch_decoding_mthread(PHY_VARS_NR_UE *phy_vars_ue, harq_process->Nl, harq_process->rvidx, harq_process->round); - - // for tbslbrm calculation according to 5.4.2.1 of 38.212 - if (harq_process->Nl < Nl) - Nl = harq_process->Nl; + // for tbslbrm calculation according to 5.4.2.1 of 38.212 + if (harq_process->Nl < Nl) + Nl = harq_process->Nl; - Tbslbrm = nr_compute_tbslbrm(harq_process->mcs_table,nb_rb,harq_process->Nl); + Tbslbrm = nr_compute_tbslbrm(harq_process->mcs_table,nb_rb,harq_process->Nl); - if (nr_rate_matching_ldpc_rx(Ilbrm, - Tbslbrm, - p_decParams->BG, - p_decParams->Z, - harq_process->d[r], - harq_process->w[r], - harq_process->C, - harq_process->rvidx, - (harq_process->round==0)?1:0, - E, - harq_process->F, - Kr-harq_process->F-2*(p_decParams->Z))==-1) { + if (nr_rate_matching_ldpc_rx(Ilbrm, + Tbslbrm, + p_decParams->BG, + p_decParams->Z, + harq_process->d[r], + harq_process->w[r], + harq_process->C, + harq_process->rvidx, + (harq_process->round==0)?1:0, + E, + harq_process->F, + Kr-harq_process->F-2*(p_decParams->Z))==-1) { #if UE_TIMING_TRACE - stop_meas(dlsch_rate_unmatching_stats); + stop_meas(dlsch_rate_unmatching_stats); #endif - LOG_E(PHY,"dlsch_decoding.c: Problem in rate_matching\n"); - return(dlsch->max_ldpc_iterations); - } else - { + LOG_E(PHY,"dlsch_decoding.c: Problem in rate_matching\n"); + return(dlsch->max_ldpc_iterations); + } else { #if UE_TIMING_TRACE - stop_meas(dlsch_rate_unmatching_stats); + stop_meas(dlsch_rate_unmatching_stats); #endif - } + } - - if (LOG_DEBUGFLAG(DEBUG_DLSCH_DECOD)) + if (LOG_DEBUGFLAG(DEBUG_DLSCH_DECOD)) for (int i =0; i<16; i++) LOG_I(PHY,"rx output ratematching d[%d]= %d r_offset %u\n", i,harq_process->d[r][i], r_offset); - - if (LOG_DEBUGFLAG(DEBUG_DLSCH_DECOD)) - { - + if (LOG_DEBUGFLAG(DEBUG_DLSCH_DECOD)) { if (r==0) { LOG_M("decoder_llr.m","decllr",dlsch_llr,G,1,0); LOG_M("decoder_in.m","dec",&harq_process->d[0][96],(3*8*Kr_bytes)+12,1,0); } LOG_D(PHY,"decoder input(segment %u) :",r); - for (int i=0;i<(3*8*Kr_bytes);i++) + + for (int i=0; i<(3*8*Kr_bytes); i++) LOG_D(PHY,"%d : %d\n",i,harq_process->d[r][i]); + LOG_D(PHY,"\n"); - } + } - memset(harq_process->c[r],0,Kr_bytes); + memset(harq_process->c[r],0,Kr_bytes); - if (harq_process->C == 1){ - if (A > NR_MAX_PDSCH_TBS) - crc_type = CRC24_A; - else - crc_type = CRC16; + if (harq_process->C == 1) { + if (A > NR_MAX_PDSCH_TBS) + crc_type = CRC24_A; + else + crc_type = CRC16; - length_dec = harq_process->B; - } - else{ - crc_type = CRC24_B; - length_dec = (harq_process->B+24*harq_process->C)/harq_process->C; - } + length_dec = harq_process->B; + } else { + crc_type = CRC24_B; + length_dec = (harq_process->B+24*harq_process->C)/harq_process->C; + } - //#ifndef __AVX2__ - - if (err_flag == 0) { -/* - LOG_D(PHY, "LDPC algo Kr=%d cb_cnt=%d C=%d nbRB=%d crc_type %d TBSInput=%d TBSHarq=%d TBSplus24=%d mcs=%d Qm=%d RIV=%d round=%d maxIter %d\n", - Kr,r,harq_process->C,harq_process->nb_rb,crc_type,A,harq_process->TBS, - harq_process->B,harq_process->mcs,harq_process->Qm,harq_process->rvidx,harq_process->round,dlsch->max_ldpc_iterations); -*/ + //#ifndef __AVX2__ + if (err_flag == 0) { + /* + LOG_D(PHY, "LDPC algo Kr=%d cb_cnt=%d C=%d nbRB=%d crc_type %d TBSInput=%d TBSHarq=%d TBSplus24=%d mcs=%d Qm=%d RIV=%d round=%d maxIter %d\n", + Kr,r,harq_process->C,harq_process->nb_rb,crc_type,A,harq_process->TBS, + harq_process->B,harq_process->mcs,harq_process->Qm,harq_process->rvidx,harq_process->round,dlsch->max_ldpc_iterations); + */ #if UE_TIMING_TRACE - start_meas(dlsch_turbo_decoding_stats); + start_meas(dlsch_turbo_decoding_stats); #endif - LOG_D(PHY,"mthread AbsSubframe %d.%d Start LDPC segment %d/%d \n",frame%1024,nr_slot_rx,r,harq_process->C-1); + LOG_D(PHY,"mthread AbsSubframe %d.%d Start LDPC segment %d/%d \n",frame%1024,nr_slot_rx,r,harq_process->C-1); + /*for (int cnt =0; cnt < (kc-2)*p_decParams->Z; cnt++){ + inv_d[cnt] = (1)*harq_process->d[r][cnt]; + }*/ + //set first 2*Z_c bits to zeros + memset(&z[0],0,2*harq_process->Z*sizeof(int16_t)); + //set Filler bits + memset((&z[0]+K_bits_F),127,harq_process->F*sizeof(int16_t)); + //Move coded bits before filler bits + memcpy((&z[0]+2*harq_process->Z),harq_process->d[r],(K_bits_F-2*harq_process->Z)*sizeof(int16_t)); + //skip filler bits + memcpy((&z[0]+Kr),harq_process->d[r]+(Kr-2*harq_process->Z),(kc*harq_process->Z-Kr)*sizeof(int16_t)); - /*for (int cnt =0; cnt < (kc-2)*p_decParams->Z; cnt++){ - inv_d[cnt] = (1)*harq_process->d[r][cnt]; - }*/ - - //set first 2*Z_c bits to zeros - memset(&z[0],0,2*harq_process->Z*sizeof(int16_t)); - //set Filler bits - memset((&z[0]+K_bits_F),127,harq_process->F*sizeof(int16_t)); - //Move coded bits before filler bits - memcpy((&z[0]+2*harq_process->Z),harq_process->d[r],(K_bits_F-2*harq_process->Z)*sizeof(int16_t)); - //skip filler bits - memcpy((&z[0]+Kr),harq_process->d[r]+(Kr-2*harq_process->Z),(kc*harq_process->Z-Kr)*sizeof(int16_t)); - //Saturate coded bits before decoding into 8 bits values - for (i=0, j=0; j < ((kc*harq_process->Z)>>4)+1; i+=2, j++) - { - pl[j] = _mm_packs_epi16(pv[i],pv[i+1]); - } - - no_iteration_ldpc = nrLDPC_decoder(p_decParams, - (int8_t*)&pl[0], - llrProcBuf, - p_nrLDPC_procBuf, - p_procTime); - - nb_total_decod++; - if (no_iteration_ldpc > 10){ - nb_error_decod++; - ret = 1+dlsch->max_ldpc_iterations; - } - else { - ret=2; - } - - if (check_crc((uint8_t*)llrProcBuf,length_dec,harq_process->F,crc_type)) { - LOG_D(PHY,"Segment %u CRC OK\n",r); - ret = 2; - } - else { - ret = 1+dlsch->max_ldpc_iterations; - } - - if (!nb_total_decod%10000){ - printf("Error number of iteration LPDC %d %ld/%ld \n", no_iteration_ldpc, nb_error_decod,nb_total_decod);fflush(stdout); + //Saturate coded bits before decoding into 8 bits values + for (i=0, j=0; j < ((kc*harq_process->Z)>>4)+1; i+=2, j++) { + pl[j] = _mm_packs_epi16(pv[i],pv[i+1]); } - for (int m=0; m < Kr>>3; m ++) - { - harq_process->c[r][m]= (uint8_t) llrProcBuf[m]; - } + no_iteration_ldpc = nrLDPC_decoder(p_decParams, + (int8_t *)&pl[0], + llrProcBuf, + p_nrLDPC_procBuf, + p_procTime); + nb_total_decod++; + + if (no_iteration_ldpc > 10) { + nb_error_decod++; + ret = 1+dlsch->max_ldpc_iterations; + } else { + ret=2; + } + + if (check_crc((uint8_t *)llrProcBuf,length_dec,harq_process->F,crc_type)) { + LOG_D(PHY,"Segment %u CRC OK\n",r); + ret = 2; + } else { + ret = 1+dlsch->max_ldpc_iterations; + } + + if (!nb_total_decod%10000) { + printf("Error number of iteration LPDC %d %ld/%ld \n", no_iteration_ldpc, nb_error_decod,nb_total_decod); + fflush(stdout); + } + + for (int m=0; m < Kr>>3; m ++) { + harq_process->c[r][m]= (uint8_t) llrProcBuf[m]; + } /*for (int u=0; u < Kr>>3; u ++) { @@ -1149,27 +1035,27 @@ uint32_t nr_dlsch_decoding_mthread(PHY_VARS_NR_UE *phy_vars_ue, //printf("output channel decoder %d %d %d %d %d \n", harq_process->c[r][0], harq_process->c[r][1], harq_process->c[r][2],harq_process->c[r][3], harq_process->c[r][4]); //printf("output decoder %d %d %d %d %d \n", harq_process->c[r][0], harq_process->c[r][1], harq_process->c[r][2],harq_process->c[r][3], harq_process->c[r][4]); - if (LOG_DEBUGFLAG(DEBUG_DLSCH_DECOD)) - for (int k=0;k<32;k++) - LOG_D(PHY,"output decoder [%d] = 0x%02x \n", k, harq_process->c[r][k]); - + if (LOG_DEBUGFLAG(DEBUG_DLSCH_DECOD)) + for (int k=0; k<32; k++) + LOG_D(PHY,"output decoder [%d] = 0x%02x \n", k, harq_process->c[r][k]); #if UE_TIMING_TRACE - stop_meas(dlsch_turbo_decoding_stats); + stop_meas(dlsch_turbo_decoding_stats); #endif - } + } + if ((err_flag == 0) && (ret>=(1+dlsch->max_ldpc_iterations))) {// a Code segment is in error so break; + LOG_D(PHY,"AbsSubframe %d.%d CRC failed, segment %d/%d \n",frame%1024,nr_slot_rx,r,harq_process->C-1); + err_flag = 1; + } - if ((err_flag == 0) && (ret>=(1+dlsch->max_ldpc_iterations))) {// a Code segment is in error so break; - LOG_D(PHY,"AbsSubframe %d.%d CRC failed, segment %d/%d \n",frame%1024,nr_slot_rx,r,harq_process->C-1); - err_flag = 1; - } //} //loop r if (err_flag == 1) { if (LOG_DEBUGFLAG(DEBUG_DLSCH_DECOD)) LOG_I(PHY,"[UE %d] DLSCH: Setting NAK for SFN/SF %d/%d (pid %d, status %d, round %d, TBS %d, mcs %d) Kr %d r %d harq_process->round %d\n", - phy_vars_ue->Mod_id, frame, nr_slot_rx, harq_pid,harq_process->status, harq_process->round,harq_process->TBS,harq_process->mcs,Kr,r,harq_process->round); + phy_vars_ue->Mod_id, frame, nr_slot_rx, harq_pid,harq_process->status, harq_process->round,harq_process->TBS,harq_process->mcs,Kr,r,harq_process->round); + harq_process->harq_ack.ack = 0; harq_process->harq_ack.harq_id = harq_pid; harq_process->harq_ack.send_harq_status = 1; @@ -1180,17 +1066,17 @@ uint32_t nr_dlsch_decoding_mthread(PHY_VARS_NR_UE *phy_vars_ue, harq_process->status = SCH_IDLE; harq_process->round = 0; } - if(is_crnti) - { - LOG_D(PHY,"[UE %d] DLSCH: Setting NACK for nr_slot_rx %d (pid %d, pid status %d, round %d/Max %d, TBS %d)\n", - phy_vars_ue->Mod_id,nr_slot_rx,harq_pid,harq_process->status,harq_process->round,dlsch->Mlimit,harq_process->TBS); + + if(is_crnti) { + LOG_D(PHY,"[UE %d] DLSCH: Setting NACK for nr_slot_rx %d (pid %d, pid status %d, round %d/Max %d, TBS %d)\n", + phy_vars_ue->Mod_id,nr_slot_rx,harq_pid,harq_process->status,harq_process->round,dlsch->Mlimit,harq_process->TBS); } return((1+dlsch->max_ldpc_iterations)); } else { - if (LOG_DEBUGFLAG(DEBUG_DLSCH_DECOD)) + if (LOG_DEBUGFLAG(DEBUG_DLSCH_DECOD)) LOG_I(PHY,"[UE %d] DLSCH: Setting ACK for nr_slot_rx %d TBS %d mcs %d nb_rb %d\n", - phy_vars_ue->Mod_id,nr_slot_rx,harq_process->TBS,harq_process->mcs,harq_process->nb_rb); + phy_vars_ue->Mod_id,nr_slot_rx,harq_process->TBS,harq_process->mcs,harq_process->nb_rb); harq_process->status = SCH_IDLE; harq_process->round = 0; @@ -1198,112 +1084,96 @@ uint32_t nr_dlsch_decoding_mthread(PHY_VARS_NR_UE *phy_vars_ue, harq_process->harq_ack.harq_id = harq_pid; harq_process->harq_ack.send_harq_status = 1; //LOG_I(PHY,"[UE %d] DLSCH: Setting ACK for SFN/SF %d/%d (pid %d, status %d, round %d, TBS %d, mcs %d)\n", - // phy_vars_ue->Mod_id, frame, subframe, harq_pid, harq_process->status, harq_process->round,harq_process->TBS,harq_process->mcs); + // phy_vars_ue->Mod_id, frame, subframe, harq_pid, harq_process->status, harq_process->round,harq_process->TBS,harq_process->mcs); - if(is_crnti) - { - LOG_D(PHY,"[UE %d] DLSCH: Setting ACK for nr_slot_rx %d (pid %d, round %d, TBS %d)\n",phy_vars_ue->Mod_id,nr_slot_rx,harq_pid,harq_process->round,harq_process->TBS); + if(is_crnti) { + LOG_D(PHY,"[UE %d] DLSCH: Setting ACK for nr_slot_rx %d (pid %d, round %d, TBS %d)\n",phy_vars_ue->Mod_id,nr_slot_rx,harq_pid,harq_process->round,harq_process->TBS); } - //LOG_D(PHY,"[UE %d] DLSCH: Setting ACK for subframe %d (pid %d, round %d)\n",phy_vars_ue->Mod_id,subframe,harq_pid,harq_process->round); + //LOG_D(PHY,"[UE %d] DLSCH: Setting ACK for subframe %d (pid %d, round %d)\n",phy_vars_ue->Mod_id,subframe,harq_pid,harq_process->round); } // Reassembly of Transport block here offset = 0; - /* printf("harq_pid %d\n",harq_pid); printf("F %d, Fbytes %d\n",harq_process->F,harq_process->F>>3); printf("C %d\n",harq_process->C); */ //uint32_t wait = 0; - /* while((proc->decoder_thread_available == 0) ) { usleep(1); } proc->decoder_thread_available == 0;*/ - /*notifiedFIFO_elt_t *res1=tryPullTpool(&nf, Tpool); if (!res1) { - printf("mthread trypull null\n"); - usleep(1); - wait++; + printf("mthread trypull null\n"); + usleep(1); + wait++; }*/ - //usleep(50); - proc->decoder_main_available = 0; Kr = harq_process->K; //to check if same K in all segments Kr_bytes = Kr>>3; - + for (r=0; rC; r++) { + memcpy(harq_process->b+offset, + harq_process->c[r], + Kr_bytes- - (harq_process->F>>3) -((harq_process->C>1)?3:0)); + offset += (Kr_bytes - (harq_process->F>>3) - ((harq_process->C>1)?3:0)); - memcpy(harq_process->b+offset, - harq_process->c[r], - Kr_bytes- - (harq_process->F>>3) -((harq_process->C>1)?3:0)); - offset += (Kr_bytes - (harq_process->F>>3) - ((harq_process->C>1)?3:0)); - - if (LOG_DEBUGFLAG(DEBUG_DLSCH_DECOD)) - { - LOG_I(PHY,"Segment %u : Kr= %u bytes\n",r,Kr_bytes); - LOG_I(PHY,"copied %d bytes to b sequence (harq_pid %d)\n", - (Kr_bytes - (harq_process->F>>3)-((harq_process->C>1)?3:0)),harq_pid); - LOG_I(PHY,"b[0] = %p,c[%d] = %p\n", - (void *)(uint64_t)(harq_process->b[offset]), - harq_process->F>>3, - (void *)(uint64_t)(harq_process->c[r])); + if (LOG_DEBUGFLAG(DEBUG_DLSCH_DECOD)) { + LOG_I(PHY,"Segment %u : Kr= %u bytes\n",r,Kr_bytes); + LOG_I(PHY,"copied %d bytes to b sequence (harq_pid %d)\n", + (Kr_bytes - (harq_process->F>>3)-((harq_process->C>1)?3:0)),harq_pid); + LOG_I(PHY,"b[0] = %p,c[%d] = %p\n", + (void *)(uint64_t)(harq_process->b[offset]), + harq_process->F>>3, + (void *)(uint64_t)(harq_process->c[r])); } } - - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_DLSCH_SEGMENTATION, VCD_FUNCTION_OUT); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_DLSCH_SEGMENTATION, VCD_FUNCTION_OUT); dlsch->last_iteration_cnt = ret; //proc->decoder_thread_available = 0; //proc->decoder_main_available = 0; - return(ret); } -void nr_dlsch_decoding_process(void *arg) -{ - nr_rxtx_thread_data_t *rxtxD= (nr_rxtx_thread_data_t *)arg; - UE_nr_rxtx_proc_t *proc = &rxtxD->proc; - PHY_VARS_NR_UE *phy_vars_ue = rxtxD->UE; - int llr8_flag1; - int32_t no_iteration_ldpc,length_dec; - t_nrLDPC_dec_params decParams; - t_nrLDPC_dec_params* p_decParams = &decParams; - t_nrLDPC_time_stats procTime; - t_nrLDPC_time_stats* p_procTime =&procTime ; - int8_t llrProcBuf[NR_LDPC_MAX_NUM_LLR] __attribute__ ((aligned(32))); - t_nrLDPC_procBuf* p_nrLDPC_procBuf; - int16_t z [68*384]; - int8_t l [68*384]; - //__m128i l; - //int16_t inv_d [68*384]; - //int16_t *p_invd =&inv_d; - uint8_t kc; - uint8_t Ilbrm = 1; - uint32_t Tbslbrm = 950984; - uint16_t nb_rb = 30; //to update - double Coderate = 0.0; - uint16_t nb_symb_sch = 12; - uint8_t nb_re_dmrs = 6; - uint16_t length_dmrs = 1; - - uint32_t i,j; - __m128i *pv = (__m128i*)&z; - __m128i *pl = (__m128i*)&l; - - proc->instance_cnt_dlsch_td=-1; - //proc->nr_slot_rx = proc->sub_frame_start * frame_parms->slots_per_subframe; - - proc->decoder_thread_available = 1; - - +void nr_dlsch_decoding_process(void *arg) { + nr_rxtx_thread_data_t *rxtxD= (nr_rxtx_thread_data_t *)arg; + UE_nr_rxtx_proc_t *proc = &rxtxD->proc; + PHY_VARS_NR_UE *phy_vars_ue = rxtxD->UE; + int llr8_flag1; + int32_t no_iteration_ldpc,length_dec; + t_nrLDPC_dec_params decParams; + t_nrLDPC_dec_params *p_decParams = &decParams; + t_nrLDPC_time_stats procTime; + t_nrLDPC_time_stats *p_procTime =&procTime ; + int8_t llrProcBuf[NR_LDPC_MAX_NUM_LLR] __attribute__ ((aligned(32))); + t_nrLDPC_procBuf *p_nrLDPC_procBuf; + int16_t z [68*384]; + int8_t l [68*384]; + //__m128i l; + //int16_t inv_d [68*384]; + //int16_t *p_invd =&inv_d; + uint8_t kc; + uint8_t Ilbrm = 1; + uint32_t Tbslbrm = 950984; + uint16_t nb_rb = 30; //to update + double Coderate = 0.0; + uint16_t nb_symb_sch = 12; + uint8_t nb_re_dmrs = 6; + uint16_t length_dmrs = 1; + uint32_t i,j; + __m128i *pv = (__m128i *)&z; + __m128i *pl = (__m128i *)&l; + proc->instance_cnt_dlsch_td=-1; + //proc->nr_slot_rx = proc->sub_frame_start * frame_parms->slots_per_subframe; + proc->decoder_thread_available = 1; #if UE_TIMING_TRACE time_stats_t *dlsch_rate_unmatching_stats=&phy_vars_ue->dlsch_rate_unmatching_stats; time_stats_t *dlsch_turbo_decoding_stats=&phy_vars_ue->dlsch_turbo_decoding_stats; @@ -1311,47 +1181,32 @@ void nr_dlsch_decoding_process(void *arg) #endif uint32_t A,E; uint32_t G; - uint32_t ret; uint32_t r,r_offset=0,Kr,Kr_bytes,err_flag=0,K_bits_F; - uint8_t crc_type; uint8_t C,Cprime; uint8_t Qm; uint8_t Nl; //uint32_t Er; - int eNB_id = proc->eNB_id; int harq_pid = proc->harq_pid; llr8_flag1 = proc->llr8_flag; int frame = proc->frame_rx; - r = proc->num_seg; - + r = proc->num_seg; NR_UE_DLSCH_t *dlsch = phy_vars_ue->dlsch[proc->thread_id][eNB_id][0]; NR_DL_UE_HARQ_t *harq_process = dlsch->harq_processes[harq_pid]; short *dlsch_llr = phy_vars_ue->pdsch_vars[proc->thread_id][eNB_id]->llr[0]; - p_nrLDPC_procBuf = harq_process->p_nrLDPC_procBuf[r]; nb_symb_sch = harq_process->nb_symbols; LOG_D(PHY,"dlsch decoding process frame %d slot %d segment %d r %u nb symb %d \n", frame, proc->nr_slot_rx, proc->num_seg, r, harq_process->nb_symbols); - - nb_rb = harq_process->nb_rb; - harq_process->trials[harq_process->round]++; - uint16_t nb_rb_oh = 0; // it was not computed at UE side even before and set to 0 in nr_compute_tbs - harq_process->TBS = nr_compute_tbs(harq_process->Qm,harq_process->R,nb_rb,nb_symb_sch,nb_re_dmrs*length_dmrs, nb_rb_oh, 0, harq_process->Nl); - A = harq_process->TBS; //2072 for QPSK 1/3 - - ret = dlsch->max_ldpc_iterations; - harq_process->G = nr_get_G(nb_rb, nb_symb_sch, nb_re_dmrs, length_dmrs, harq_process->Qm,harq_process->Nl); G = harq_process->G; - LOG_D(PHY,"DLSCH Decoding process, harq_pid %d TBS %d G %d mcs %d Nl %d nb_symb_sch %d nb_rb %d\n",harq_pid,A,G, harq_process->mcs, harq_process->Nl, nb_symb_sch,nb_rb); if ((harq_process->R)<1024) @@ -1359,107 +1214,89 @@ void nr_dlsch_decoding_process(void *arg) else Coderate = (float) (harq_process->R) /(float) 2048; - if ((A <= 292) || ((A <= NR_MAX_PDSCH_TBS) && (Coderate <= 0.6667)) || Coderate <= 0.25) - { + if ((A <= 292) || ((A <= NR_MAX_PDSCH_TBS) && (Coderate <= 0.6667)) || Coderate <= 0.25) { p_decParams->BG = 2; kc = 52; - if (Coderate < 0.3333){ + + if (Coderate < 0.3333) { p_decParams->R = 15; - } - else if (Coderate <0.6667){ + } else if (Coderate <0.6667) { p_decParams->R = 13; - } - else { + } else { p_decParams->R = 23; } - } - else{ + } else { p_decParams->BG = 1; kc = 68; - if (Coderate < 0.6667){ + + if (Coderate < 0.6667) { p_decParams->R = 13; - } - else if (Coderate <0.8889){ + } else if (Coderate <0.8889) { p_decParams->R = 23; - } - else { + } else { p_decParams->R = 89; } - } + } harq_process->round =0; - // if (harq_process->round == 0) { - // This is a new packet, so compute quantities regarding segmentation + + // if (harq_process->round == 0) { + // This is a new packet, so compute quantities regarding segmentation if (A > NR_MAX_PDSCH_TBS) - harq_process->B = A+24; - else - harq_process->B = A+16; - - nr_segmentation(NULL, - NULL, - harq_process->B, - &harq_process->C, - &harq_process->K, - &harq_process->Z, - &harq_process->F, - p_decParams->BG); - - p_decParams->Z = harq_process->Z; - - // } - - LOG_D(PHY,"round %d Z %d K %d BG %d\n", harq_process->round, p_decParams->Z, harq_process->K, p_decParams->BG); - + harq_process->B = A+24; + else + harq_process->B = A+16; + nr_segmentation(NULL, + NULL, + harq_process->B, + &harq_process->C, + &harq_process->K, + &harq_process->Z, + &harq_process->F, + p_decParams->BG); + p_decParams->Z = harq_process->Z; + // } + LOG_D(PHY,"round %d Z %d K %d BG %d\n", harq_process->round, p_decParams->Z, harq_process->K, p_decParams->BG); p_decParams->numMaxIter = dlsch->max_ldpc_iterations; p_decParams->outMode= 0; - err_flag = 0; - opp_enabled=1; - Qm= harq_process->Qm; Nl=harq_process->Nl; //r_thread = harq_process->C/2-1; C= harq_process->C; - Cprime = C; //assume CBGTI not present if (r <= Cprime - ((G/(Nl*Qm))%Cprime) - 1) r_offset = Nl*Qm*(G/(Nl*Qm*Cprime)); else r_offset = Nl*Qm*((G/(Nl*Qm*Cprime))+1); - + //for (r=(harq_process->C/2); rC; r++) { - // r=1; //(harq_process->C/2); - + // r=1; //(harq_process->C/2); r_offset = r*r_offset; - Kr = harq_process->K; Kr_bytes = Kr>>3; K_bits_F = Kr-harq_process->F; - E = nr_get_E(G, harq_process->C, harq_process->Qm, harq_process->Nl, r); - #if UE_TIMING_TRACE - start_meas(dlsch_deinterleaving_stats); + start_meas(dlsch_deinterleaving_stats); #endif - nr_deinterleaving_ldpc(E, - harq_process->Qm, - harq_process->w[r], - dlsch_llr+r_offset); + nr_deinterleaving_ldpc(E, + harq_process->Qm, + harq_process->w[r], + dlsch_llr+r_offset); if (LOG_DEBUGFLAG(DEBUG_DLSCH_DECOD)) for (int i =0; i<16; i++) - LOG_D(PHY,"rx output thread 0 deinterleaving w[%d]= %d r_offset %u\n", i,harq_process->w[r][i], r_offset); - + LOG_D(PHY,"rx output thread 0 deinterleaving w[%d]= %d r_offset %u\n", i,harq_process->w[r][i], r_offset); #if UE_TIMING_TRACE - stop_meas(dlsch_deinterleaving_stats); + stop_meas(dlsch_deinterleaving_stats); #endif - #if UE_TIMING_TRACE - start_meas(dlsch_rate_unmatching_stats); + start_meas(dlsch_rate_unmatching_stats); #endif if (LOG_DEBUGFLAG(DEBUG_DLSCH_DECOD)) @@ -1473,134 +1310,128 @@ void nr_dlsch_decoding_process(void *arg) harq_process->rvidx, harq_process->round); + if (Nl<4) + Tbslbrm = nr_compute_tbslbrm(harq_process->mcs_table,nb_rb,Nl); + else + Tbslbrm = nr_compute_tbslbrm(harq_process->mcs_table,nb_rb,4); - if (Nl<4) - Tbslbrm = nr_compute_tbslbrm(harq_process->mcs_table,nb_rb,Nl); + if (nr_rate_matching_ldpc_rx(Ilbrm, + Tbslbrm, + p_decParams->BG, + p_decParams->Z, + harq_process->d[r], + harq_process->w[r], + harq_process->C, + harq_process->rvidx, + (harq_process->round==0)?1:0, + E, + harq_process->F, + Kr-harq_process->F-2*(p_decParams->Z))==-1) { +#if UE_TIMING_TRACE + stop_meas(dlsch_rate_unmatching_stats); +#endif + LOG_E(PHY,"dlsch_decoding.c: Problem in rate_matching\n"); + //return(dlsch->max_ldpc_iterations); + } else { +#if UE_TIMING_TRACE + stop_meas(dlsch_rate_unmatching_stats); +#endif + } + + if (LOG_DEBUGFLAG(DEBUG_DLSCH_DECOD)) { + LOG_D(PHY,"decoder input(segment %u) :",r); + + for (int i=0; i<(3*8*Kr_bytes)+12; i++) + LOG_D(PHY,"%d : %d\n",i,harq_process->d[r][i]); + + LOG_D(PHY,"\n"); + } + + memset(harq_process->c[r],0,Kr_bytes); + + if (harq_process->C == 1) { + if (A > NR_MAX_PDSCH_TBS) + crc_type = CRC24_A; else - Tbslbrm = nr_compute_tbslbrm(harq_process->mcs_table,nb_rb,4); + crc_type = CRC16; + + length_dec = harq_process->B; + } else { + crc_type = CRC24_B; + length_dec = (harq_process->B+24*harq_process->C)/harq_process->C; + } + + if (err_flag == 0) { + /* + LOG_D(PHY, "LDPC algo Kr=%d cb_cnt=%d C=%d nbRB=%d crc_type %d TBSInput=%d TBSHarq=%d TBSplus24=%d mcs=%d Qm=%d RIV=%d round=%d maxIter %d\n", + Kr,r,harq_process->C,harq_process->nb_rb,crc_type,A,harq_process->TBS, + harq_process->B,harq_process->mcs,harq_process->Qm,harq_process->rvidx,harq_process->round,dlsch->max_ldpc_iterations); + */ + if (llr8_flag1) { + AssertFatal (Kr >= 256, "LDPC algo issue Kr=%d cb_cnt=%d C=%d nbRB=%d TBSInput=%d TBSHarq=%d TBSplus24=%d mcs=%d Qm=%d RIV=%d round=%d\n", + Kr,r,harq_process->C,harq_process->nb_rb,A,harq_process->TBS,harq_process->B,harq_process->mcs,harq_process->Qm,harq_process->rvidx,harq_process->round); + } - if (nr_rate_matching_ldpc_rx(Ilbrm, - Tbslbrm, - p_decParams->BG, - p_decParams->Z, - harq_process->d[r], - harq_process->w[r], - harq_process->C, - harq_process->rvidx, - (harq_process->round==0)?1:0, - E, - harq_process->F, - Kr-harq_process->F-2*(p_decParams->Z))==-1) { #if UE_TIMING_TRACE - stop_meas(dlsch_rate_unmatching_stats); -#endif - LOG_E(PHY,"dlsch_decoding.c: Problem in rate_matching\n"); - //return(dlsch->max_ldpc_iterations); - } else - { -#if UE_TIMING_TRACE - stop_meas(dlsch_rate_unmatching_stats); + start_meas(dlsch_turbo_decoding_stats); #endif + // LOG_D(PHY,"AbsSubframe %d.%d Start LDPC segment %d/%d \n",frame%1024,subframe,r,harq_process->C-1); + /* + for (int cnt =0; cnt < (kc-2)*p_decParams->Z; cnt++){ + inv_d[cnt] = (1)*harq_process->d[r][cnt]; + } + */ + //set first 2*Z_c bits to zeros + memset(&z[0],0,2*harq_process->Z*sizeof(int16_t)); + //set Filler bits + memset((&z[0]+K_bits_F),127,harq_process->F*sizeof(int16_t)); + //Move coded bits before filler bits + memcpy((&z[0]+2*harq_process->Z),harq_process->d[r],(K_bits_F-2*harq_process->Z)*sizeof(int16_t)); + //skip filler bits + memcpy((&z[0]+Kr),harq_process->d[r]+(Kr-2*harq_process->Z),(kc*harq_process->Z-Kr)*sizeof(int16_t)); + + //Saturate coded bits before decoding into 8 bits values + for (i=0, j=0; j < ((kc*harq_process->Z)>>4)+1; i+=2, j++) { + pl[j] = _mm_packs_epi16(pv[i],pv[i+1]); } - if (LOG_DEBUGFLAG(DEBUG_DLSCH_DECOD)) { - LOG_D(PHY,"decoder input(segment %u) :",r); - for (int i=0;i<(3*8*Kr_bytes)+12;i++) - LOG_D(PHY,"%d : %d\n",i,harq_process->d[r][i]); - LOG_D(PHY,"\n"); + no_iteration_ldpc = nrLDPC_decoder(p_decParams, + (int8_t *)&pl[0], + llrProcBuf, + p_nrLDPC_procBuf, + p_procTime); + + // Fixme: correct type is unsigned, but nrLDPC_decoder and all called behind use signed int + if (check_crc((uint8_t *)llrProcBuf,length_dec,harq_process->F,crc_type)) { + LOG_D(PHY,"Segment %u CRC OK\n",r); + ret = 2; + } else { + LOG_D(PHY,"Segment %u CRC NOK\n",r); + ret = 1+dlsch->max_ldpc_iterations; } - - memset(harq_process->c[r],0,Kr_bytes); - - if (harq_process->C == 1){ - if (A > NR_MAX_PDSCH_TBS) - crc_type = CRC24_A; - else - crc_type = CRC16; - - length_dec = harq_process->B; - } - else{ - crc_type = CRC24_B; - length_dec = (harq_process->B+24*harq_process->C)/harq_process->C; - } - - if (err_flag == 0) { -/* - LOG_D(PHY, "LDPC algo Kr=%d cb_cnt=%d C=%d nbRB=%d crc_type %d TBSInput=%d TBSHarq=%d TBSplus24=%d mcs=%d Qm=%d RIV=%d round=%d maxIter %d\n", - Kr,r,harq_process->C,harq_process->nb_rb,crc_type,A,harq_process->TBS, - harq_process->B,harq_process->mcs,harq_process->Qm,harq_process->rvidx,harq_process->round,dlsch->max_ldpc_iterations); -*/ - if (llr8_flag1) { - AssertFatal (Kr >= 256, "LDPC algo issue Kr=%d cb_cnt=%d C=%d nbRB=%d TBSInput=%d TBSHarq=%d TBSplus24=%d mcs=%d Qm=%d RIV=%d round=%d\n", - Kr,r,harq_process->C,harq_process->nb_rb,A,harq_process->TBS,harq_process->B,harq_process->mcs,harq_process->Qm,harq_process->rvidx,harq_process->round); - } -#if UE_TIMING_TRACE - start_meas(dlsch_turbo_decoding_stats); -#endif -// LOG_D(PHY,"AbsSubframe %d.%d Start LDPC segment %d/%d \n",frame%1024,subframe,r,harq_process->C-1); -/* - for (int cnt =0; cnt < (kc-2)*p_decParams->Z; cnt++){ - inv_d[cnt] = (1)*harq_process->d[r][cnt]; - } -*/ - - //set first 2*Z_c bits to zeros - memset(&z[0],0,2*harq_process->Z*sizeof(int16_t)); - //set Filler bits - memset((&z[0]+K_bits_F),127,harq_process->F*sizeof(int16_t)); - //Move coded bits before filler bits - memcpy((&z[0]+2*harq_process->Z),harq_process->d[r],(K_bits_F-2*harq_process->Z)*sizeof(int16_t)); - //skip filler bits - memcpy((&z[0]+Kr),harq_process->d[r]+(Kr-2*harq_process->Z),(kc*harq_process->Z-Kr)*sizeof(int16_t)); - //Saturate coded bits before decoding into 8 bits values - for (i=0, j=0; j < ((kc*harq_process->Z)>>4)+1; i+=2, j++) - { - pl[j] = _mm_packs_epi16(pv[i],pv[i+1]); - } - - no_iteration_ldpc = nrLDPC_decoder(p_decParams, - (int8_t*)&pl[0], - llrProcBuf, - p_nrLDPC_procBuf, - p_procTime); - - // Fixme: correct type is unsigned, but nrLDPC_decoder and all called behind use signed int - if (check_crc((uint8_t*)llrProcBuf,length_dec,harq_process->F,crc_type)) { - LOG_D(PHY,"Segment %u CRC OK\n",r); - ret = 2; - } - else { - LOG_D(PHY,"Segment %u CRC NOK\n",r); - ret = 1+dlsch->max_ldpc_iterations; - } - if (no_iteration_ldpc > 10) LOG_D(PHY,"Error number of iteration LPDC %d\n", no_iteration_ldpc); + for (int m=0; m < Kr>>3; m ++) { + harq_process->c[r][m]= (uint8_t) llrProcBuf[m]; + } - for (int m=0; m < Kr>>3; m ++) - { - harq_process->c[r][m]= (uint8_t) llrProcBuf[m]; - } - - if ( LOG_DEBUGFLAG(DEBUG_DLSCH_DECOD)) - for (int k=0;k<2;k++) + if ( LOG_DEBUGFLAG(DEBUG_DLSCH_DECOD)) + for (int k=0; k<2; k++) LOG_D(PHY,"segment 1 output decoder [%d] = 0x%02x \n", k, harq_process->c[r][k]); - #if UE_TIMING_TRACE - stop_meas(dlsch_turbo_decoding_stats); + stop_meas(dlsch_turbo_decoding_stats); #endif - } + } + + if ((err_flag == 0) && (ret>=(1+dlsch->max_ldpc_iterations))) {// a Code segment is in error so break; + // LOG_D(PHY,"AbsSubframe %d.%d CRC failed, segment %d/%d \n",frame%1024,subframe,r,harq_process->C-1); + err_flag = 1; + } - if ((err_flag == 0) && (ret>=(1+dlsch->max_ldpc_iterations))) {// a Code segment is in error so break; -// LOG_D(PHY,"AbsSubframe %d.%d CRC failed, segment %d/%d \n",frame%1024,subframe,r,harq_process->C-1); - err_flag = 1; - } //} - proc->decoder_thread_available = 1; //proc->decoder_main_available = 0; } @@ -1612,12 +1443,12 @@ void *dlsch_thread(void *arg) { notifiedFIFO_elt_t *res_dl; initNotifiedFIFO_nothreadSafe(&freeBlocks_dl); - for (int i=0; i= tpool_nbthreads(pool_dl)) { @@ -1628,15 +1459,12 @@ void *dlsch_thread(void *arg) { usleep(200); } - + res_dl=pullTpool(&nf, &pool_dl); nbDlProcessing--; - pushNotifiedFIFO_nothreadSafe(&freeBlocks_dl,res_dl); - - + pushNotifiedFIFO_nothreadSafe(&freeBlocks_dl,res_dl); //msgToPush->key=0; //pushTpool(Tpool, msgToPush); - } // while !oai_exit return NULL; diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_demodulation.c b/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_demodulation.c index 2046c13eaa..12d95a07fd 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_demodulation.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_demodulation.c @@ -793,7 +793,7 @@ void nr_dlsch_channel_compensation(int **rxdataF_ext, unsigned short rb; unsigned char aatx,aarx,atx; __m128i *dl_ch128,*dl_ch128_2,*dl_ch_mag128,*dl_ch_mag128b,*dl_ch_mag128r,*rxdataF128,*rxdataF_comp128,*rho128; - __m128i mmtmpD0,mmtmpD1,mmtmpD2,mmtmpD3,QAM_amp128,QAM_amp128b,QAM_amp128r; + __m128i mmtmpD0,mmtmpD1,mmtmpD2,mmtmpD3,QAM_amp128={0},QAM_amp128b={0},QAM_amp128r={0}; QAM_amp128b = _mm_setzero_si128(); for (aatx=0; aatxsize; l = l->next; } diff --git a/openair2/LAYER2/nr_rlc/nr_rlc_entity_tm.c b/openair2/LAYER2/nr_rlc/nr_rlc_entity_tm.c index 86a0697624..26ae481889 100644 --- a/openair2/LAYER2/nr_rlc/nr_rlc_entity_tm.c +++ b/openair2/LAYER2/nr_rlc/nr_rlc_entity_tm.c @@ -78,7 +78,7 @@ static int tx_list_size(nr_rlc_entity_tm_t *entity, { int ret = 0; - while (l != NULL) { + while (l != NULL && ret < maxsize) { ret += l->size; l = l->next; } diff --git a/openair2/LAYER2/nr_rlc/nr_rlc_entity_um.c b/openair2/LAYER2/nr_rlc/nr_rlc_entity_um.c index 4ef952667d..f967c3c543 100644 --- a/openair2/LAYER2/nr_rlc/nr_rlc_entity_um.c +++ b/openair2/LAYER2/nr_rlc/nr_rlc_entity_um.c @@ -497,7 +497,7 @@ static int tx_list_size(nr_rlc_entity_um_t *entity, { int ret = 0; - while (l != NULL) { + while (l != NULL && ret < maxsize) { ret += compute_pdu_header_size(entity, l) + l->size; l = l->next; } From 6b71382a6883604cd669088a3669a2ea62827dcb Mon Sep 17 00:00:00 2001 From: Laurent OpenCells Date: Tue, 20 Jul 2021 17:50:08 +0200 Subject: [PATCH 48/91] merge develop --- openair1/PHY/CODING/3gpplte_turbo_decoder_avx2_16bit.c | 2 +- openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_demodulation.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/openair1/PHY/CODING/3gpplte_turbo_decoder_avx2_16bit.c b/openair1/PHY/CODING/3gpplte_turbo_decoder_avx2_16bit.c index 8c2513b702..619a8f07b9 100644 --- a/openair1/PHY/CODING/3gpplte_turbo_decoder_avx2_16bit.c +++ b/openair1/PHY/CODING/3gpplte_turbo_decoder_avx2_16bit.c @@ -933,7 +933,7 @@ unsigned char phy_threegpplte_turbo_decoder16avx2(int16_t *y, uint32_t db; - __m256i tmp, zeros=_mm256_setzero_si256(); + __m256i tmp={0}, zeros=_mm256_setzero_si256(); int offset8_flag=0; diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_demodulation.c b/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_demodulation.c index 85090f79cd..e2bc810085 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_demodulation.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_demodulation.c @@ -2877,7 +2877,7 @@ uint8_t nr_zero_forcing_rx_2layers(int **rxdataF_comp, * * **************************************************************************/ - __m128i *rxdataF_comp128_0,*rxdataF_comp128_1,*dl_ch_mag128_0,*dl_ch_mag128b_0,*dl_ch_mag128r_0,*determ_fin_128;//*dl_ch_mag128_1,*dl_ch_mag128b_1,*dl_ch_mag128r_1 + __m128i *rxdataF_comp128_0,*rxdataF_comp128_1,*dl_ch_mag128_0=NULL,*dl_ch_mag128b_0=NULL,*dl_ch_mag128r_0=NULL,*determ_fin_128;//*dl_ch_mag128_1,*dl_ch_mag128b_1,*dl_ch_mag128r_1 __m128i mmtmpD0,mmtmpD1,mmtmpD2,mmtmpD3; __m128i *after_mf_a_128,*after_mf_b_128, *after_mf_c_128, *after_mf_d_128; __m128i QAM_amp128={0},QAM_amp128b={0},QAM_amp128r={0}; From 39c63eb158c499684cf2ce534b48f98f50d39868 Mon Sep 17 00:00:00 2001 From: Laurent OpenCells Date: Thu, 22 Jul 2021 13:19:37 +0200 Subject: [PATCH 49/91] move function declaration in not duplicated files (.h instead of .c) --- .../conf_files/rcc.band7.tm1.nfapi.conf | 20 ++++----- ci-scripts/conf_files/ue.nfapi.conf | 6 +-- cmake_targets/CMakeLists.txt | 4 +- executables/nr-softmodem.c | 2 +- nfapi/oai_integration/nfapi_pnf.c | 42 ++----------------- nfapi/oai_integration/nfapi_vnf.c | 2 +- .../PHY/LTE_UE_TRANSPORT/dlsch_demodulation.c | 2 +- openair1/SCHED/fapi_l1.h | 6 ++- openair1/SIMULATION/TOOLS/channel_sim.c | 16 +++---- targets/RT/USER/lte-softmodem.c | 2 - 10 files changed, 34 insertions(+), 68 deletions(-) diff --git a/ci-scripts/conf_files/rcc.band7.tm1.nfapi.conf b/ci-scripts/conf_files/rcc.band7.tm1.nfapi.conf index 281f7433af..bfd07512f1 100644 --- a/ci-scripts/conf_files/rcc.band7.tm1.nfapi.conf +++ b/ci-scripts/conf_files/rcc.band7.tm1.nfapi.conf @@ -15,7 +15,7 @@ eNBs = // Tracking area code, 0x0000 and 0xfffe are reserved values tracking_area_code = 1; - plmn_list = ( { mcc = 208; mnc = 93; mnc_length = 2; } ); + plmn_list = ( { mcc = 450; mnc = 05; mnc_length = 2; } ); tr_s_preference = "local_mac" @@ -172,7 +172,7 @@ eNBs = ////////// MME parameters: - mme_ip_address = ( { ipv4 = "CI_MME_IP_ADDR"; + mme_ip_address = ( { ipv4 = "192.168.5.233"; ipv6 = "192:168:30::17"; port = 36412 ; active = "yes"; @@ -191,12 +191,12 @@ eNBs = NETWORK_INTERFACES : { - ENB_INTERFACE_NAME_FOR_S1_MME = "ens3"; - ENB_IPV4_ADDRESS_FOR_S1_MME = "CI_ENB_IP_ADDR"; - ENB_INTERFACE_NAME_FOR_S1U = "ens3"; - ENB_IPV4_ADDRESS_FOR_S1U = "CI_ENB_IP_ADDR"; + ENB_INTERFACE_NAME_FOR_S1_MME = "enp0s31f6"; + ENB_IPV4_ADDRESS_FOR_S1_MME = "192.168.5.200"; + ENB_INTERFACE_NAME_FOR_S1U = "enp0s31f6"; + ENB_IPV4_ADDRESS_FOR_S1U = "192.168.5.200"; ENB_PORT_FOR_S1U = 2152; # Spec 2152 - ENB_IPV4_ADDRESS_FOR_X2C = "CI_ENB_IP_ADDR"; + ENB_IPV4_ADDRESS_FOR_X2C = "192.168.5.200"; ENB_PORT_FOR_X2C = 36422; # Spec 36422 }; @@ -206,9 +206,9 @@ eNBs = MACRLCs = ( { num_cc = 1; - local_s_if_name = "ens3"; - remote_s_address = "CI_UE_IP_ADDR"; - local_s_address = "CI_ENB_IP_ADDR"; + local_s_if_name = "enp0s31f6"; + remote_s_address = "127.0.0.1"; + local_s_address = "127.0.0.1"; local_s_portc = 50001; remote_s_portc = 50000; local_s_portd = 50011; diff --git a/ci-scripts/conf_files/ue.nfapi.conf b/ci-scripts/conf_files/ue.nfapi.conf index 2b602cbcf2..3e78be1278 100644 --- a/ci-scripts/conf_files/ue.nfapi.conf +++ b/ci-scripts/conf_files/ue.nfapi.conf @@ -20,9 +20,9 @@ L1s = ( { num_cc = 1; tr_n_preference = "nfapi"; - local_n_if_name = "ens3"; - remote_n_address = "CI_ENB_IP_ADDR"; - local_n_address = "CI_UE_IP_ADDR"; + local_n_if_name = "enp0s31f6"; + remote_n_address = "127.0.0.1"; + local_n_address = "127.0.0.1"; local_n_portc = 50000; remote_n_portc = 50001; local_n_portd = 50010; diff --git a/cmake_targets/CMakeLists.txt b/cmake_targets/CMakeLists.txt index b8992573cd..b26a3fce33 100644 --- a/cmake_targets/CMakeLists.txt +++ b/cmake_targets/CMakeLists.txt @@ -349,8 +349,8 @@ set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,-rpath -Wl,${CMAKE_CU ######################### # set a flag for changes in the source code # these changes are related to hardcoded path to include .h files -set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS} -g3 -Og -DMALLOC_CHECK_=3") -set(CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS} -g3 -DMALLOC_CHECK_=3 -O2 -fno-delete-null-pointer-checks") +set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS} -ggdb3 -ggnu-pubnames -fvar-tracking-assignments -feliminate-dwarf2-dups -Og -DMALLOC_CHECK_=3") +set(CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS} -ggdb3 -ggnu-pubnames -fvar-tracking-assignments -feliminate-dwarf2-dups -DMALLOC_CHECK_=3 -O2 -fno-delete-null-pointer-checks") set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS} -O3") set(GIT_BRANCH "UNKNOWN") diff --git a/executables/nr-softmodem.c b/executables/nr-softmodem.c index 5afc576bbb..b855418d64 100644 --- a/executables/nr-softmodem.c +++ b/executables/nr-softmodem.c @@ -53,6 +53,7 @@ #include "PHY_INTERFACE/phy_interface_vars.h" #include "gnb_config.h" #include "SIMULATION/TOOLS/sim.h" +#include #ifdef SMBV #include "PHY/TOOLS/smbv.h" @@ -179,7 +180,6 @@ void sendFs6Ulharq(enum pckType type, int UEid, PHY_VARS_eNB *eNB, LTE_eNB_UCI * extern void reset_opp_meas(void); extern void print_opp_meas(void); -extern void init_eNB_afterRU(void); extern void *udp_eNB_task(void *args_p); int transmission_mode=1; diff --git a/nfapi/oai_integration/nfapi_pnf.c b/nfapi/oai_integration/nfapi_pnf.c index 5ce66aad89..d9c5df199c 100644 --- a/nfapi/oai_integration/nfapi_pnf.c +++ b/nfapi/oai_integration/nfapi_pnf.c @@ -59,6 +59,9 @@ extern RAN_CONTEXT_t RC; #include "openair1/SCHED_NR/fapi_nr_l1.h" #include "openair1/PHY/NR_TRANSPORT/nr_dlsch.h" #include "openair1/PHY/defs_gNB.h" +#include +#include +#include #define NUM_P5_PHY 2 @@ -74,45 +77,6 @@ extern int nfapi_sync_var; extern int sync_var; -extern void init_eNB_afterRU(void); -extern void init_UE_stub(int nb_inst,int,int); -extern void handle_nfapi_dci_dl_pdu(PHY_VARS_eNB *eNB, int frame, int subframe, L1_rxtx_proc_t *proc, nfapi_dl_config_request_pdu_t *dl_config_pdu); -extern void handle_nfapi_ul_pdu(PHY_VARS_eNB *eNB,L1_rxtx_proc_t *proc, nfapi_ul_config_request_pdu_t *ul_config_pdu, uint16_t frame,uint8_t subframe,uint8_t srs_present); -extern void handle_nfapi_dlsch_pdu(PHY_VARS_eNB *eNB,int frame, int subframe, L1_rxtx_proc_t *proc, nfapi_dl_config_request_pdu_t *dl_config_pdu, uint8_t codeword_index, uint8_t *sdu); -extern void handle_nfapi_hi_dci0_dci_pdu(PHY_VARS_eNB *eNB,int frame, int subframe, L1_rxtx_proc_t *proc, nfapi_hi_dci0_request_pdu_t *hi_dci0_config_pdu); -extern void handle_nfapi_hi_dci0_hi_pdu(PHY_VARS_eNB *eNB,int frame, int subframe, L1_rxtx_proc_t *proc, nfapi_hi_dci0_request_pdu_t *hi_dci0_config_pdu); -extern void handle_nfapi_bch_pdu(PHY_VARS_eNB *eNB,L1_rxtx_proc_t *proc, nfapi_dl_config_request_pdu_t *dl_config_pdu, uint8_t *sdu); -extern void handle_nfapi_nr_ul_dci_pdu(PHY_VARS_gNB *gNB, - int frame, int slot, - nfapi_nr_ul_dci_request_pdus_t *ul_dci_request_pdu); -extern void handle_nfapi_nr_pdcch_pdu(PHY_VARS_gNB *gNB, - int frame, int slot, - nfapi_nr_dl_tti_pdcch_pdu *pdcch_pdu); -extern void handle_nr_nfapi_pdsch_pdu(PHY_VARS_gNB *gNB,int frame,int slot, - nfapi_nr_dl_tti_pdsch_pdu *pdsch_pdu, - uint8_t *sdu); -extern void handle_nr_nfapi_ssb_pdu(PHY_VARS_gNB *gNB,int frame,int slot, - nfapi_nr_dl_tti_request_pdu_t *dl_tti_pdu); -extern void nr_fill_ulsch(PHY_VARS_gNB *gNB, - int frame, - int slot, - nfapi_nr_pusch_pdu_t *ulsch_pdu); -extern void nr_fill_pucch(PHY_VARS_gNB *gNB, - int frame, - int slot, - nfapi_nr_pucch_pdu_t *pucch_pdu); -extern void nr_fill_prach(PHY_VARS_gNB *gNB, - int SFN, - int Slot, - nfapi_nr_prach_pdu_t *prach_pdu); -extern void nr_fill_prach_ru(RU_t *ru, - int SFN, - int Slot, - nfapi_nr_prach_pdu_t *prach_pdu); - - - - nfapi_tx_request_pdu_t *tx_request_pdu[1023][10][10]; // [frame][subframe][max_num_pdus] uint8_t nr_tx_pdus[32][16][4096]; nfapi_nr_pdu_t *tx_data_request[1023][20][10]; //[frame][slot][max_num_pdus] diff --git a/nfapi/oai_integration/nfapi_vnf.c b/nfapi/oai_integration/nfapi_vnf.c index 485f17922f..f4448e71df 100644 --- a/nfapi/oai_integration/nfapi_vnf.c +++ b/nfapi/oai_integration/nfapi_vnf.c @@ -40,6 +40,7 @@ #include "PHY/defs_eNB.h" #include "PHY/LTE_TRANSPORT/transport_proto.h" #include "openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h" +#include #include "common/ran_context.h" @@ -196,7 +197,6 @@ int vnf_unpack_vendor_extension_tlv(nfapi_tl_t *tl, uint8_t **ppReadPackedMessag void install_nr_schedule_handlers(NR_IF_Module_t *if_inst); void install_schedule_handlers(IF_Module_t *if_inst); extern int single_thread_flag; -extern void init_eNB_afterRU(void); extern uint16_t sf_ahead; extern uint16_t slot_ahead; diff --git a/openair1/PHY/LTE_UE_TRANSPORT/dlsch_demodulation.c b/openair1/PHY/LTE_UE_TRANSPORT/dlsch_demodulation.c index d793536b93..9906b945d8 100644 --- a/openair1/PHY/LTE_UE_TRANSPORT/dlsch_demodulation.c +++ b/openair1/PHY/LTE_UE_TRANSPORT/dlsch_demodulation.c @@ -2004,7 +2004,7 @@ void dlsch_channel_compensation_TM56(int **rxdataF_ext, __m128i *dl_ch0_128,*dl_ch1_128,*dl_ch_mag128,*dl_ch_mag128b,*rxdataF128,*rxdataF_comp128; unsigned char aarx=0,symbol_mod,pilots=0; int precoded_signal_strength=0; - __m128i mmtmpD0,mmtmpD1,mmtmpD2,mmtmpD3,QAM_amp128; + __m128i mmtmpD0,mmtmpD1,mmtmpD2,mmtmpD3,QAM_amp128={0}; symbol_mod = (symbol>=(7-frame_parms->Ncp)) ? symbol-(7-frame_parms->Ncp) : symbol; if ((symbol_mod == 0) || (symbol_mod == (4-frame_parms->Ncp))) diff --git a/openair1/SCHED/fapi_l1.h b/openair1/SCHED/fapi_l1.h index b8f0ae1dd8..60ef5e764a 100644 --- a/openair1/SCHED/fapi_l1.h +++ b/openair1/SCHED/fapi_l1.h @@ -61,6 +61,8 @@ void handle_nfapi_ul_pdu(PHY_VARS_eNB *eNB,L1_rxtx_proc_t *proc, nfapi_ul_config_request_pdu_t *ul_config_pdu, uint16_t frame,uint8_t subframe,uint8_t srs_present); +void handle_nfapi_hi_dci0_dci_pdu(PHY_VARS_eNB *eNB,int frame,int subframe,L1_rxtx_proc_t *proc, + nfapi_hi_dci0_request_pdu_t *hi_dci0_config_pdu); void handle_ulsch_harq_pdu( PHY_VARS_eNB *eNB, int UE_id, @@ -68,7 +70,9 @@ void handle_ulsch_harq_pdu( nfapi_ul_config_ulsch_harq_information *harq_information, uint16_t frame, uint8_t subframe); - +void handle_nfapi_bch_pdu(PHY_VARS_eNB *eNB,L1_rxtx_proc_t *proc, + nfapi_dl_config_request_pdu_t *dl_config_pdu, + uint8_t *sdu) ; void handle_ulsch_cqi_ri_pdu(PHY_VARS_eNB *eNB,int UE_id,nfapi_ul_config_request_pdu_t *ul_config_pdu,uint16_t frame,uint8_t subframe); void handle_uci_harq_information(PHY_VARS_eNB *eNB, LTE_eNB_UCI *uci,nfapi_ul_config_harq_information *harq_information); diff --git a/openair1/SIMULATION/TOOLS/channel_sim.c b/openair1/SIMULATION/TOOLS/channel_sim.c index 81949f40e6..197a296a51 100644 --- a/openair1/SIMULATION/TOOLS/channel_sim.c +++ b/openair1/SIMULATION/TOOLS/channel_sim.c @@ -70,16 +70,16 @@ void do_DL_sig(sim_t *sim, double s_re0[30720]; double s_re1[30720]; - double *s_re[2]; + double *s_re[RC.nb_RU]; double s_im0[30720]; double s_im1[30720]; - double *s_im[2]; + double *s_im[RC.nb_RU]; double r_re00[30720]; double r_re01[30720]; - double *r_re0[2]; + double *r_re0[RC.nb_RU]; double r_im00[30720]; double r_im01[30720]; - double *r_im0[2]; + double *r_im0[RC.nb_RU]; LTE_DL_FRAME_PARMS *frame_parms; s_re[0] = s_re0; @@ -320,16 +320,16 @@ void do_UL_sig(sim_t *sim, double s_re0[30720]; double s_re1[30720]; - double *s_re[2]; + double *s_re[NB_UE_INST]; double s_im0[30720]; double s_im1[30720]; - double *s_im[2]; + double *s_im[NB_UE_INST]; double r_re00[30720]; double r_re01[30720]; - double *r_re0[2]; + double *r_re0[NB_UE_INST]; double r_im00[30720]; double r_im01[30720]; - double *r_im0[2]; + double *r_im0[NB_UE_INST]; s_re[0] = s_re0; s_im[0] = s_im0; diff --git a/targets/RT/USER/lte-softmodem.c b/targets/RT/USER/lte-softmodem.c index 424a139001..f9ff03e422 100644 --- a/targets/RT/USER/lte-softmodem.c +++ b/targets/RT/USER/lte-softmodem.c @@ -169,8 +169,6 @@ extern void reset_opp_meas(void); extern void print_opp_meas(void); -extern void init_eNB_afterRU(void); - 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; From b3f3a1db577db16bb0f2e2a92c5bbd7b39857c3f Mon Sep 17 00:00:00 2001 From: Laurent Thomas Date: Fri, 23 Jul 2021 16:38:01 +0200 Subject: [PATCH 50/91] try another gcc option for ubuntu 16, one fix in fapi p7 --- cmake_targets/CMakeLists.txt | 59 +++++++++------------------ nfapi/open-nFAPI/nfapi/src/nfapi_p7.c | 2 +- 2 files changed, 21 insertions(+), 40 deletions(-) diff --git a/cmake_targets/CMakeLists.txt b/cmake_targets/CMakeLists.txt index 40c357c5c3..bb1cc36193 100644 --- a/cmake_targets/CMakeLists.txt +++ b/cmake_targets/CMakeLists.txt @@ -309,48 +309,39 @@ if (CMAKE_SYSTEM_PROCESSOR MATCHES "x86") endif() # -set(CMAKE_C_FLAGS - "${CMAKE_C_FLAGS} ${C_FLAGS_PROCESSOR} -pipe -std=gnu99 -Wall -Wstrict-prototypes -fno-strict-aliasing -rdynamic -funroll-loops -Wno-packed-bitfield-compat -fPIC") # add autotools definitions that were maybe used! +set(legacyAutoTools "-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") + +set(CMAKE_C_FLAGS + "${CMAKE_C_FLAGS} ${C_FLAGS_PROCESSOR} -pipe -std=gnu99 -Wall -Wstrict-prototypes -fno-strict-aliasing -rdynamic -funroll-loops -Wno-packed-bitfield-compat -fPIC ${legacyAutoTools}" ) +set(CUDA_CMAKE_CXX_FLAGS + "${CMAKE_CXX_FLAGS} ${C_FLAGS_PROCESSOR} -Wno-packed-bitfield-compat -fPIC -Wall -fno-strict-aliasing -rdynamic -std=c++11") + +set(MKVER "'MAKE_VERSION(a,b,c)=((a)*256+(b)*16+c)'") +set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -D${MKVER} " ) +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -D${MKVER} " ) + if (CUDA_FOUND) - set(MKVER "'MAKE_VERSION(a,b,c)=((a)*256+(b)*16+c)'") - set(CUDA_CMAKE_C_FLAGS - "${CMAKE_C_FLAGS} -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 -D CUDA_FLAG" - ) - set(CUDA_CMAKE_CXX_FLAGS - "${CMAKE_CXX_FLAGS} ${C_FLAGS_PROCESSOR} -Wno-packed-bitfield-compat -fPIC -Wall -fno-strict-aliasing -rdynamic -std=c++11 -D CUDA_FLAG" - ) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -D CUDA_FLAG" ) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -D CUDA_FLAG" ) +endif() - set(CMAKE_C_FLAGS - "${CMAKE_C_FLAGS} -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 -D${MKVER} -D CUDA_FLAG" - ) - set(CMAKE_CXX_FLAGS - "${CMAKE_CXX_FLAGS} ${C_FLAGS_PROCESSOR} -Wno-packed-bitfield-compat -fPIC -Wall -fno-strict-aliasing -rdynamic -std=c++11 -D${MKVER} -D CUDA_FLAG" - ) -else (CUDA_FOUND) - set(MKVER "'MAKE_VERSION(a,b,c)=((a)*256+(b)*16+c)'") - set(CMAKE_C_FLAGS - "${CMAKE_C_FLAGS} -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 -D${MKVER}" - ) - set(CMAKE_CXX_FLAGS - "${CMAKE_CXX_FLAGS} ${C_FLAGS_PROCESSOR} -Wno-packed-bitfield-compat -fPIC -Wall -fno-strict-aliasing -rdynamic -std=c++11 -D${MKVER}" - ) -endif () if (SANITIZE_ADDRESS) - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=address -fno-common") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address -fno-common") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=address -fno-common") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address -fno-common") endif () add_definitions("-DASN_DISABLE_OER_SUPPORT") ######################### -set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,-rpath -Wl,${CMAKE_CURRENT_BINARY_DIR}") +set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -ggdb3 -Wl,-rpath -Wl,${CMAKE_CURRENT_BINARY_DIR}") ######################### # set a flag for changes in the source code # these changes are related to hardcoded path to include .h files -set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS} -ggdb3 -ggnu-pubnames -fvar-tracking-assignments -feliminate-dwarf2-dups -Og -DMALLOC_CHECK_=3") -set(CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS} -ggdb3 -ggnu-pubnames -fvar-tracking-assignments -feliminate-dwarf2-dups -DMALLOC_CHECK_=3 -O2 -fno-delete-null-pointer-checks") +set(debOpt "-ggdb3 -feliminate-dwarf2-dups -DMALLOC_CHECK_=3 -fno-delete-null-pointer-checks") +set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS} ${debOpt} -Og") +set(CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS} ${debOpt} -O2") set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS} -O3") set(GIT_BRANCH "UNKNOWN") @@ -3201,14 +3192,6 @@ target_link_libraries(smallblocktest m pthread ${ATLAS_LIBRARIES} dl ) - -# temp_C_flag = CMAKE_C_FLAGS -#set(CMAKE_C_FLAGS " ") -set (TEMP_C_FLAG ${CMAKE_C_FLAGS}) -set (CMAKE_C_FLAGS ${CUDA_CMAKE_C_FLAGS}) - -set (TEMP_CXX_FLAG ${CMAKE_CXX_FLAGS}) -set (CMAKE_CXX_FLAGS ${CUDA_CMAKE_CXX_FLAGS}) if (CUDA_FOUND) ################################################### # For CUDA library @@ -3239,8 +3222,6 @@ else (CUDA_FOUND) ) endif () -set (CMAKE_C_FLAGS ${TEMP_C_FLAG}) -set (CMAKE_CXX_FLAGS ${TEMP_CXX_FLAG}) # add_executable(ldpctest diff --git a/nfapi/open-nFAPI/nfapi/src/nfapi_p7.c b/nfapi/open-nFAPI/nfapi/src/nfapi_p7.c index 75a7c85bdf..9e9c9d5496 100644 --- a/nfapi/open-nFAPI/nfapi/src/nfapi_p7.c +++ b/nfapi/open-nFAPI/nfapi/src/nfapi_p7.c @@ -2656,7 +2656,7 @@ static uint8_t pack_cqi_indication_body_value(void *tlv, uint8_t **ppWritePacked static uint8_t pack_cqi_indication(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t *config) { nfapi_cqi_indication_t *pNfapiMsg = (nfapi_cqi_indication_t *)msg; //Fixme: allocate some mem to fix pure bug, need to find out proper size - pNfapiMsg->vendor_extension=(nfapi_vendor_extension_tlv_t)malloc( sizeof(* pNfapiMsg->vendor_extension)); + pNfapiMsg->vendor_extension=NULL;//(nfapi_vendor_extension_tlv_t)malloc( sizeof(* pNfapiMsg->vendor_extension)); return ( push16(pNfapiMsg->sfn_sf, ppWritePackedMsg, end) && pack_tlv(NFAPI_CQI_INDICATION_BODY_TAG, &pNfapiMsg->cqi_indication_body, ppWritePackedMsg, end, pack_cqi_indication_body_value) && pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); From 654e37cdb122770491ceab8313e463f0085b5c7e Mon Sep 17 00:00:00 2001 From: Laurent Thomas Date: Fri, 23 Jul 2021 23:12:07 +0200 Subject: [PATCH 51/91] try another (second trial) gcc option for ubuntu 16 --- cmake_targets/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake_targets/CMakeLists.txt b/cmake_targets/CMakeLists.txt index bb1cc36193..30b2aadde7 100644 --- a/cmake_targets/CMakeLists.txt +++ b/cmake_targets/CMakeLists.txt @@ -339,7 +339,7 @@ set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -ggdb3 -Wl,-rpath -Wl,${C ######################### # set a flag for changes in the source code # these changes are related to hardcoded path to include .h files -set(debOpt "-ggdb3 -feliminate-dwarf2-dups -DMALLOC_CHECK_=3 -fno-delete-null-pointer-checks") +set(debOpt "-ggdb3 -DMALLOC_CHECK_=3 -fno-delete-null-pointer-checks") set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS} ${debOpt} -Og") set(CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS} ${debOpt} -O2") set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS} -O3") From de4676dde1c9ad518212a1fda0fd7b3a615c68b7 Mon Sep 17 00:00:00 2001 From: francescomani Date: Tue, 22 Jun 2021 13:32:12 +0200 Subject: [PATCH 52/91] reworking UL antenna port definitions at gNB --- openair1/PHY/INIT/nr_init.c | 35 +++++++++++-------- openair1/PHY/INIT/nr_parms.c | 3 +- .../PHY/NR_ESTIMATION/nr_measurements_gNB.c | 4 +-- .../NR_ESTIMATION/nr_ul_channel_estimation.c | 3 +- openair1/PHY/NR_ESTIMATION/nr_ul_estimation.h | 2 +- .../PHY/NR_TRANSPORT/nr_transport_proto.h | 2 ++ .../PHY/NR_TRANSPORT/nr_ulsch_demodulation.c | 30 ++++++++-------- openair1/SCHED_NR/phy_procedures_nr_gNB.c | 12 +++---- 8 files changed, 50 insertions(+), 41 deletions(-) diff --git a/openair1/PHY/INIT/nr_init.c b/openair1/PHY/INIT/nr_init.c index dcff18f025..df4cb850e1 100644 --- a/openair1/PHY/INIT/nr_init.c +++ b/openair1/PHY/INIT/nr_init.c @@ -121,6 +121,7 @@ int phy_init_nr_gNB(PHY_VARS_gNB *gNB, int i; int Ptx=cfg->carrier_config.num_tx_ant.value; int Prx=cfg->carrier_config.num_rx_ant.value; + int max_ul_mimo_layers = 4; AssertFatal(Ptx>0 && Ptx<9,"Ptx %d is not supported\n",Ptx); AssertFatal(Prx>0 && Prx<9,"Prx %d is not supported\n",Prx); @@ -295,27 +296,30 @@ int phy_init_nr_gNB(PHY_VARS_gNB *gNB, init_prach_list(gNB); int N_RB_UL = cfg->carrier_config.ul_grid_size[cfg->ssb_config.scs_common.value].value; + int n_buf = Prx*max_ul_mimo_layers; for (int ULSCH_id=0; ULSCH_idnumber_of_nr_ulsch_max; ULSCH_id++) { pusch_vars[ULSCH_id] = (NR_gNB_PUSCH *)malloc16_clear( sizeof(NR_gNB_PUSCH) ); pusch_vars[ULSCH_id]->rxdataF_ext = (int32_t **)malloc16(Prx*sizeof(int32_t *) ); pusch_vars[ULSCH_id]->rxdataF_ext2 = (int32_t **)malloc16(Prx*sizeof(int32_t *) ); - pusch_vars[ULSCH_id]->ul_ch_estimates = (int32_t **)malloc16(Prx*sizeof(int32_t *) ); - pusch_vars[ULSCH_id]->ul_ch_estimates_ext = (int32_t **)malloc16(Prx*sizeof(int32_t *) ); - pusch_vars[ULSCH_id]->ul_ch_ptrs_estimates = (int32_t **)malloc16(Prx*sizeof(int32_t *) ); - pusch_vars[ULSCH_id]->ul_ch_ptrs_estimates_ext = (int32_t **)malloc16(Prx*sizeof(int32_t *) ); - pusch_vars[ULSCH_id]->ptrs_phase_per_slot = (int32_t **)malloc16(Prx*sizeof(int32_t *) ); - pusch_vars[ULSCH_id]->ul_ch_estimates_time = (int32_t **)malloc16(Prx*sizeof(int32_t *) ); - pusch_vars[ULSCH_id]->rxdataF_comp = (int32_t **)malloc16(Prx*sizeof(int32_t *) ); - pusch_vars[ULSCH_id]->ul_ch_mag0 = (int32_t **)malloc16(Prx*sizeof(int32_t *) ); - pusch_vars[ULSCH_id]->ul_ch_magb0 = (int32_t **)malloc16(Prx*sizeof(int32_t *) ); - pusch_vars[ULSCH_id]->ul_ch_mag = (int32_t **)malloc16(Prx*sizeof(int32_t *) ); - pusch_vars[ULSCH_id]->ul_ch_magb = (int32_t **)malloc16(Prx*sizeof(int32_t *) ); - pusch_vars[ULSCH_id]->rho = (int32_t **)malloc16_clear(Prx*sizeof(int32_t*) ); + pusch_vars[ULSCH_id]->ul_ch_estimates = (int32_t **)malloc16(n_buf*sizeof(int32_t *) ); + pusch_vars[ULSCH_id]->ul_ch_estimates_ext = (int32_t **)malloc16(n_buf*sizeof(int32_t *) ); + pusch_vars[ULSCH_id]->ul_ch_ptrs_estimates = (int32_t **)malloc16(n_buf*sizeof(int32_t *) ); + pusch_vars[ULSCH_id]->ul_ch_ptrs_estimates_ext = (int32_t **)malloc16(n_buf*sizeof(int32_t *) ); + pusch_vars[ULSCH_id]->ptrs_phase_per_slot = (int32_t **)malloc16(n_buf*sizeof(int32_t *) ); + pusch_vars[ULSCH_id]->ul_ch_estimates_time = (int32_t **)malloc16(n_buf*sizeof(int32_t *) ); + pusch_vars[ULSCH_id]->rxdataF_comp = (int32_t **)malloc16(n_buf*sizeof(int32_t *) ); + pusch_vars[ULSCH_id]->ul_ch_mag0 = (int32_t **)malloc16(n_buf*sizeof(int32_t *) ); + pusch_vars[ULSCH_id]->ul_ch_magb0 = (int32_t **)malloc16(n_buf*sizeof(int32_t *) ); + pusch_vars[ULSCH_id]->ul_ch_mag = (int32_t **)malloc16(n_buf*sizeof(int32_t *) ); + pusch_vars[ULSCH_id]->ul_ch_magb = (int32_t **)malloc16(n_buf*sizeof(int32_t *) ); + pusch_vars[ULSCH_id]->rho = (int32_t **)malloc16_clear(n_buf*sizeof(int32_t*) ); for (i=0; irxdataF_ext[i] = (int32_t *)malloc16_clear( sizeof(int32_t)*N_RB_UL*12*fp->symbols_per_slot ); pusch_vars[ULSCH_id]->rxdataF_ext2[i] = (int32_t *)malloc16_clear( sizeof(int32_t)*N_RB_UL*12*fp->symbols_per_slot ); + } + for (i=0; iul_ch_estimates[i] = (int32_t *)malloc16_clear( sizeof(int32_t)*fp->ofdm_symbol_size*2*fp->symbols_per_slot ); pusch_vars[ULSCH_id]->ul_ch_estimates_ext[i] = (int32_t *)malloc16_clear( sizeof(int32_t)*N_RB_UL*12*fp->symbols_per_slot ); pusch_vars[ULSCH_id]->ul_ch_estimates_time[i] = (int32_t *)malloc16_clear( 2*sizeof(int32_t)*fp->ofdm_symbol_size ); @@ -341,7 +345,7 @@ int phy_init_nr_gNB(PHY_VARS_gNB *gNB, void phy_free_nr_gNB(PHY_VARS_gNB *gNB) { - //NR_DL_FRAME_PARMS* const fp = &gNB->frame_parms; + NR_DL_FRAME_PARMS* const fp = &gNB->frame_parms; NR_gNB_COMMON *const common_vars = &gNB->common_vars; NR_gNB_PUSCH **const pusch_vars = gNB->pusch_vars; /*LTE_eNB_SRS *const srs_vars = gNB->srs_vars; @@ -382,9 +386,11 @@ void phy_free_nr_gNB(PHY_VARS_gNB *gNB) free_and_zero(prach_vars->rxsigF[0]); */ for (int ULSCH_id=0; ULSCH_idnumber_of_nr_ulsch_max; ULSCH_id++) { - for (int i = 0; i < 2; i++) { + for (int i = 0; i < fp->nb_antennas_rx; i++) { free_and_zero(pusch_vars[ULSCH_id]->rxdataF_ext[i]); free_and_zero(pusch_vars[ULSCH_id]->rxdataF_ext2[i]); + } + for (int i = 0; i < 4*fp->nb_antennas_rx; i++) { free_and_zero(pusch_vars[ULSCH_id]->ul_ch_estimates[i]); free_and_zero(pusch_vars[ULSCH_id]->ul_ch_estimates_ext[i]); free_and_zero(pusch_vars[ULSCH_id]->ul_ch_estimates_time[i]); @@ -398,7 +404,6 @@ void phy_free_nr_gNB(PHY_VARS_gNB *gNB) free_and_zero(pusch_vars[ULSCH_id]->ul_ch_magb[i]); free_and_zero(pusch_vars[ULSCH_id]->rho[i]); } - free_and_zero(pusch_vars[ULSCH_id]->rxdataF_ext); free_and_zero(pusch_vars[ULSCH_id]->rxdataF_ext2); free_and_zero(pusch_vars[ULSCH_id]->ul_ch_estimates); diff --git a/openair1/PHY/INIT/nr_parms.c b/openair1/PHY/INIT/nr_parms.c index 3a9d8a6c18..dab280de26 100644 --- a/openair1/PHY/INIT/nr_parms.c +++ b/openair1/PHY/INIT/nr_parms.c @@ -198,9 +198,8 @@ int nr_init_frame_parms(nfapi_nr_config_request_scf_t* cfg, fp->slots_per_frame = 10* fp->slots_per_subframe; - fp->nb_antenna_ports_gNB = 1; // It corresponds to the number of common antenna ports fp->nb_antennas_rx = cfg->carrier_config.num_rx_ant.value; // It denotes the number of rx antennas at gNB - fp->nb_antennas_tx = cfg->carrier_config.num_tx_ant.value; // It corresponds to pdsch_AntennaPorts + fp->nb_antennas_tx = cfg->carrier_config.num_tx_ant.value; // It corresponds to pdsch_AntennaPorts (logical antenna ports) fp->symbols_per_slot = ((Ncp == NORMAL)? 14 : 12); // to redefine for different slot formats fp->samples_per_subframe_wCP = fp->ofdm_symbol_size * fp->symbols_per_slot * fp->slots_per_subframe; diff --git a/openair1/PHY/NR_ESTIMATION/nr_measurements_gNB.c b/openair1/PHY/NR_ESTIMATION/nr_measurements_gNB.c index 91b6a59248..a162001e0a 100644 --- a/openair1/PHY/NR_ESTIMATION/nr_measurements_gNB.c +++ b/openair1/PHY/NR_ESTIMATION/nr_measurements_gNB.c @@ -149,7 +149,7 @@ void gNB_I0_measurements(PHY_VARS_gNB *gNB,int first_symb,int num_symb) { // // Todo: // - averaging IIR filter for RX power and noise -void nr_gnb_measurements(PHY_VARS_gNB *gNB, uint8_t ulsch_id, unsigned char harq_pid, unsigned char symbol){ +void nr_gnb_measurements(PHY_VARS_gNB *gNB, uint8_t ulsch_id, unsigned char harq_pid, unsigned char symbol, uint8_t nrOfLayers){ int rx_power_tot[NUMBER_OF_NR_ULSCH_MAX]; int rx_power[NUMBER_OF_NR_ULSCH_MAX][NB_ANTENNAS_RX]; @@ -169,7 +169,7 @@ void nr_gnb_measurements(PHY_VARS_gNB *gNB, uint8_t ulsch_id, unsigned char harq rx_power[ulsch_id][aarx] = 0; - for (int aatx = 0; aatx < fp->nb_antennas_tx; aatx++){ + for (int aatx = 0; aatx < nrOfLayers; aatx++){ meas->rx_spatial_power[ulsch_id][aatx][aarx] = (signal_energy_nodc(&gNB->pusch_vars[ulsch_id]->ul_ch_estimates[aarx][ch_offset], N_RB_UL * NR_NB_SC_PER_RB)); diff --git a/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c b/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c index 5e1528c922..4495425a6c 100644 --- a/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c +++ b/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c @@ -130,7 +130,8 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB, //------------------generate DMRS------------------// if (pusch_pdu->transform_precoding == transform_precoder_disabled) { - nr_pusch_dmrs_rx(gNB, Ns, gNB->nr_gold_pusch_dmrs[pusch_pdu->scid][Ns][symbol], &pilot[0], 1000, 0, nb_rb_pusch, (pusch_pdu->bwp_start + pusch_pdu->rb_start)*NR_NB_SC_PER_RB, pusch_pdu->dmrs_config_type); + nr_pusch_dmrs_rx(gNB, Ns, gNB->nr_gold_pusch_dmrs[pusch_pdu->scid][Ns][symbol], &pilot[0], 1000, 0, nb_rb_pusch, + (pusch_pdu->bwp_start + pusch_pdu->rb_start)*NR_NB_SC_PER_RB, pusch_pdu->dmrs_config_type); } else { // if transform precoding or SC-FDMA is enabled in Uplink diff --git a/openair1/PHY/NR_ESTIMATION/nr_ul_estimation.h b/openair1/PHY/NR_ESTIMATION/nr_ul_estimation.h index 89bb5b2807..c8e02fd13d 100644 --- a/openair1/PHY/NR_ESTIMATION/nr_ul_estimation.h +++ b/openair1/PHY/NR_ESTIMATION/nr_ul_estimation.h @@ -51,7 +51,7 @@ void dump_nr_I0_stats(FILE *fd,PHY_VARS_gNB *gNB); void gNB_I0_measurements(PHY_VARS_gNB *gNB,int first_symb,int num_symb); -void nr_gnb_measurements(PHY_VARS_gNB *gNB, uint8_t ulsch_id, unsigned char harq_pid, unsigned char symbol); +void nr_gnb_measurements(PHY_VARS_gNB *gNB, uint8_t ulsch_id, unsigned char harq_pid, unsigned char symbol, uint8_t nrOfLayers); int nr_est_timing_advance_pusch(PHY_VARS_gNB* phy_vars_gNB, int UE_id); diff --git a/openair1/PHY/NR_TRANSPORT/nr_transport_proto.h b/openair1/PHY/NR_TRANSPORT/nr_transport_proto.h index 994ff18bc8..192c21216b 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_transport_proto.h +++ b/openair1/PHY/NR_TRANSPORT/nr_transport_proto.h @@ -178,6 +178,7 @@ void nr_ulsch_channel_level(int **ul_ch_estimates_ext, int32_t *avg, uint8_t symbol, uint32_t len, + uint8_t nrOfLayers, unsigned short nb_rb); /** \brief This function performs channel compensation (matched filtering) on the received RBs for this allocation. In addition, it computes the squared-magnitude of the channel with weightings for 16QAM/64QAM detection as well as dual-stream detection (cross-correlation) @@ -202,6 +203,7 @@ void nr_ulsch_channel_compensation(int **rxdataF_ext, unsigned char symbol, uint8_t is_dmrs_symbol, unsigned char mod_order, + uint8_t nrOfLayers, unsigned short nb_rb, unsigned char output_shift); diff --git a/openair1/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c b/openair1/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c index 7a4555d254..6a69b45276 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c +++ b/openair1/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c @@ -467,6 +467,7 @@ void nr_ulsch_channel_level(int **ul_ch_estimates_ext, int32_t *avg, uint8_t symbol, uint32_t len, + uint8_t nrOfLayers, unsigned short nb_rb) { @@ -474,7 +475,6 @@ void nr_ulsch_channel_level(int **ul_ch_estimates_ext, short rb; unsigned char aatx, aarx; - char nb_antennas_ue_tx = 1; __m128i *ul_ch128, avg128U; int16_t x = factor2(len); @@ -486,7 +486,7 @@ void nr_ulsch_channel_level(int **ul_ch_estimates_ext, int off = 0; #endif - for (aatx = 0; aatx < nb_antennas_ue_tx; aatx++) + for (aatx = 0; aatx < nrOfLayers; aatx++) for (aarx = 0; aarx < frame_parms->nb_antennas_rx; aarx++) { //clear average level avg128U = _mm_setzero_si128(); @@ -519,7 +519,7 @@ void nr_ulsch_channel_level(int **ul_ch_estimates_ext, symbol_mod = (symbol>=(7-frame_parms->Ncp)) ? symbol-(7-frame_parms->Ncp) : symbol; - for (aatx=0; aatxnb_antenna_ports_gNB; aatx++) { + for (aatx=0; aatxnb_antennas_rx; aarx++) { //clear average level avg128U = vdupq_n_s32(0); @@ -535,7 +535,7 @@ void nr_ulsch_channel_level(int **ul_ch_estimates_ext, avg128U = vqaddq_s32(avg128U, vmull_s16(ul_ch128[2], ul_ch128[2])); avg128U = vqaddq_s32(avg128U, vmull_s16(ul_ch128[3], ul_ch128[3])); - if (((symbol_mod == 0) || (symbol_mod == (frame_parms->Ncp-1)))&&(frame_parms->nb_antenna_ports_gNB!=1)) { + if (((symbol_mod == 0) || (symbol_mod == (frame_parms->Ncp-1)))&&(nrOfLayers!=1)) { ul_ch128+=4; } else { avg128U = vqaddq_s32(avg128U, vmull_s16(ul_ch128[4], ul_ch128[4])); @@ -576,6 +576,7 @@ void nr_ulsch_channel_compensation(int **rxdataF_ext, unsigned char symbol, uint8_t is_dmrs_symbol, unsigned char mod_order, + uint8_t nrOfLayers, unsigned short nb_rb, unsigned char output_shift) { @@ -627,12 +628,11 @@ void nr_ulsch_channel_compensation(int **rxdataF_ext, unsigned short rb; unsigned char aatx,aarx; - char nb_antennas_ue_tx = 1; __m128i *ul_ch128,*ul_ch128_2,*ul_ch_mag128,*ul_ch_mag128b,*rxdataF128,*rxdataF_comp128,*rho128; __m128i mmtmpD0,mmtmpD1,mmtmpD2,mmtmpD3,QAM_amp128,QAM_amp128b; QAM_amp128b = _mm_setzero_si128(); - for (aatx=0; aatx=(7-frame_parms->Ncp)) ? symbol-(7-frame_parms->Ncp) : symbol; if ((symbol_mod == 0) || (symbol_mod == (4-frame_parms->Ncp))) { - if (frame_parms->nb_antenna_ports_gNB==1) { // 10 out of 12 so don't reduce size + if (nrOfLayers==1) { // 10 out of 12 so don't reduce size nb_rb=1+(5*nb_rb/6); } else { @@ -892,7 +892,7 @@ void nr_ulsch_channel_compensation(int **rxdataF_ext, } } - for (aatx=0; aatxnb_antenna_ports_gNB; aatx++) { + for (aatx=0; aatxframe_parms; nfapi_nr_pusch_pdu_t *rel15_ul = &gNB->ulsch[ulsch_id][0]->harq_processes[harq_pid]->ulsch_pdu; + int avg[frame_parms->nb_antennas_rx*rel15_ul->nrOfLayers]; gNB->pusch_vars[ulsch_id]->dmrs_symbol = INVALID_VALUE; gNB->pusch_vars[ulsch_id]->cl_done = 0; @@ -1188,7 +1188,7 @@ int nr_rx_pusch(PHY_VARS_gNB *gNB, if (dmrs_symbol_flag == 1) { if (gNB->pusch_vars[ulsch_id]->dmrs_symbol == INVALID_VALUE) gNB->pusch_vars[ulsch_id]->dmrs_symbol = symbol; - +z nr_pusch_channel_estimation(gNB, slot, 0, // p @@ -1197,7 +1197,7 @@ int nr_rx_pusch(PHY_VARS_gNB *gNB, bwp_start_subcarrier, rel15_ul); - nr_gnb_measurements(gNB, ulsch_id, harq_pid, symbol); + nr_gnb_measurements(gNB, ulsch_id, harq_pid, symbol,rel15_ul->nrOfLayers); for (aarx = 0; aarx < frame_parms->nb_antennas_rx; aarx++) { if (symbol == rel15_ul->start_symbol_index) { @@ -1278,11 +1278,12 @@ int nr_rx_pusch(PHY_VARS_gNB *gNB, avg, symbol, nb_re_pusch, + rel15_ul->nrOfLayers, rel15_ul->rb_size); avgs = 0; - for (aatx=0;aatxnrOfLayers;aatx++) for (aarx=0;aarxnb_antennas_rx;aarx++) avgs = cmax(avgs,avg[(aatx<<1)+aarx]); @@ -1299,11 +1300,12 @@ int nr_rx_pusch(PHY_VARS_gNB *gNB, gNB->pusch_vars[ulsch_id]->ul_ch_mag0, gNB->pusch_vars[ulsch_id]->ul_ch_magb0, gNB->pusch_vars[ulsch_id]->rxdataF_comp, - (nb_antennas_ue_tx>1) ? gNB->pusch_vars[ulsch_id]->rho : NULL, + (rel15_ul->nrOfLayers>1) ? gNB->pusch_vars[ulsch_id]->rho : NULL, frame_parms, symbol, dmrs_symbol_flag, rel15_ul->qam_mod_order, + rel15_ul->nrOfLayers, rel15_ul->rb_size, gNB->pusch_vars[ulsch_id]->log2_maxh); stop_meas(&gNB->ulsch_channel_compensation_stats); diff --git a/openair1/SCHED_NR/phy_procedures_nr_gNB.c b/openair1/SCHED_NR/phy_procedures_nr_gNB.c index 550d4c8e31..009e16e6ef 100644 --- a/openair1/SCHED_NR/phy_procedures_nr_gNB.c +++ b/openair1/SCHED_NR/phy_procedures_nr_gNB.c @@ -557,8 +557,8 @@ int phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx) { NR_gNB_PUCCH_t *pucch = gNB->pucch[i]; if (pucch) { if ((pucch->active == 1) && - (pucch->frame == frame_rx) && - (pucch->slot == slot_rx) ) { + (pucch->frame == frame_rx) && + (pucch->slot == slot_rx) ) { pucch_decode_done = 1; @@ -579,7 +579,7 @@ int phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx) { LOG_D(PHY,"frame %d, slot %d: PUCCH signal energy %d\n",frame_rx,slot_rx,power_rxF); nr_decode_pucch0(gNB, - frame_rx, + frame_rx, slot_rx, uci_pdu_format0, pucch_pdu); @@ -621,9 +621,9 @@ int phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx) { (ulsch->rnti > 0)) { // for for an active HARQ process for (harq_pid=0;harq_pidharq_processes[harq_pid]; - AssertFatal(ulsch_harq!=NULL,"harq_pid %d is not allocated\n",harq_pid); - if ((ulsch_harq->status == NR_ACTIVE) && + ulsch_harq = ulsch->harq_processes[harq_pid]; + AssertFatal(ulsch_harq!=NULL,"harq_pid %d is not allocated\n",harq_pid); + if ((ulsch_harq->status == NR_ACTIVE) && (ulsch_harq->frame == frame_rx) && (ulsch_harq->slot == slot_rx) && (ulsch_harq->handled == 0)){ From 0f4e765991eb1b91662c45fcd6a7c639573253fc Mon Sep 17 00:00:00 2001 From: francescomani Date: Sat, 24 Jul 2021 16:20:54 +0200 Subject: [PATCH 53/91] add get_dmrs_port function for ul --- common/utils/nr/nr_common.c | 20 +++++++++++++++++++ common/utils/nr/nr_common.h | 2 +- .../PHY/NR_TRANSPORT/nr_ulsch_demodulation.c | 2 +- 3 files changed, 22 insertions(+), 2 deletions(-) diff --git a/common/utils/nr/nr_common.c b/common/utils/nr/nr_common.c index cc2860191a..9e4869035a 100644 --- a/common/utils/nr/nr_common.c +++ b/common/utils/nr/nr_common.c @@ -196,6 +196,26 @@ uint32_t nr_get_code_rate(uint8_t Imcs, uint8_t table_idx) { } } + +int get_dmrs_port(int nl, uint16_t dmrs_ports) { + + if (dmrs_ports == 0) return 0; // dci 1_0 + int p = -1; + int found = -1; + for (int i=0; i<12; i++) { // loop over dmrs ports + if((dmrs_ports>>i)&0x01) { // check if current bit is 1 + found++; + if (found == nl) { // found antenna port number corresponding to current layer + p = i; + break; + } + } + } + AssertFatal(p>-1,"No dmrs port corresponding to layer %d found\n",nl); + return p; +} + + int get_subband_size(int NPRB,int size) { // implements table 5.2.1.4-2 from 36.214 // diff --git a/common/utils/nr/nr_common.h b/common/utils/nr/nr_common.h index 6389c2c094..b95fdd5046 100644 --- a/common/utils/nr/nr_common.h +++ b/common/utils/nr/nr_common.h @@ -62,7 +62,7 @@ uint8_t nr_get_Qm(uint8_t Imcs, uint8_t table_idx); uint32_t nr_get_code_rate(uint8_t Imcs, uint8_t table_idx); int get_subband_size(int NPRB,int size); void SLIV2SL(int SLIV,int *S,int *L); - +int get_dmrs_port(int nl, uint16_t dmrs_ports); #define CEILIDIV(a,b) ((a+b-1)/b) #define ROUNDIDIV(a,b) (((a<<1)+b)/(b<<1)) diff --git a/openair1/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c b/openair1/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c index 6a69b45276..936d523244 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c +++ b/openair1/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c @@ -1188,7 +1188,7 @@ int nr_rx_pusch(PHY_VARS_gNB *gNB, if (dmrs_symbol_flag == 1) { if (gNB->pusch_vars[ulsch_id]->dmrs_symbol == INVALID_VALUE) gNB->pusch_vars[ulsch_id]->dmrs_symbol = symbol; -z + nr_pusch_channel_estimation(gNB, slot, 0, // p From f833ca474a5a8881b6ebfac7be76b95a6a1a2a46 Mon Sep 17 00:00:00 2001 From: francescomani Date: Mon, 28 Jun 2021 18:47:47 +0200 Subject: [PATCH 54/91] some more changes in ulsch structures --- .../PHY/NR_ESTIMATION/nr_measurements_gNB.c | 2 +- .../NR_ESTIMATION/nr_ul_channel_estimation.c | 8 +-- openair1/PHY/NR_TRANSPORT/nr_dlsch.c | 3 +- .../PHY/NR_TRANSPORT/nr_ulsch_demodulation.c | 54 ++++++++++--------- 4 files changed, 35 insertions(+), 32 deletions(-) diff --git a/openair1/PHY/NR_ESTIMATION/nr_measurements_gNB.c b/openair1/PHY/NR_ESTIMATION/nr_measurements_gNB.c index a162001e0a..e942ef2c6b 100644 --- a/openair1/PHY/NR_ESTIMATION/nr_measurements_gNB.c +++ b/openair1/PHY/NR_ESTIMATION/nr_measurements_gNB.c @@ -171,7 +171,7 @@ void nr_gnb_measurements(PHY_VARS_gNB *gNB, uint8_t ulsch_id, unsigned char harq for (int aatx = 0; aatx < nrOfLayers; aatx++){ - meas->rx_spatial_power[ulsch_id][aatx][aarx] = (signal_energy_nodc(&gNB->pusch_vars[ulsch_id]->ul_ch_estimates[aarx][ch_offset], N_RB_UL * NR_NB_SC_PER_RB)); + meas->rx_spatial_power[ulsch_id][aatx][aarx] = (signal_energy_nodc(&gNB->pusch_vars[ulsch_id]->ul_ch_estimates[aatx*fp->nb_antennas_rx+aarx][ch_offset], N_RB_UL * NR_NB_SC_PER_RB)); if (meas->rx_spatial_power[ulsch_id][aatx][aarx] < 0) { meas->rx_spatial_power[ulsch_id][aatx][aarx] = 0; diff --git a/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c b/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c index 4495425a6c..99523c06fd 100644 --- a/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c +++ b/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c @@ -172,7 +172,7 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB, pil = (int16_t *)&pilot[0]; rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+k+nushift)]; - ul_ch = (int16_t *)&ul_ch_estimates[aarx][ch_offset]; + ul_ch = (int16_t *)&ul_ch_estimates[p*gNB->frame_parms.nb_antennas_rx+aarx][ch_offset]; re_offset = k; memset(ul_ch,0,4*(gNB->frame_parms.ofdm_symbol_size)); @@ -371,7 +371,7 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB, // check if PRB crosses DC and improve estimates around DC if ((bwp_start_subcarrier < gNB->frame_parms.ofdm_symbol_size) && (bwp_start_subcarrier+nb_rb_pusch*12 >= gNB->frame_parms.ofdm_symbol_size)) { - ul_ch = (int16_t *)&ul_ch_estimates[aarx][ch_offset]; + ul_ch = (int16_t *)&ul_ch_estimates[p*gNB->frame_parms.nb_antennas_rx+aarx][ch_offset]; uint16_t idxDC = 2*(gNB->frame_parms.ofdm_symbol_size - bwp_start_subcarrier); uint16_t idxPil = idxDC/2; re_offset = k; @@ -422,7 +422,7 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB, } } #ifdef DEBUG_PUSCH - ul_ch = (int16_t *)&ul_ch_estimates[aarx][ch_offset]; + ul_ch = (int16_t *)&ul_ch_estimates[p*gNB->frame_parms.nb_antennas_rx+aarx][ch_offset]; for(uint16_t idxP=0; idxPframe_parms.nb_antennas_rx+aarx][ch_offset]; ul_ch_128[0] = _mm_slli_epi16 (ul_ch_128[0], 2); } diff --git a/openair1/PHY/NR_TRANSPORT/nr_dlsch.c b/openair1/PHY/NR_TRANSPORT/nr_dlsch.c index 03bd0ddf6c..b1bf32b790 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_dlsch.c +++ b/openair1/PHY/NR_TRANSPORT/nr_dlsch.c @@ -278,8 +278,9 @@ uint8_t nr_generate_pdsch(PHY_VARS_gNB *gNB, printf("PDSCH resource mapping started (start SC %d\tstart symbol %d\tN_PRB %d\tnb_re %d,nb_layers %d)\n", start_sc, rel15->StartSymbolIndex, rel15->rbSize, nb_re,rel15->nrOfLayers); #endif + for (int ap=0; apnrOfLayers; ap++) { - + // DMRS params for this ap get_Wt(Wt, ap, dmrs_Type); get_Wf(Wf, ap, dmrs_Type); diff --git a/openair1/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c b/openair1/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c index 936d523244..a153453347 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 "common/utils/nr/nr_common.h" //#define DEBUG_CH_COMP //#define DEBUG_RB_EXT @@ -491,7 +492,7 @@ void nr_ulsch_channel_level(int **ul_ch_estimates_ext, //clear average level avg128U = _mm_setzero_si128(); - ul_ch128=(__m128i *)&ul_ch_estimates_ext[(aatx<<1)+aarx][symbol*(off+(nb_rb*12))]; + ul_ch128=(__m128i *)&ul_ch_estimates_ext[aatx*frame_parms->nb_antennas_rx+aarx][symbol*(off+(nb_rb*12))]; for (rb = 0; rb < len/12; rb++) { avg128U = _mm_add_epi32(avg128U, _mm_srai_epi32(_mm_madd_epi16(ul_ch128[0], ul_ch128[0]), x)); @@ -500,10 +501,10 @@ void nr_ulsch_channel_level(int **ul_ch_estimates_ext, ul_ch128+=3; } - avg[(aatx<<1)+aarx] = (((int32_t*)&avg128U)[0] + - ((int32_t*)&avg128U)[1] + - ((int32_t*)&avg128U)[2] + - ((int32_t*)&avg128U)[3] ) / y; + avg[aatx*frame_parms->nb_antennas_rx+aarx] = (((int32_t*)&avg128U)[0] + + ((int32_t*)&avg128U)[1] + + ((int32_t*)&avg128U)[2] + + ((int32_t*)&avg128U)[3]) / y; } @@ -525,7 +526,7 @@ void nr_ulsch_channel_level(int **ul_ch_estimates_ext, avg128U = vdupq_n_s32(0); // 5 is always a symbol with no pilots for both normal and extended prefix - ul_ch128 = (int16x4_t *)&ul_ch_estimates_ext[(aatx<<1)+aarx][symbol*frame_parms->N_RB_UL*12]; + ul_ch128 = (int16x4_t *)&ul_ch_estimates_ext[aatx*frame_parms->nb_antennas_rx+aarx][symbol*frame_parms->N_RB_UL*12]; for (rb = 0; rb < nb_rb; rb++) { // printf("rb %d : ",rb); @@ -557,10 +558,10 @@ void nr_ulsch_channel_level(int **ul_ch_estimates_ext, else nre=12; - avg[(aatx<<1)+aarx] = (((int32_t*)&avg128U)[0] + - ((int32_t*)&avg128U)[1] + - ((int32_t*)&avg128U)[2] + - ((int32_t*)&avg128U)[3] ) / (nb_rb*nre); + avg[aatx*frame_parms->nb_antennas_rx+aarx] = (((int32_t*)&avg128U)[0] + + ((int32_t*)&avg128U)[1] + + ((int32_t*)&avg128U)[2] + + ((int32_t*)&avg128U)[3]) / (nb_rb*nre); } } #endif @@ -646,11 +647,11 @@ void nr_ulsch_channel_compensation(int **rxdataF_ext, for (aarx=0; aarxnb_antennas_rx; aarx++) { - ul_ch128 = (__m128i *)&ul_ch_estimates_ext[(aatx<<1)+aarx][symbol*(off+(nb_rb*12))]; - ul_ch_mag128 = (__m128i *)&ul_ch_mag[(aatx<<1)+aarx][symbol*(off+(nb_rb*12))]; - ul_ch_mag128b = (__m128i *)&ul_ch_magb[(aatx<<1)+aarx][symbol*(off+(nb_rb*12))]; + ul_ch128 = (__m128i *)&ul_ch_estimates_ext[aatx*frame_parms->nb_antennas_rx+aarx][symbol*(off+(nb_rb*12))]; + ul_ch_mag128 = (__m128i *)&ul_ch_mag[aatx*frame_parms->nb_antennas_rx+aarx][symbol*(off+(nb_rb*12))]; + ul_ch_mag128b = (__m128i *)&ul_ch_magb[aatx*frame_parms->nb_antennas_rx+aarx][symbol*(off+(nb_rb*12))]; rxdataF128 = (__m128i *)&rxdataF_ext[aarx][symbol*(off+(nb_rb*12))]; - rxdataF_comp128 = (__m128i *)&rxdataF_comp[(aatx<<1)+aarx][symbol*(off+(nb_rb*12))]; + rxdataF_comp128 = (__m128i *)&rxdataF_comp[aatx*frame_parms->nb_antennas_rx+aarx][symbol*(off+(nb_rb*12))]; for (rb=0; rbnb_antennas_rx; aarx++) { - ul_ch128 = (int16x4_t*)&ul_ch_estimates_ext[(aatx<<1)+aarx][symbol*frame_parms->N_RB_UL*12]; - ul_ch_mag128 = (int16x8_t*)&ul_ch_mag[(aatx<<1)+aarx][symbol*frame_parms->N_RB_UL*12]; - ul_ch_mag128b = (int16x8_t*)&ul_ch_magb[(aatx<<1)+aarx][symbol*frame_parms->N_RB_UL*12]; + ul_ch128 = (int16x4_t*)&ul_ch_estimates_ext[aatx*frame_parms->nb_antennas_rx+aarx][symbol*frame_parms->N_RB_UL*12]; + ul_ch_mag128 = (int16x8_t*)&ul_ch_mag[aatx*frame_parms->nb_antennas_rx+aarx][symbol*frame_parms->N_RB_UL*12]; + ul_ch_mag128b = (int16x8_t*)&ul_ch_magb[aatx*frame_parms->nb_antennas_rx+aarx][symbol*frame_parms->N_RB_UL*12]; rxdataF128 = (int16x4_t*)&rxdataF_ext[aarx][symbol*frame_parms->N_RB_UL*12]; - rxdataF_comp128 = (int16x4x2_t*)&rxdataF_comp[(aatx<<1)+aarx][symbol*frame_parms->N_RB_UL*12]; + rxdataF_comp128 = (int16x4x2_t*)&rxdataF_comp[aatx*frame_parms->nb_antennas_rx+aarx][symbol*frame_parms->N_RB_UL*12]; for (rb=0; rb2) { @@ -1189,13 +1190,14 @@ int nr_rx_pusch(PHY_VARS_gNB *gNB, if (gNB->pusch_vars[ulsch_id]->dmrs_symbol == INVALID_VALUE) gNB->pusch_vars[ulsch_id]->dmrs_symbol = symbol; - nr_pusch_channel_estimation(gNB, - slot, - 0, // p - symbol, - ulsch_id, - bwp_start_subcarrier, - rel15_ul); + for (int nl=0; nlnrOfLayers; nl++) + nr_pusch_channel_estimation(gNB, + slot, + get_dmrs_port(nl,rel15_ul->dmrs_ports), + symbol, + ulsch_id, + bwp_start_subcarrier, + rel15_ul); nr_gnb_measurements(gNB, ulsch_id, harq_pid, symbol,rel15_ul->nrOfLayers); @@ -1285,7 +1287,7 @@ int nr_rx_pusch(PHY_VARS_gNB *gNB, for (aatx=0;aatxnrOfLayers;aatx++) for (aarx=0;aarxnb_antennas_rx;aarx++) - avgs = cmax(avgs,avg[(aatx<<1)+aarx]); + avgs = cmax(avgs,avg[aatx*frame_parms->nb_antennas_rx+aarx]); gNB->pusch_vars[ulsch_id]->log2_maxh = (log2_approx(avgs)/2)+3; gNB->pusch_vars[ulsch_id]->cl_done = 1; From 754e8e304316026c24581eefa08f0f70cb3a4080 Mon Sep 17 00:00:00 2001 From: Laurent OpenCells Date: Sun, 25 Jul 2021 13:52:01 +0200 Subject: [PATCH 55/91] CMakeList cleanup,improvement and trial to run in ubuntu 16 --- cmake_targets/CMakeLists.txt | 527 ++++++++++---------- openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c | 10 +- openair2/PHY_INTERFACE/mac_phy_primitives.c | 283 ----------- openair2/PHY_INTERFACE/mac_phy_primitives.h | 232 --------- openair2/RRC/LTE/rrc_eNB.c | 3 - 5 files changed, 259 insertions(+), 796 deletions(-) delete mode 100644 openair2/PHY_INTERFACE/mac_phy_primitives.c delete mode 100644 openair2/PHY_INTERFACE/mac_phy_primitives.h diff --git a/cmake_targets/CMakeLists.txt b/cmake_targets/CMakeLists.txt index bb1cc36193..a8c33139d9 100644 --- a/cmake_targets/CMakeLists.txt +++ b/cmake_targets/CMakeLists.txt @@ -89,8 +89,8 @@ if ("${NETTLE_VERSION_MAJOR}" STREQUAL "" OR "${NETTLE_VERSION_MINOR}" STREQUAL message( FATAL_ERROR "The nettle version not detected properly. Try to run build_oai -I again" ) endif() -add_definitions("-DNETTLE_VERSION_MAJOR=${NETTLE_VERSION_MAJOR}") -add_definitions("-DNETTLE_VERSION_MINOR=${NETTLE_VERSION_MINOR}") +add_compile_definitions("NETTLE_VERSION_MAJOR=${NETTLE_VERSION_MAJOR}") +add_compile_definitions("NETTLE_VERSION_MINOR=${NETTLE_VERSION_MINOR}") pkg_search_module(XPM xpm) if(NOT ${XPM_FOUND}) @@ -124,13 +124,13 @@ if(EXISTS "/usr/include/atlas/cblas.h" OR EXISTS "/usr/include/cblas.h") # for ubuntu 17.10, directories are different elseif(EXISTS "/usr/include/x86_64-linux-gnu/cblas.h") - + include_directories("/usr/include/x86_64-linux-gnu") LINK_DIRECTORIES("/usr/lib/x86_64-linux-gnu") list(APPEND ATLAS_LIBRARIES cblas) list(APPEND ATLAS_LIBRARIES atlas) list(APPEND ATLAS_LIBRARIES lapack) - + else() message("No Blas/Atlas libs found, some targets will fail") endif() @@ -155,8 +155,6 @@ set (OPENAIR_BIN_DIR ${CMAKE_CURRENT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}) project (OpenAirInterface) - - ############################################## # Base CUDA setting ############################################## @@ -165,7 +163,7 @@ if (CUDA_FOUND) message ("cuda include ${CUDA_INCLUDE_DIRS}") message ("cuda library ${CUDA_LIBRARY_DIRS}") - add_definitions("-L/usr/local/cuda/lib64") + add_compile_definitions("-L/usr/local/cuda/lib64") SET(CUDA_NVCC_FLAGS "${CUDA_NVCC_FLAGS};-arch=sm_60;") @@ -192,7 +190,7 @@ macro(add_option name val helpstr) set(value ${val}) endif() set(${name} ${value} CACHE STRING "${helpstr}") - add_definitions("-D${name}=${value}") + add_compile_definitions("${name}=${value}") endmacro(add_option) macro(add_boolean_option name val helpstr) @@ -204,7 +202,7 @@ macro(add_boolean_option name val helpstr) set(${name} ${value} CACHE STRING "${helpstr}") set_property(CACHE ${name} PROPERTY TYPE BOOL) if (${value}) - add_definitions("-D${name}") + add_compile_definitions("${name}") endif (${value}) endmacro(add_boolean_option) @@ -215,7 +213,7 @@ macro(add_integer_option name val helpstr) set(value ${val}) endif() set(${name} ${value} CACHE STRING "${helpstr}") - add_definitions("-D${name}=${value}") + add_compile_definitions("${name}=${value}") endmacro(add_integer_option) macro(add_list1_option name val helpstr) @@ -227,7 +225,7 @@ macro(add_list1_option name val helpstr) set(${name} ${value} CACHE STRING "${helpstr}") set_property(CACHE ${name} PROPERTY STRINGS ${ARGN}) if(NOT "${value}" STREQUAL "False") - add_definitions("-D${name}=${value}") + add_compile_definitions("${name}=${value}") endif() endmacro(add_list1_option) @@ -240,7 +238,7 @@ macro(add_list2_option name val helpstr) set(${name} ${value} CACHE STRING "${helpstr}") set_property(CACHE ${name} PROPERTY STRINGS ${ARGN}) if(NOT "${value}" STREQUAL "False") - add_definitions("-D${value}=1") + add_compile_definitions("${value}=1") endif() endmacro(add_list2_option) @@ -253,7 +251,7 @@ macro(add_list_string_option name val helpstr) set(${name} ${value} CACHE STRING "${helpstr}") set_property(CACHE ${name} PROPERTY STRINGS ${ARGN}) if(NOT "${value}" STREQUAL "False") - add_definitions("-D${name}=\"${value}\"") + add_compile_definitions("${name}=\"${value}\"") endif() endmacro(add_list_string_option) @@ -310,39 +308,36 @@ endif() # # add autotools definitions that were maybe used! -set(legacyAutoTools "-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_compile_definitions(STDC_HEADERS=1 HAVE_SYS_TYPES_H=1 HAVE_SYS_STAT_H=1 HAVE_STRING_H=1 HAVE_MEMORY_H=1 HAVE_STRINGS_H=1 HAVE_INTTYPES_H=1 HAVE_STDINT_H=1 HAVE_UNISTD_H=1 HAVE_FCNTL_H=1 HAVE_ARPA_INET_H=1 HAVE_SYS_TIME_H=1 HAVE_SYS_SOCKET_H=1 HAVE_STRERROR=1 HAVE_SOCKET=1 HAVE_MEMSET=1 HAVE_GETTIMEOFDAY=1 HAVE_STDLIB_H=1 HAVE_MALLOC=1 HAVE_LIBSCTP=1) + +add_compile_options(-pipe -Wno-packed-bitfield-compat -fPIC -Wall -fno-strict-aliasing -rdynamic) +set(MKVER "'MAKE_VERSION(a,b,c)=((a)*256+(b)*16+c)'") set(CMAKE_C_FLAGS - "${CMAKE_C_FLAGS} ${C_FLAGS_PROCESSOR} -pipe -std=gnu99 -Wall -Wstrict-prototypes -fno-strict-aliasing -rdynamic -funroll-loops -Wno-packed-bitfield-compat -fPIC ${legacyAutoTools}" ) -set(CUDA_CMAKE_CXX_FLAGS - "${CMAKE_CXX_FLAGS} ${C_FLAGS_PROCESSOR} -Wno-packed-bitfield-compat -fPIC -Wall -fno-strict-aliasing -rdynamic -std=c++11") - -set(MKVER "'MAKE_VERSION(a,b,c)=((a)*256+(b)*16+c)'") -set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -D${MKVER} " ) -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -D${MKVER} " ) + "${CMAKE_C_FLAGS} ${C_FLAGS_PROCESSOR} -std=gnu99 -funroll-loops -D${MKVER}") +set(CMAKE_CXX_FLAGS + "${CMAKE_CXX_FLAGS} ${C_FLAGS_PROCESSOR} -std=c++11 -D${MKVER}") if (CUDA_FOUND) - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -D CUDA_FLAG" ) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -D CUDA_FLAG" ) + add_compile_definitions(CUDA_FLAG ) endif() - if (SANITIZE_ADDRESS) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=address -fno-common") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address -fno-common") endif () -add_definitions("-DASN_DISABLE_OER_SUPPORT") +add_compile_definitions("ASN_DISABLE_OER_SUPPORT") ######################### set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -ggdb3 -Wl,-rpath -Wl,${CMAKE_CURRENT_BINARY_DIR}") ######################### # set a flag for changes in the source code # these changes are related to hardcoded path to include .h files -set(debOpt "-ggdb3 -feliminate-dwarf2-dups -DMALLOC_CHECK_=3 -fno-delete-null-pointer-checks") -set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS} ${debOpt} -Og") -set(CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS} ${debOpt} -O2") -set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS} -O3") +set(debugOpt "-ggdb3 -feliminate-dwarf2-dups -DMALLOC_CHECK_=3 -fno-delete-null-pointer-checks") +set(CMAKE_C_FLAGS_DEBUG "${debugOpt} -Og") +set(CMAKE_C_FLAGS_RELWITHDEBINFO "${debugOpt} -O2") +set(CMAKE_C_FLAGS_RELEASE "-O3") set(GIT_BRANCH "UNKNOWN") set(GIT_COMMIT_HASH "UNKNOWN") @@ -376,14 +371,12 @@ if(GIT_FOUND) ) endif() - # Below is a hard-coded info set (FIRMWARE_VERSION "No svn information") -add_definitions("-DFIRMWARE_VERSION=\"${FIRMWARE_VERSION}\"") -add_definitions("-DPACKAGE_VERSION=\"Branch: ${GIT_BRANCH} Abrev. Hash: ${GIT_COMMIT_HASH} Date: ${GIT_COMMIT_DATE}\"") -add_definitions("-DPACKAGE_BUGREPORT=\"openair4g-devel@lists.eurecom.fr\"") -#add_definitions("-DEMIT_ASN_DEBUG=1") - +add_compile_definitions("FIRMWARE_VERSION=\"${FIRMWARE_VERSION}\"") +add_compile_definitions("PACKAGE_VERSION=\"Branch: ${GIT_BRANCH} Abrev. Hash: ${GIT_COMMIT_HASH} Date: ${GIT_COMMIT_DATE}\"") +add_compile_definitions("PACKAGE_BUGREPORT=\"openair4g-devel@lists.eurecom.fr\"") +#add_compile_definitions("EMIT_ASN_DEBUG=1") # Debug related options ######################################### @@ -397,14 +390,12 @@ add_boolean_option(PDCP_MSG_PRINT False "print PDCP messages to /tmp/pdcp.l add_boolean_option(DEBUG_PDCP_PAYLOAD False "print PDCP PDU to stdout") # if true, make sure that global and PDCP log levels are trace add_boolean_option(DEBUG_MAC_INTERFACE False "print MAC-RLC PDU exchange to stdout") # if true, make sure that global and PDCP log levels are trace add_boolean_option(TRACE_RLC_PAYLOAD False "print RLC PDU to stdout") # if true, make sure that global and PDCP log levels are trace -add_boolean_option(TEST_OMG False "???") -add_boolean_option(DEBUG_OMG False "???") add_boolean_option(PRINT_STATS False "This adds the possibility to see the status") add_boolean_option(T_TRACER True "Activate the T tracer, a debugging/monitoring framework" ) add_boolean_option(UE_AUTOTEST_TRACE False "Activate UE autotest specific logs") add_boolean_option(UE_DEBUG_TRACE False "Activate UE debug trace") add_boolean_option(UE_TIMING_TRACE False "Activate UE timing trace") -add_boolean_option(DEBUG_CONSOLE False "makes debugging easier, disables stdout/stderr buffering") +add_boolean_option(DEBUG_CONSOLE False "disables stdout/stderr buffering") set (OCP_ITTI ${OPENAIR_DIR}/common/utils/ocp_itti) add_library(ITTI @@ -412,8 +403,6 @@ add_library(ITTI ${OPENAIR_DIR}/common/utils/backtrace.c ) add_dependencies(ITTI rrc_flag) - set(ITTI_LIB ITTI) - ################################################## # ASN.1 grammar C code generation & dependencies # @@ -435,7 +424,7 @@ set (RRC_ASN1_VERSION "Rel15") make_version(LTE_RRC_VERSION 15 6 0) set (RRC_GRAMMAR ${OPENAIR2_DIR}/RRC/LTE/MESSAGES/asn1c/ASN1_files/lte-rrc-15.6.0.asn1) -add_definitions(-DLTE_RRC_VERSION=${LTE_RRC_VERSION}) +add_compile_definitions(LTE_RRC_VERSION=${LTE_RRC_VERSION}) set (RRC_FULL_DIR ${asn1_generated_dir}/RRC_${RRC_ASN1_VERSION}) # Warning: if you modify ASN.1 source file to generate new C files, cmake should be re-run instead of make @@ -467,7 +456,7 @@ include_directories ("${RRC_FULL_DIR}") set (NR_RRC_ASN1_VERSION "NR_Rel16" ) make_version(NR_RRC_VERSION 16 1 0) set (NR_RRC_GRAMMAR ${OPENAIR2_DIR}/RRC/NR/MESSAGES/asn1c/ASN1_files/nr-rrc-16.1.0.asn1) -add_definitions(-DNR_RRC_VERSION=${NR_RRC_VERSION}) +add_compile_definitions(NR_RRC_VERSION=${NR_RRC_VERSION}) set (NR_RRC_FULL_DIR ${asn1_generated_dir}/RRC_${NR_RRC_ASN1_VERSION}) # Warning: if you modify ASN.1 source file to generate new C files, cmake should be re-run instead of make @@ -502,7 +491,7 @@ set(S1AP_DIR ${OPENAIR3_DIR}/S1AP) make_version(S1AP_VERSION 15 6 0) set(S1AP_ASN_FILES "s1ap-15.6.0.asn1") -add_definitions(-DS1AP_VERSION=${S1AP_VERSION}) +add_compile_definitions(S1AP_VERSION=${S1AP_VERSION}) set(S1AP_ASN_DIR ${S1AP_DIR}/MESSAGES/ASN1/${S1AP_RELEASE}) set(S1AP_C_DIR ${asn1_generated_dir}/S1AP_${S1AP_RELEASE}) @@ -559,7 +548,7 @@ set(NGAP_DIR ${OPENAIR3_DIR}/NGAP) make_version(NGAP_VERSION 15 8 0) set(NGAP_ASN_FILES "ngap-15.8.0.asn1") -add_definitions(-DNGAP_VERSION=${NGAP_VERSION}) +add_compile_definitions(NGAP_VERSION=${NGAP_VERSION}) set(NGAP_ASN_DIR ${NGAP_DIR}/MESSAGES/ASN1/ASN1_files) set(NGAP_C_DIR ${asn1_generated_dir}/NGAP_${NGAP_RELEASE}) @@ -626,7 +615,7 @@ elseif (${M2AP_RELEASE} STREQUAL "R15") make_version(M2AP_VERSION 15 1 0) set(M2AP_ASN_FILES m2ap-15.1.0.asn1) endif(${M2AP_RELEASE} STREQUAL "R8") -add_definitions(-DM2AP_VERSION=${M2AP_VERSION}) +add_compile_definitions(M2AP_VERSION=${M2AP_VERSION}) set(M2AP_ASN_DIR ${M2AP_DIR}/MESSAGES/ASN1/${M2AP_RELEASE}) set(M2AP_C_DIR ${asn1_generated_dir}/M2AP_${M2AP_RELEASE}) @@ -699,7 +688,7 @@ elseif (${M3AP_RELEASE} STREQUAL "R15") make_version(M3AP_VERSION 15 1 0) set(M3AP_ASN_FILES m3ap-15.1.0.asn1) endif(${M3AP_RELEASE} STREQUAL "R8") -add_definitions(-DM3AP_VERSION=${M3AP_VERSION}) +add_compile_definitions(M3AP_VERSION=${M3AP_VERSION}) set(M3AP_ASN_DIR ${M3AP_DIR}/MESSAGES/ASN1/${M3AP_RELEASE}) set(M3AP_C_DIR ${asn1_generated_dir}/M3AP_${M3AP_RELEASE}) @@ -757,7 +746,7 @@ set(X2AP_DIR ${OPENAIR2_DIR}/X2AP) make_version(X2AP_VERSION 15 6 0) set(X2AP_ASN_FILES x2ap-15.6.0.asn1) -add_definitions(-DX2AP_VERSION=${X2AP_VERSION}) +add_compile_definitions(X2AP_VERSION=${X2AP_VERSION}) set(X2AP_ASN_DIR ${X2AP_DIR}/MESSAGES/ASN1/${X2AP_RELEASE}) set(X2AP_C_DIR ${asn1_generated_dir}/X2AP_${X2AP_RELEASE}) # Warning: if you modify ASN.1 source file to generate new C files, cmake should be re-run instead of make @@ -810,7 +799,7 @@ if (${F1AP_RELEASE} STREQUAL "R16") make_version(F1AP_VERSION 16 3 1) set (ASN1RELDIR R16.3.1) endif(${F1AP_RELEASE} STREQUAL "R16") -add_definitions(-DF1AP_VERSION=${F1AP_VERSION}) +add_compile_definitions(F1AP_VERSION=${F1AP_VERSION}) set(F1AP_ASN_DIR ${F1AP_DIR}/MESSAGES/ASN1/${ASN1RELDIR}) set(F1AP_ASN_FILES ${F1AP_ASN_DIR}/F1AP-CommonDataTypes.asn @@ -828,11 +817,11 @@ if (${RU} STREQUAL 0) COMMAND ${OPENAIR_CMAKE}/tools/make_asn1c_includes.sh "F1AP_" "-findirect-choice -fno-include-deps" ${F1AP_ASN_GENERATED_C_DIR} ${F1AP_ASN_FILES} RESULT_VARIABLE ret ) - + if (NOT ${ret} STREQUAL 0) message(FATAL_ERROR "asn1c: error") endif (NOT ${ret} STREQUAL 0) - + add_custom_target ( f1_flag ALL COMMAND ${OPENAIR_CMAKE}/tools/make_asn1c_includes.sh "F1AP_" "-findirect-choice -fno-include-deps" ${F1AP_ASN_GENERATED_C_DIR} ${F1AP_ASN_FILES} @@ -843,15 +832,13 @@ if (${RU} STREQUAL 0) ${F1AP_ASN_GENERATED_C_FILES} ) add_dependencies (F1AP_LIB f1_flag) - -include_directories ("${F1AP_ASN_GENERATED_C_DIR}") -include_directories ("${F1AP_DIR}") - -file(GLOB F1AP_C_FILES ${F1AP_DIR}/*.c) -add_library(F1AP - ${F1AP_C_FILES} -) - + + include_directories ("${F1AP_ASN_GENERATED_C_DIR}") + include_directories ("${F1AP_DIR}") + + file(GLOB F1AP_C_FILES ${F1AP_DIR}/*.c) + add_library(F1AP ${F1AP_C_FILES} ) + endif (${RU} STREQUAL 0) # Hardware dependant options @@ -864,22 +851,22 @@ add_list2_option(RF_BOARD "EXMIMO" "RF head type" "None" "OAI_USRP" "OAI_BLADERF add_list2_option(TRANSP_PRO "None" "Transport protocol type" "None" "ETHERNET") #NOKIA config enhancement set (CONFIG_ROOTDIR - ${OPENAIR_DIR}/common/config - ) + ${OPENAIR_DIR}/common/config + ) set (CONFIG_SOURCES - ${CONFIG_ROOTDIR}/config_load_configmodule.c - ${CONFIG_ROOTDIR}/config_userapi.c - ${CONFIG_ROOTDIR}/config_cmdline.c - ) + ${CONFIG_ROOTDIR}/config_load_configmodule.c + ${CONFIG_ROOTDIR}/config_userapi.c + ${CONFIG_ROOTDIR}/config_cmdline.c + ) set (CONFIG_LIBCONFIG_SOURCES - ${CONFIG_ROOTDIR}/libconfig/config_libconfig.c - ) + ${CONFIG_ROOTDIR}/libconfig/config_libconfig.c + ) add_library(CONFIG_LIB ${CONFIG_SOURCES}) add_library(params_libconfig MODULE ${CONFIG_LIBCONFIG_SOURCES} ) target_link_libraries(params_libconfig config) # shared library loader set (SHLIB_LOADER_SOURCES - ${OPENAIR_DIR}/common/utils/load_module_shlib.c + ${OPENAIR_DIR}/common/utils/load_module_shlib.c ) # include RF devices / transport protocols library modules ###################################################################### @@ -918,8 +905,8 @@ add_library(oai_eth_transpro MODULE ${TPLIB_ETHERNET_SOURCE} ) include_directories("${OPENAIR_TARGETS}/ARCH/IRIS/USERSPACE/LIB/") set(option_HWIRISLIB_lib "-l SoapySDR") set(HWLIB_IRIS_SOURCE - ${OPENAIR_TARGETS}/ARCH/IRIS/USERSPACE/LIB/iris_lib.cpp - ) + ${OPENAIR_TARGETS}/ARCH/IRIS/USERSPACE/LIB/iris_lib.cpp + ) add_library(oai_irisdevif MODULE ${HWLIB_IRIS_SOURCE}) target_include_directories(oai_irisdevif PRIVATE /usr/local/lib/SoapySDR/modules0.7/) target_link_libraries(oai_irisdevif SoapySDR) @@ -1026,7 +1013,6 @@ add_boolean_option(ENABLE_VCD False "always true now, time measure add_boolean_option(ENABLE_VCD_FIFO False "time measurements of proc calls and var displays sent to FIFO (one more thread)") add_boolean_option(LINUX False "used in weird memcpy() in pdcp.c ???") add_boolean_option(LINUX_LIST False "used only in lists.c: either use OAI implementation of lists or Linux one (should be True, but it is False") -add_boolean_option(OPENAIR_LTE True "Seems legacy: keep it to true") ########################## # PHY options @@ -1035,10 +1021,7 @@ add_boolean_option(DRIVER2013 True "only relevant for EXMIMO") add_boolean_option(EXMIMO_IOT True "????") add_boolean_option(LOCALIZATION False "???") add_integer_option(MAX_NUM_CCs 1 "????") -add_boolean_option(MU_RECEIVER False "????") add_boolean_option(PHYSIM False "for L1 simulators (dlsim, ulsim, ...)") -add_boolean_option(PHY_CONTEXT True "not clear: must remain False for dlsim") -add_boolean_option(PHY_EMUL False "not clear: must remain False for dlsim") add_boolean_option(SMBV False "Rohde&Schwarz SMBV100A vector signal generator") add_boolean_option(DEBUG_PHY False "Enable PHY layer debugging options") add_boolean_option(DEBUG_PHY_PROC False "Enable debugging of PHY layer procedures") @@ -1380,42 +1363,42 @@ target_link_libraries (msc LFDS) include_directories(${OPENAIR_DIR}/common/utils/msc) set(UTIL_SRC -# ${OPENAIR2_DIR}/UTIL/CLI/cli.c -# ${OPENAIR2_DIR}/UTIL/CLI/cli_cmd.c -# ${OPENAIR2_DIR}/UTIL/CLI/cli_server.c + # ${OPENAIR2_DIR}/UTIL/CLI/cli.c + # ${OPENAIR2_DIR}/UTIL/CLI/cli_cmd.c + # ${OPENAIR2_DIR}/UTIL/CLI/cli_server.c ${OPENAIR2_DIR}/UTIL/FIFO/pad_list.c ${OPENAIR2_DIR}/UTIL/LISTS/list.c ${OPENAIR2_DIR}/UTIL/LISTS/list2.c ${OPENAIR_DIR}/common/utils/LOG/log.c ${OPENAIR_DIR}/common/utils/LOG/vcd_signal_dumper.c ${OPENAIR2_DIR}/UTIL/MATH/oml.c -# ${OPENAIR2_DIR}/UTIL/MEM/mem_block.c -# ${OPENAIR2_DIR}/UTIL/OCG/OCG.c -# ${OPENAIR2_DIR}/UTIL/OCG/OCG_create_dir.c -# ${OPENAIR2_DIR}/UTIL/OCG/OCG_detect_file.c -# ${OPENAIR2_DIR}/UTIL/OCG/OCG_generate_report.c -# ${OPENAIR2_DIR}/UTIL/OCG/OCG_parse_filename.c -# ${OPENAIR2_DIR}/UTIL/OCG/OCG_parse_XML.c -# ${OPENAIR2_DIR}/UTIL/OCG/OCG_save_XML.c -# ${OPENAIR2_DIR}/UTIL/OMG/common.c -# ${OPENAIR2_DIR}/UTIL/OMG/grid.c -# ${OPENAIR2_DIR}/UTIL/OMG/job.c -# ${OPENAIR2_DIR}/UTIL/OMG/mobility_parser.c -# ${OPENAIR2_DIR}/UTIL/OMG/omg.c -# ${OPENAIR2_DIR}/UTIL/OMG/omg_hashtable.c -# ${OPENAIR2_DIR}/UTIL/OMG/rwalk.c -# ${OPENAIR2_DIR}/UTIL/OMG/rwp.c -# ${OPENAIR2_DIR}/UTIL/OMG/static.c -# ${OPENAIR2_DIR}/UTIL/OMG/steadystaterwp.c -# ${OPENAIR2_DIR}/UTIL/OMG/trace.c -# ${OPENAIR2_DIR}/UTIL/OMG/trace_hashtable.c + # ${OPENAIR2_DIR}/UTIL/MEM/mem_block.c + # ${OPENAIR2_DIR}/UTIL/OCG/OCG.c + # ${OPENAIR2_DIR}/UTIL/OCG/OCG_create_dir.c + # ${OPENAIR2_DIR}/UTIL/OCG/OCG_detect_file.c + # ${OPENAIR2_DIR}/UTIL/OCG/OCG_generate_report.c + # ${OPENAIR2_DIR}/UTIL/OCG/OCG_parse_filename.c + # ${OPENAIR2_DIR}/UTIL/OCG/OCG_parse_XML.c + # ${OPENAIR2_DIR}/UTIL/OCG/OCG_save_XML.c + # ${OPENAIR2_DIR}/UTIL/OMG/common.c + # ${OPENAIR2_DIR}/UTIL/OMG/grid.c + # ${OPENAIR2_DIR}/UTIL/OMG/job.c + # ${OPENAIR2_DIR}/UTIL/OMG/mobility_parser.c + # ${OPENAIR2_DIR}/UTIL/OMG/omg.c + # ${OPENAIR2_DIR}/UTIL/OMG/omg_hashtable.c + # ${OPENAIR2_DIR}/UTIL/OMG/rwalk.c + # ${OPENAIR2_DIR}/UTIL/OMG/rwp.c + # ${OPENAIR2_DIR}/UTIL/OMG/static.c + # ${OPENAIR2_DIR}/UTIL/OMG/steadystaterwp.c + # ${OPENAIR2_DIR}/UTIL/OMG/trace.c + # ${OPENAIR2_DIR}/UTIL/OMG/trace_hashtable.c ${OPENAIR2_DIR}/UTIL/OPT/probe.c -# ${OPENAIR2_DIR}/UTIL/OTG/otg_tx.c -# ${OPENAIR2_DIR}/UTIL/OTG/otg.c -# ${OPENAIR2_DIR}/UTIL/OTG/otg_kpi.c -# ${OPENAIR2_DIR}/UTIL/OTG/otg_models.c -# ${OPENAIR2_DIR}/UTIL/OTG/otg_form.c -# ${OPENAIR2_DIR}/UTIL/OTG/otg_rx.c + # ${OPENAIR2_DIR}/UTIL/OTG/otg_tx.c + # ${OPENAIR2_DIR}/UTIL/OTG/otg.c + # ${OPENAIR2_DIR}/UTIL/OTG/otg_kpi.c + # ${OPENAIR2_DIR}/UTIL/OTG/otg_models.c + # ${OPENAIR2_DIR}/UTIL/OTG/otg_form.c + # ${OPENAIR2_DIR}/UTIL/OTG/otg_rx.c ) add_library(UTIL ${UTIL_SRC}) add_dependencies(UTIL rrc_flag) @@ -1506,7 +1489,7 @@ add_library(SCHED_NR_UE_LIB ${SCHED_SRC_NR_UE}) ################################# set(NFAPI_COMMON_SRC ${NFAPI_DIR}/common/src/debug.c -) + ) add_library(NFAPI_COMMON_LIB ${NFAPI_COMMON_SRC}) include_directories(${NFAPI_DIR}/common/public_inc) @@ -2164,7 +2147,6 @@ set (MISC_NFAPI_LTE ${OPENAIR1_DIR}/SCHED/nfapi_lte_dummy.c ) - add_library(MISC_NFAPI_LTE_LIB ${MISC_NFAPI_LTE} ) @@ -2173,7 +2155,6 @@ set (MISC_NFAPI_NR ${OPENAIR1_DIR}/SCHED/nfapi_nr_dummy.c ) - add_library(MISC_NFAPI_NR_LIB ${MISC_NFAPI_NR} ) @@ -2256,8 +2237,8 @@ set(GTPV1U_DIR ${OPENAIR3_DIR}/GTPV1-U) add_library (GTPV1U_OCP ${NR_RRC_DIR}/rrc_gNB_GTPV1U.c ${RRC_DIR}/rrc_eNB_GTPV1U.c -${OPENAIR3_DIR}/ocp-gtpu/gtp_itf.cpp -) + ${OPENAIR3_DIR}/ocp-gtpu/gtp_itf.cpp + ) target_compile_definitions(GTPV1U_OCP PUBLIC NEW_GTPU) add_dependencies(GTPV1U_OCP rrc_flag) include_directories(${OPENAIR3_DIR}/ocp-gtp) @@ -2273,7 +2254,7 @@ set (NR_GTPV1U_SRC ${GTPV1U_DIR}/nw-gtpv1u/src/NwGtpv1uMsg.c ${GTPV1U_DIR}/nw-gtpv1u/src/NwGtpv1u.c ${GTPV1U_DIR}/gtpv1u_teid_pool.c -) + ) add_library(NR_GTPV1U ${NR_GTPV1U_SRC}) add_dependencies(NR_GTPV1U rrc_flag) @@ -2295,7 +2276,6 @@ add_dependencies(SCTP_CLIENT rrc_flag) add_library(UDP ${OPENAIR3_DIR}/UDP/udp_eNB_task.c) add_dependencies(UDP rrc_flag) - set(NAS_SRC ${OPENAIR3_DIR}/NAS/) set(libnas_api_OBJS ${NAS_SRC}COMMON/API/NETWORK/as_message.c @@ -2454,171 +2434,171 @@ set (libnas_utils_OBJS ${NAS_SRC}COMMON/UTIL/OctetString.c ) - set(libnas_ue_api_OBJS - ${NAS_SRC}UE/API/USER/at_command.c - ${NAS_SRC}UE/API/USER/at_error.c - ${NAS_SRC}UE/API/USER/at_response.c - ${NAS_SRC}UE/API/USER/user_api.c - ${NAS_SRC}UE/API/USER/user_indication.c - ${NAS_SRC}UE/API/USIM/aka_functions.c - ${NAS_SRC}UE/API/USIM/usim_api.c +set(libnas_ue_api_OBJS + ${NAS_SRC}UE/API/USER/at_command.c + ${NAS_SRC}UE/API/USER/at_error.c + ${NAS_SRC}UE/API/USER/at_response.c + ${NAS_SRC}UE/API/USER/user_api.c + ${NAS_SRC}UE/API/USER/user_indication.c + ${NAS_SRC}UE/API/USIM/aka_functions.c + ${NAS_SRC}UE/API/USIM/usim_api.c ) - set(libnas_ue_emm_OBJS - ${NAS_SRC}UE/EMM/Attach.c - ${NAS_SRC}UE/EMM/Authentication.c - ${NAS_SRC}UE/EMM/Detach.c - ${NAS_SRC}UE/EMM/emm_main.c - ${NAS_SRC}UE/EMM/EmmStatusHdl.c - ${NAS_SRC}UE/EMM/Identification.c - ${NAS_SRC}UE/EMM/IdleMode.c - ${NAS_SRC}UE/EMM/LowerLayer.c - ${NAS_SRC}UE/EMM/SecurityModeControl.c - ${NAS_SRC}UE/EMM/ServiceRequestHdl.c - ${NAS_SRC}UE/EMM/TrackingAreaUpdate.c +set(libnas_ue_emm_OBJS + ${NAS_SRC}UE/EMM/Attach.c + ${NAS_SRC}UE/EMM/Authentication.c + ${NAS_SRC}UE/EMM/Detach.c + ${NAS_SRC}UE/EMM/emm_main.c + ${NAS_SRC}UE/EMM/EmmStatusHdl.c + ${NAS_SRC}UE/EMM/Identification.c + ${NAS_SRC}UE/EMM/IdleMode.c + ${NAS_SRC}UE/EMM/LowerLayer.c + ${NAS_SRC}UE/EMM/SecurityModeControl.c + ${NAS_SRC}UE/EMM/ServiceRequestHdl.c + ${NAS_SRC}UE/EMM/TrackingAreaUpdate.c ) - set(libnas_ue_emm_sap_OBJS - ${NAS_SRC}UE/EMM/SAP/emm_as.c - ${NAS_SRC}UE/EMM/SAP/EmmDeregisteredAttachNeeded.c - ${NAS_SRC}UE/EMM/SAP/EmmDeregisteredAttemptingToAttach.c - ${NAS_SRC}UE/EMM/SAP/EmmDeregistered.c - ${NAS_SRC}UE/EMM/SAP/EmmDeregisteredInitiated.c - ${NAS_SRC}UE/EMM/SAP/EmmDeregisteredLimitedService.c - ${NAS_SRC}UE/EMM/SAP/EmmDeregisteredNoCellAvailable.c - ${NAS_SRC}UE/EMM/SAP/EmmDeregisteredNoImsi.c - ${NAS_SRC}UE/EMM/SAP/EmmDeregisteredNormalService.c - ${NAS_SRC}UE/EMM/SAP/EmmDeregisteredPlmnSearch.c - ${NAS_SRC}UE/EMM/SAP/emm_esm.c - ${NAS_SRC}UE/EMM/SAP/emm_fsm.c - ${NAS_SRC}UE/EMM/SAP/EmmNull.c - ${NAS_SRC}UE/EMM/SAP/emm_recv.c - ${NAS_SRC}UE/EMM/SAP/emm_reg.c - ${NAS_SRC}UE/EMM/SAP/EmmRegisteredAttemptingToUpdate.c - ${NAS_SRC}UE/EMM/SAP/EmmRegistered.c - ${NAS_SRC}UE/EMM/SAP/EmmRegisteredImsiDetachInitiated.c - ${NAS_SRC}UE/EMM/SAP/EmmRegisteredInitiated.c - ${NAS_SRC}UE/EMM/SAP/EmmRegisteredLimitedService.c - ${NAS_SRC}UE/EMM/SAP/EmmRegisteredNoCellAvailable.c - ${NAS_SRC}UE/EMM/SAP/EmmRegisteredNormalService.c - ${NAS_SRC}UE/EMM/SAP/EmmRegisteredPlmnSearch.c - ${NAS_SRC}UE/EMM/SAP/EmmRegisteredUpdateNeeded.c - ${NAS_SRC}UE/EMM/SAP/emm_sap.c - ${NAS_SRC}UE/EMM/SAP/emm_send.c - ${NAS_SRC}UE/EMM/SAP/EmmServiceRequestInitiated.c - ${NAS_SRC}UE/EMM/SAP/EmmTrackingAreaUpdatingInitiated.c +set(libnas_ue_emm_sap_OBJS + ${NAS_SRC}UE/EMM/SAP/emm_as.c + ${NAS_SRC}UE/EMM/SAP/EmmDeregisteredAttachNeeded.c + ${NAS_SRC}UE/EMM/SAP/EmmDeregisteredAttemptingToAttach.c + ${NAS_SRC}UE/EMM/SAP/EmmDeregistered.c + ${NAS_SRC}UE/EMM/SAP/EmmDeregisteredInitiated.c + ${NAS_SRC}UE/EMM/SAP/EmmDeregisteredLimitedService.c + ${NAS_SRC}UE/EMM/SAP/EmmDeregisteredNoCellAvailable.c + ${NAS_SRC}UE/EMM/SAP/EmmDeregisteredNoImsi.c + ${NAS_SRC}UE/EMM/SAP/EmmDeregisteredNormalService.c + ${NAS_SRC}UE/EMM/SAP/EmmDeregisteredPlmnSearch.c + ${NAS_SRC}UE/EMM/SAP/emm_esm.c + ${NAS_SRC}UE/EMM/SAP/emm_fsm.c + ${NAS_SRC}UE/EMM/SAP/EmmNull.c + ${NAS_SRC}UE/EMM/SAP/emm_recv.c + ${NAS_SRC}UE/EMM/SAP/emm_reg.c + ${NAS_SRC}UE/EMM/SAP/EmmRegisteredAttemptingToUpdate.c + ${NAS_SRC}UE/EMM/SAP/EmmRegistered.c + ${NAS_SRC}UE/EMM/SAP/EmmRegisteredImsiDetachInitiated.c + ${NAS_SRC}UE/EMM/SAP/EmmRegisteredInitiated.c + ${NAS_SRC}UE/EMM/SAP/EmmRegisteredLimitedService.c + ${NAS_SRC}UE/EMM/SAP/EmmRegisteredNoCellAvailable.c + ${NAS_SRC}UE/EMM/SAP/EmmRegisteredNormalService.c + ${NAS_SRC}UE/EMM/SAP/EmmRegisteredPlmnSearch.c + ${NAS_SRC}UE/EMM/SAP/EmmRegisteredUpdateNeeded.c + ${NAS_SRC}UE/EMM/SAP/emm_sap.c + ${NAS_SRC}UE/EMM/SAP/emm_send.c + ${NAS_SRC}UE/EMM/SAP/EmmServiceRequestInitiated.c + ${NAS_SRC}UE/EMM/SAP/EmmTrackingAreaUpdatingInitiated.c ) - set (libnas_ue_esm_OBJS - ${NAS_SRC}UE/ESM/DedicatedEpsBearerContextActivation.c - ${NAS_SRC}UE/ESM/DefaultEpsBearerContextActivation.c - ${NAS_SRC}UE/ESM/EpsBearerContextDeactivation.c - ${NAS_SRC}UE/ESM/esm_ebr.c - ${NAS_SRC}UE/ESM/esm_ebr_context.c - ${NAS_SRC}UE/ESM/esm_ip.c - ${NAS_SRC}UE/ESM/esm_main.c - ${NAS_SRC}UE/ESM/esm_pt.c - ${NAS_SRC}UE/ESM/EsmStatusHdl.c - ${NAS_SRC}UE/ESM/PdnConnectivity.c - ${NAS_SRC}UE/ESM/PdnDisconnect.c +set (libnas_ue_esm_OBJS + ${NAS_SRC}UE/ESM/DedicatedEpsBearerContextActivation.c + ${NAS_SRC}UE/ESM/DefaultEpsBearerContextActivation.c + ${NAS_SRC}UE/ESM/EpsBearerContextDeactivation.c + ${NAS_SRC}UE/ESM/esm_ebr.c + ${NAS_SRC}UE/ESM/esm_ebr_context.c + ${NAS_SRC}UE/ESM/esm_ip.c + ${NAS_SRC}UE/ESM/esm_main.c + ${NAS_SRC}UE/ESM/esm_pt.c + ${NAS_SRC}UE/ESM/EsmStatusHdl.c + ${NAS_SRC}UE/ESM/PdnConnectivity.c + ${NAS_SRC}UE/ESM/PdnDisconnect.c ) - set(libnas_ue_esm_sap_OBJS - ${NAS_SRC}UE/ESM/SAP/esm_recv.c - ${NAS_SRC}UE/ESM/SAP/esm_send.c - ${NAS_SRC}UE/ESM/SAP/esm_sap.c +set(libnas_ue_esm_sap_OBJS + ${NAS_SRC}UE/ESM/SAP/esm_recv.c + ${NAS_SRC}UE/ESM/SAP/esm_send.c + ${NAS_SRC}UE/ESM/SAP/esm_sap.c ) - set(libnrnas_emm_msg_OBJS - ${NAS_SRC}COMMON/EMM/MSG/RegistrationRequest.c - ${NAS_SRC}COMMON/EMM/MSG/RegistrationAccept.c - ${NAS_SRC}COMMON/EMM/MSG/FGSIdentityResponse.c - ${NAS_SRC}COMMON/EMM/MSG/FGSAuthenticationResponse.c - ${NAS_SRC}COMMON/EMM/MSG/FGSNASSecurityModeComplete.c - ${NAS_SRC}COMMON/EMM/MSG/RegistrationComplete.c - ${NAS_SRC}COMMON/EMM/MSG/FGSUplinkNasTransport.c - ${NAS_SRC}COMMON/ESM/MSG/PduSessionEstablishRequest.c +set(libnrnas_emm_msg_OBJS + ${NAS_SRC}COMMON/EMM/MSG/RegistrationRequest.c + ${NAS_SRC}COMMON/EMM/MSG/RegistrationAccept.c + ${NAS_SRC}COMMON/EMM/MSG/FGSIdentityResponse.c + ${NAS_SRC}COMMON/EMM/MSG/FGSAuthenticationResponse.c + ${NAS_SRC}COMMON/EMM/MSG/FGSNASSecurityModeComplete.c + ${NAS_SRC}COMMON/EMM/MSG/RegistrationComplete.c + ${NAS_SRC}COMMON/EMM/MSG/FGSUplinkNasTransport.c + ${NAS_SRC}COMMON/ESM/MSG/PduSessionEstablishRequest.c ) - set(libnrnas_ies_OBJS - ${NAS_SRC}COMMON/IES/ExtendedProtocolDiscriminator.c - ${NAS_SRC}COMMON/IES/FGSMobileIdentity.c - ${NAS_SRC}COMMON/IES/FGSRegistrationType.c - ${NAS_SRC}COMMON/IES/SpareHalfOctet.c - ${NAS_SRC}COMMON/IES/FGSRegistrationResult.c - ${NAS_SRC}COMMON/IES/FGMMCapability.c - ${NAS_SRC}COMMON/IES/NrUESecurityCapability.c - ${NAS_SRC}COMMON/IES/FGCNasMessageContainer.c - ${NAS_SRC}COMMON/IES/SORTransparentContainer.c +set(libnrnas_ies_OBJS + ${NAS_SRC}COMMON/IES/ExtendedProtocolDiscriminator.c + ${NAS_SRC}COMMON/IES/FGSMobileIdentity.c + ${NAS_SRC}COMMON/IES/FGSRegistrationType.c + ${NAS_SRC}COMMON/IES/SpareHalfOctet.c + ${NAS_SRC}COMMON/IES/FGSRegistrationResult.c + ${NAS_SRC}COMMON/IES/FGMMCapability.c + ${NAS_SRC}COMMON/IES/NrUESecurityCapability.c + ${NAS_SRC}COMMON/IES/FGCNasMessageContainer.c + ${NAS_SRC}COMMON/IES/SORTransparentContainer.c ) - add_library(LIB_NAS_SIMUE - ${NAS_SRC}UE/nas_itti_messaging.c - ${NAS_SRC}UE/nas_network.c - ${NAS_SRC}UE/nas_parser.c - ${NAS_SRC}UE/nas_proc.c - ${NAS_SRC}UE/nas_user.c - ${NAS_SRC}NR_UE/nr_nas_msg_sim.c - ${libnas_api_OBJS} - ${libnas_ue_api_OBJS} - ${libnas_emm_msg_OBJS} - ${libnas_esm_msg_OBJS} - ${libnas_ies_OBJS} - ${libnas_utils_OBJS} - ${libnas_ue_emm_OBJS} - ${libnas_ue_emm_sap_OBJS} - ${libnas_ue_esm_OBJS} - ${libnas_ue_esm_sap_OBJS} - ${libnrnas_emm_msg_OBJS} - ${libnrnas_ies_OBJS} +add_library(LIB_NAS_SIMUE + ${NAS_SRC}UE/nas_itti_messaging.c + ${NAS_SRC}UE/nas_network.c + ${NAS_SRC}UE/nas_parser.c + ${NAS_SRC}UE/nas_proc.c + ${NAS_SRC}UE/nas_user.c + ${NAS_SRC}NR_UE/nr_nas_msg_sim.c + ${libnas_api_OBJS} + ${libnas_ue_api_OBJS} + ${libnas_emm_msg_OBJS} + ${libnas_esm_msg_OBJS} + ${libnas_ies_OBJS} + ${libnas_utils_OBJS} + ${libnas_ue_emm_OBJS} + ${libnas_ue_emm_sap_OBJS} + ${libnas_ue_esm_OBJS} + ${libnas_ue_esm_sap_OBJS} + ${libnrnas_emm_msg_OBJS} + ${libnrnas_ies_OBJS} ) - add_dependencies(LIB_NAS_SIMUE rrc_flag) - set(NAS_SIM_LIB LIB_NAS_SIMUE) +add_dependencies(LIB_NAS_SIMUE rrc_flag) +set(NAS_SIM_LIB LIB_NAS_SIMUE) - add_library(LIB_NAS_UE - ${NAS_SRC}UE/nas_itti_messaging.c - ${NAS_SRC}UE/nas_network.c - ${NAS_SRC}UE/nas_parser.c - ${NAS_SRC}UE/nas_proc.c - ${NAS_SRC}UE/nas_user.c - ${libnas_api_OBJS} - ${libnas_ue_api_OBJS} - ${libnas_emm_msg_OBJS} - ${libnas_esm_msg_OBJS} - ${libnas_ies_OBJS} - ${libnas_utils_OBJS} - ${libnas_ue_emm_OBJS} - ${libnas_ue_emm_sap_OBJS} - ${libnas_ue_esm_OBJS} - ${libnas_ue_esm_sap_OBJS} +add_library(LIB_NAS_UE + ${NAS_SRC}UE/nas_itti_messaging.c + ${NAS_SRC}UE/nas_network.c + ${NAS_SRC}UE/nas_parser.c + ${NAS_SRC}UE/nas_proc.c + ${NAS_SRC}UE/nas_user.c + ${libnas_api_OBJS} + ${libnas_ue_api_OBJS} + ${libnas_emm_msg_OBJS} + ${libnas_esm_msg_OBJS} + ${libnas_ies_OBJS} + ${libnas_utils_OBJS} + ${libnas_ue_emm_OBJS} + ${libnas_ue_emm_sap_OBJS} + ${libnas_ue_esm_OBJS} + ${libnas_ue_esm_sap_OBJS} ) - add_dependencies(LIB_NAS_UE rrc_flag) - set(NAS_UE_LIB LIB_NAS_UE) +add_dependencies(LIB_NAS_UE rrc_flag) +set(NAS_UE_LIB LIB_NAS_UE) - include_directories(${NAS_SRC}NR_UE) - include_directories(${NAS_SRC}UE) - include_directories(${NAS_SRC}UE/API/USER) - include_directories(${NAS_SRC}UE/API/USIM) - include_directories(${NAS_SRC}UE/EMM) - include_directories(${NAS_SRC}UE/EMM/SAP) - include_directories(${NAS_SRC}UE/ESM) - include_directories(${NAS_SRC}UE/ESM/SAP) +include_directories(${NAS_SRC}NR_UE) +include_directories(${NAS_SRC}UE) +include_directories(${NAS_SRC}UE/API/USER) +include_directories(${NAS_SRC}UE/API/USIM) +include_directories(${NAS_SRC}UE/EMM) +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") +add_compile_definitions("NUMBER_OF_UE_MAX_NB_IoT=16") set (NBIOT_SOURCES - ${OPENAIR2_DIR}/ENB_APP/NB_IoT_config.c -) + ${OPENAIR2_DIR}/ENB_APP/NB_IoT_config.c + ) add_library(NB_IoT MODULE ${NBIOT_SOURCES} ) # shared library loader set (SHLIB_LOADER_SOURCES - ${OPENAIR_DIR}/common/utils/load_module_shlib.c -) + ${OPENAIR_DIR}/common/utils/load_module_shlib.c + ) add_library(LIB_5GNAS_GNB - ${NAS_SRC}/COMMON/nr_common.c - ${NAS_SRC}/gNB/network_process_nas.c - ${NAS_SRC}/NR_UE/ue_process_nas.c - ${OPENAIR3_DIR}//UICC/usim_interface.c - ) + ${NAS_SRC}/COMMON/nr_common.c + ${NAS_SRC}/gNB/network_process_nas.c + ${NAS_SRC}/NR_UE/ue_process_nas.c + ${OPENAIR3_DIR}//UICC/usim_interface.c + ) target_link_libraries(LIB_5GNAS_GNB SECU_CN ${CRYPTO_LIBRARIES}) # Make lfds as a own source code (even if it is a outside library) @@ -2781,7 +2761,7 @@ add_custom_target ( ) # Hack on a test of asn1c version (already dirty) -add_definitions(-DASN1_MINIMUM_VERSION=924) +add_compile_definitions(ASN1_MINIMUM_VERSION=924) ################################# # add executables for operation @@ -2850,10 +2830,9 @@ add_dependencies(lte-softmodem rrc_flag s1ap_flag x2_flag oai_iqplayer) target_link_libraries (lte-softmodem -Wl,--start-group - RRC_LIB NR_RRC_LIB S1AP_LIB S1AP_ENB F1AP_LIB F1AP M2AP_LIB M2AP_ENB X2AP_LIB X2AP_ENB M3AP_LIB M3AP_ENB NR_GTPV1U SECU_CN SECU_OSA UTIL HASHTABLE SCTP_CLIENT MME_APP UDP SCHED_LIB SCHED_RU_LIB PHY_COMMON PHY PHY_RU LFDS L2 L2_LTE NFAPI_COMMON_LIB NFAPI_LIB NFAPI_VNF_LIB NFAPI_PNF_LIB NFAPI_USER_LIB MISC_NFAPI_LTE_LIB LFDS7 - ${MSC_LIB} ${RAL_LIB} ${NAS_UE_LIB} ${ITTI_LIB} ${FLPT_MSG_LIB} ${ASYNC_IF_LIB} ${FLEXRAN_AGENT_LIB} ${FSPT_MSG_LIB} ${PROTO_AGENT_LIB} + ${MSC_LIB} ${RAL_LIB} ${NAS_UE_LIB} ITTI ${FLPT_MSG_LIB} ${ASYNC_IF_LIB} ${FLEXRAN_AGENT_LIB} ${FSPT_MSG_LIB} ${PROTO_AGENT_LIB} -Wl,--end-group z dl) target_link_libraries (lte-softmodem ${LIBXML2_LIBRARIES}) @@ -2896,7 +2875,7 @@ target_link_libraries (ocp-enb RRC_LIB NR_RRC_LIB S1AP_LIB S1AP_ENB F1AP_LIB F1AP M2AP_LIB M2AP_ENB X2AP_LIB X2AP_ENB M3AP_LIB M3AP_ENB NR_GTPV1U SECU_CN SECU_OSA UTIL HASHTABLE SCTP_CLIENT MME_APP UDP SCHED_LIB SCHED_RU_LIB PHY_COMMON PHY PHY_RU LFDS L2 L2_LTE NFAPI_COMMON_LIB NFAPI_LIB MISC_NFAPI_LTE_LIB NFAPI_VNF_LIB NFAPI_PNF_LIB NFAPI_USER_LIB LFDS7 SIMU_COMMON - ${MSC_LIB} ${RAL_LIB} ${NAS_UE_LIB} ${ITTI_LIB} ${FLPT_MSG_LIB} ${ASYNC_IF_LIB} ${FLEXRAN_AGENT_LIB} ${FSPT_MSG_LIB} ${PROTO_AGENT_LIB} + ${MSC_LIB} ${RAL_LIB} ${NAS_UE_LIB} ITTI ${FLPT_MSG_LIB} ${ASYNC_IF_LIB} ${FLEXRAN_AGENT_LIB} ${FSPT_MSG_LIB} ${PROTO_AGENT_LIB} -Wl,--end-group z dl) target_link_libraries (ocp-enb ${LIBXML2_LIBRARIES} pthread m ${CONFIG_LIBRARIES} rt crypt ${CRYPTO_LIBRARIES} ${OPENSSL_LIBRARIES} sctp ${PROTOBUF_LIB} ${CMAKE_DL_LIBS} ${LIBYAML_LIBRARIES} ${LIB_LMS_LIBRARIES} ${T_LIB}) @@ -2911,7 +2890,7 @@ add_executable(cu_test ) target_link_libraries(cu_test ${FLPT_MSG_LIB} ${ASYNC_IF_LIB} ${FSPT_MSG_LIB} ${PROTOBUF_LIB} - ${PROTO_AGENT_LIB} pthread UTIL ${T_LIB} dl ${ITTI_LIB} + ${PROTO_AGENT_LIB} pthread UTIL ${T_LIB} dl ITTI ) add_executable(du_test @@ -2925,7 +2904,7 @@ add_executable(du_test ) target_link_libraries(du_test ${FLPT_MSG_LIB} ${ASYNC_IF_LIB} ${FSPT_MSG_LIB} ${PROTOBUF_LIB} - ${PROTO_AGENT_LIB} pthread UTIL ${T_LIB} dl ${ITTI_LIB} + ${PROTO_AGENT_LIB} pthread UTIL ${T_LIB} dl ITTI ) add_executable(oairu @@ -2993,7 +2972,7 @@ target_link_libraries (lte-uesoftmodem NR_GTPV1U SECU_CN SECU_OSA UTIL HASHTABLE SCTP_CLIENT MME_APP UDP SCHED_RU_LIB SCHED_UE_LIB PHY_COMMON PHY_UE PHY_RU LFDS L2_UE L2_LTE LFDS7 SIMU_COMMON SIMU NFAPI_COMMON_LIB NFAPI_LIB NFAPI_PNF_LIB NFAPI_USER_LIB MISC_NFAPI_LTE_LIB - ${MSC_LIB} ${RAL_LIB} ${NAS_UE_LIB} ${ITTI_LIB} ${FLPT_MSG_LIB} ${ASYNC_IF_LIB} ${ATLAS_LIBRARIES} + ${MSC_LIB} ${RAL_LIB} ${NAS_UE_LIB} ITTI ${FLPT_MSG_LIB} ${ASYNC_IF_LIB} ${ATLAS_LIBRARIES} -Wl,--end-group z dl) target_link_libraries (lte-uesoftmodem ${LIBXML2_LIBRARIES}) @@ -3036,7 +3015,7 @@ target_compile_definitions(nr-softmodem PUBLIC NEW_GTPU) target_link_libraries (nr-softmodem -Wl,--start-group UTIL HASHTABLE SCTP_CLIENT UDP SCHED_LIB SCHED_RU_LIB SCHED_NR_LIB PHY_NR PHY PHY_COMMON PHY_NR_COMMON PHY_RU LFDS GTPV1U_OCP SECU_CN SECU_OSA - ${ITTI_LIB} ${FLPT_MSG_LIB} ${ASYNC_IF_LIB} ${FLEXRAN_AGENT_LIB} LFDS7 ${MSC_LIB} ${RAL_LIB} ${NAS_UE_LIB} RRC_LIB NR_RRC_LIB + ITTI ${FLPT_MSG_LIB} ${ASYNC_IF_LIB} ${FLEXRAN_AGENT_LIB} LFDS7 ${MSC_LIB} ${RAL_LIB} ${NAS_UE_LIB} RRC_LIB NR_RRC_LIB NGAP_LIB NGAP_GNB S1AP_LIB S1AP_ENB L2_LTE_NR L2_NR MAC_NR_COMMON NFAPI_COMMON_LIB NFAPI_LIB NFAPI_VNF_LIB NFAPI_PNF_LIB NFAPI_USER_LIB X2AP_LIB X2AP_ENB F1AP_LIB F1AP M2AP_LIB M2AP_ENB M3AP_LIB M3AP_ENB ${PROTO_AGENT_LIB} ${FSPT_MSG_LIB} -Wl,--end-group z dl) @@ -3075,7 +3054,7 @@ add_executable(ocp-gnb target_link_libraries (ocp-gnb -Wl,--start-group UTIL HASHTABLE SCTP_CLIENT UDP SCHED_LIB SCHED_RU_LIB SCHED_NR_LIB PHY_NR PHY PHY_COMMON PHY_NR_COMMON PHY_RU LFDS GTPV1U_OCP SECU_CN SECU_OSA - ${ITTI_LIB} ${FLPT_MSG_LIB} ${ASYNC_IF_LIB} LFDS7 ${MSC_LIB} ${RAL_LIB} ${NAS_UE_LIB} RRC_LIB NR_RRC_LIB + ITTI ${FLPT_MSG_LIB} ${ASYNC_IF_LIB} LFDS7 ${MSC_LIB} ${RAL_LIB} ${NAS_UE_LIB} RRC_LIB NR_RRC_LIB NGAP_LIB NGAP_GNB S1AP_LIB S1AP_ENB L2_LTE_NR L2_NR MAC_NR_COMMON NFAPI_COMMON_LIB NFAPI_LIB NFAPI_VNF_LIB NFAPI_PNF_LIB NFAPI_USER_LIB X2AP_LIB X2AP_ENB F1AP_LIB F1AP M2AP_LIB M2AP_ENB M3AP_LIB M3AP_ENB SIMU_COMMON -Wl,--end-group z dl) @@ -3121,9 +3100,9 @@ target_link_libraries (nr-uesoftmodem RRC_LIB NR_RRC_LIB NGAP_LIB NGAP_GNB SECU_CN SECU_OSA UTIL HASHTABLE SCTP_CLIENT UDP SCHED_RU_LIB SCHED_UE_LIB SCHED_NR_UE_LIB PHY_COMMON PHY_NR_COMMON PHY_UE PHY_NR_UE PHY_RU LFDS NR_L2_UE L2_UE_LTE_NR MAC_NR_COMMON NFAPI_COMMON_LIB NFAPI_LIB NFAPI_PNF_LIB NFAPI_USER_LIB MISC_NFAPI_NR_LIB S1AP_LIB S1AP_ENB - ${MSC_LIB} ${RAL_LIB} ${NAS_UE_LIB} ${ITTI_LIB} ${FLPT_MSG_LIB} ${ASYNC_IF_LIB} LFDS7 ${ATLAS_LIBRARIES} + ${MSC_LIB} ${RAL_LIB} ${NAS_UE_LIB} ITTI ${FLPT_MSG_LIB} ${ASYNC_IF_LIB} LFDS7 ${ATLAS_LIBRARIES} NFAPI_USER_LIB S1AP_LIB S1AP_ENB - ${MSC_LIB} ${RAL_LIB} ${NAS_UE_LIB} ${ITTI_LIB} ${FLPT_MSG_LIB} ${ASYNC_IF_LIB} LFDS7 ${ATLAS_LIBRARIES} LIB_5GNAS_GNB LIB_NAS_SIMUE ${NAS_SIM_LIB} + ${MSC_LIB} ${RAL_LIB} ${NAS_UE_LIB} ITTI ${FLPT_MSG_LIB} ${ASYNC_IF_LIB} LFDS7 ${ATLAS_LIBRARIES} LIB_5GNAS_GNB LIB_NAS_SIMUE ${NAS_SIM_LIB} -Wl,--end-group z dl) target_link_libraries (nr-uesoftmodem ${LIBXML2_LIBRARIES}) @@ -3149,7 +3128,7 @@ add_executable(dlsim_tm4 ${T_SOURCE} ) target_link_libraries (dlsim_tm4 - -Wl,--start-group SIMU_COMMON SIMU UTIL SCHED_LIB SCHED_RU_LIB PHY LFDS ${ITTI_LIB} -Wl,--end-group + -Wl,--start-group SIMU_COMMON SIMU UTIL SCHED_LIB SCHED_RU_LIB PHY LFDS ITTI -Wl,--end-group pthread m rt ${CONFIG_LIB} ${ATLAS_LIBRARIES} ${T_LIB} ) @@ -3249,7 +3228,7 @@ add_executable(nr_dlschsim ) target_link_libraries(nr_dlschsim -Wl,--start-group UTIL SIMU_COMMON SIMU PHY_COMMON PHY_NR_COMMON PHY_NR PHY_NR_UE SCHED_NR_LIB CONFIG_LIB MAC_NR_COMMON -Wl,--end-group - m pthread ${ATLAS_LIBRARIES} ${T_LIB} ${ITTI_LIB} dl + m pthread ${ATLAS_LIBRARIES} ${T_LIB} ITTI dl ) add_executable(nr_pbchsim @@ -3264,7 +3243,7 @@ add_executable(nr_pbchsim ) target_link_libraries(nr_pbchsim -Wl,--start-group UTIL SIMU_COMMON SIMU PHY_COMMON PHY_NR_COMMON PHY_NR PHY_NR_UE SCHED_NR_LIB CONFIG_LIB MAC_NR_COMMON -Wl,--end-group - m pthread ${ATLAS_LIBRARIES} ${T_LIB} ${ITTI_LIB} dl + m pthread ${ATLAS_LIBRARIES} ${T_LIB} ITTI dl ) #PUCCH ---> Prashanth @@ -3281,7 +3260,7 @@ add_executable(nr_pucchsim ) target_link_libraries(nr_pucchsim -Wl,--start-group UTIL SIMU_COMMON SIMU PHY_COMMON PHY_NR_COMMON PHY_NR PHY_NR_UE SCHED_NR_LIB CONFIG_LIB MAC_NR_COMMON -Wl,--end-group - m pthread ${ATLAS_LIBRARIES} ${T_LIB} ${ITTI_LIB} dl + m pthread ${ATLAS_LIBRARIES} ${T_LIB} ITTI dl ) add_executable(nr_dlsim @@ -3300,7 +3279,7 @@ add_executable(nr_dlsim ) target_link_libraries(nr_dlsim -Wl,--start-group UTIL SIMU_COMMON SIMU PHY_COMMON PHY_NR_COMMON PHY_NR PHY_NR_UE SCHED_NR_LIB SCHED_NR_UE_LIB MAC_NR MAC_UE_NR MAC_NR_COMMON RRC_LIB NR_RRC_LIB CONFIG_LIB L2_LTE_NR L2_NR HASHTABLE X2AP_ENB X2AP_LIB SECU_CN NGAP_GNB -Wl,--end-group - m pthread ${ATLAS_LIBRARIES} ${T_LIB} ${ITTI_LIB} ${OPENSSL_LIBRARIES} dl + m pthread ${ATLAS_LIBRARIES} ${T_LIB} ITTI ${OPENSSL_LIBRARIES} dl ) target_compile_definitions(nr_dlsim PUBLIC -DPHYSICAL_SIMULATOR) @@ -3319,7 +3298,7 @@ add_executable(nr_prachsim ${SHLIB_LOADER_SOURCES}) target_link_libraries(nr_prachsim -Wl,--start-group UTIL SIMU_COMMON SIMU PHY_COMMON PHY_NR_COMMON PHY_NR PHY_RU PHY_NR_UE MAC_NR_COMMON SCHED_NR_LIB SCHED_NR_UE_LIB MAC_NR MAC_UE_NR MAC_NR_COMMON RRC_LIB NR_RRC_LIB CONFIG_LIB L2_LTE_NR L2_NR HASHTABLE X2AP_ENB X2AP_LIB SECU_CN NGAP_GNB -Wl,--end-group - m pthread ${ATLAS_LIBRARIES} ${T_LIB} ${ITTI_LIB} ${OPENSSL_LIBRARIES} dl) + m pthread ${ATLAS_LIBRARIES} ${T_LIB} ITTI ${OPENSSL_LIBRARIES} dl) add_executable(nr_ulschsim ${OPENAIR1_DIR}/SIMULATION/NR_PHY/ulschsim.c @@ -3333,7 +3312,7 @@ add_executable(nr_ulschsim ) target_link_libraries(nr_ulschsim -Wl,--start-group UTIL SIMU_COMMON SIMU PHY_COMMON PHY_NR_COMMON PHY_NR PHY_NR_UE SCHED_NR_LIB CONFIG_LIB MAC_NR_COMMON -Wl,--end-group - m pthread ${ATLAS_LIBRARIES} ${T_LIB} ${ITTI_LIB} dl + m pthread ${ATLAS_LIBRARIES} ${T_LIB} ITTI dl ) add_executable(nr_ulsim @@ -3352,7 +3331,7 @@ add_executable(nr_ulsim ) target_link_libraries(nr_ulsim -Wl,--start-group UTIL SIMU_COMMON SIMU PHY_COMMON PHY_NR_COMMON PHY_NR PHY_NR_UE SCHED_NR_LIB SCHED_NR_UE_LIB MAC_NR MAC_UE_NR MAC_NR_COMMON RRC_LIB NR_RRC_LIB CONFIG_LIB L2_LTE_NR L2_NR HASHTABLE X2AP_ENB X2AP_LIB SECU_CN NGAP_GNB -Wl,--end-group - m pthread ${ATLAS_LIBRARIES} ${T_LIB} ${ITTI_LIB} ${OPENSSL_LIBRARIES} dl + m pthread ${ATLAS_LIBRARIES} ${T_LIB} ITTI ${OPENSSL_LIBRARIES} dl ) target_compile_definitions(nr_ulsim PUBLIC -DPHYSICAL_SIMULATOR) @@ -3374,7 +3353,7 @@ foreach(myExe dlsim dlsim_tm7 ulsim pbchsim scansim mbmssim pdcchsim pucchsim pr ${NFAPI_USER_DIR}/nfapi.c ) target_link_libraries (${myExe} - -Wl,--start-group SIMU_COMMON SIMU UTIL SCHED_LIB SCHED_RU_LIB SCHED_UE_LIB PHY_COMMON PHY_NR_COMMON PHY PHY_UE PHY_RU LFDS ${ITTI_LIB} LFDS7 -Wl,--end-group + -Wl,--start-group SIMU_COMMON SIMU UTIL SCHED_LIB SCHED_RU_LIB SCHED_UE_LIB PHY_COMMON PHY_NR_COMMON PHY PHY_UE PHY_RU LFDS ITTI LFDS7 -Wl,--end-group pthread m rt ${CONFIG_LIB} ${ATLAS_LIBRARIES} ${XFORMS_LIBRARIES} ${T_LIB} dl ) @@ -3389,7 +3368,7 @@ add_executable(test_epc_generate_scenario ${OPENAIR3_DIR}/S1AP/s1ap_eNB_defs.h ) target_link_libraries (test_epc_generate_scenario - -Wl,--start-group RRC_LIB S1AP_LIB S1AP_ENB X2AP_LIB X2AP_ENB M2AP_LIB M2AP_ENB M3AP_LIB M3AP_ENB F1AP_LIB F1AP NR_GTPV1U LIB_NAS_UE SECU_CN UTIL HASHTABLE SCTP_CLIENT MME_APP UDP SCHED_LIB PHY LFDS ${ITTI_LIB} ${MSC_LIB} L2 -Wl,--end-group pthread m rt crypt sctp ${LIBXML2_LIBRARIES} ${LIBXSLT_LIBRARIES} ${CRYPTO_LIBRARIES} ${OPENSSL_LIBRARIES} ${CONFIG_LIB} + -Wl,--start-group RRC_LIB S1AP_LIB S1AP_ENB X2AP_LIB X2AP_ENB M2AP_LIB M2AP_ENB M3AP_LIB M3AP_ENB F1AP_LIB F1AP NR_GTPV1U LIB_NAS_UE SECU_CN UTIL HASHTABLE SCTP_CLIENT MME_APP UDP SCHED_LIB PHY LFDS ITTI ${MSC_LIB} L2 -Wl,--end-group pthread m rt crypt sctp ${LIBXML2_LIBRARIES} ${LIBXSLT_LIBRARIES} ${CRYPTO_LIBRARIES} ${OPENSSL_LIBRARIES} ${CONFIG_LIB} ) add_executable(test_epc_play_scenario @@ -3408,7 +3387,7 @@ add_executable(test_epc_play_scenario ) target_include_directories(test_epc_play_scenario PUBLIC /usr/local/share/asn1c) target_link_libraries (test_epc_play_scenario - -Wl,--start-group RRC_LIB S1AP_LIB X2AP_LIB X2AP_ENB M3AP_LIB M3AP_ENB F1AP_LIB F1AP NR_GTPV1U LIB_NAS_UE SECU_CN UTIL HASHTABLE SCTP_CLIENT MME_APP UDP SCHED_LIB PHY_NR_COMMON PHY_COMMON PHY PHY_UE LFDS ${ITTI_LIB} ${MSC_LIB} -Wl,--end-group pthread m rt crypt sctp ${LIBXML2_LIBRARIES} ${LIBXSLT_LIBRARIES} ${CRYPTO_LIBRARIES} ${OPENSSL_LIBRARIES} ${CONFIG_LIB} + -Wl,--start-group RRC_LIB S1AP_LIB X2AP_LIB X2AP_ENB M3AP_LIB M3AP_ENB F1AP_LIB F1AP NR_GTPV1U LIB_NAS_UE SECU_CN UTIL HASHTABLE SCTP_CLIENT MME_APP UDP SCHED_LIB PHY_NR_COMMON PHY_COMMON PHY PHY_UE LFDS ITTI ${MSC_LIB} -Wl,--end-group pthread m rt crypt sctp ${LIBXML2_LIBRARIES} ${LIBXSLT_LIBRARIES} ${CRYPTO_LIBRARIES} ${OPENSSL_LIBRARIES} ${CONFIG_LIB} ) @@ -3564,7 +3543,7 @@ target_compile_definitions(nr-ittisim PUBLIC NEW_GTPU) target_link_libraries (nr-ittisim -Wl,--start-group UTIL HASHTABLE SCTP_CLIENT UDP SCHED_LIB SCHED_RU_LIB SCHED_NR_LIB PHY_NR PHY PHY_COMMON PHY_NR_COMMON PHY_RU LFDS GTPV1U_OCP SECU_CN SECU_OSA - ${ITTI_LIB} ${FLPT_MSG_LIB} ${ASYNC_IF_LIB} ${FLEXRAN_AGENT_LIB} LFDS7 ${MSC_LIB} ${RAL_LIB} ${NAS_SIM_LIB} RRC_LIB NR_RRC_LIB + ITTI ${FLPT_MSG_LIB} ${ASYNC_IF_LIB} ${FLEXRAN_AGENT_LIB} LFDS7 ${MSC_LIB} ${RAL_LIB} ${NAS_SIM_LIB} RRC_LIB NR_RRC_LIB NGAP_LIB NGAP_GNB S1AP_LIB S1AP_ENB L2_LTE_NR L2_NR MAC_NR_COMMON NFAPI_COMMON_LIB NFAPI_LIB NFAPI_VNF_LIB NFAPI_PNF_LIB NFAPI_USER_LIB X2AP_LIB X2AP_ENB F1AP_LIB F1AP M2AP_LIB M2AP_ENB M3AP_LIB M3AP_ENB ${PROTO_AGENT_LIB} ${FSPT_MSG_LIB} PHY_NR_UE SCHED_NR_UE_LIB NR_L2_UE diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c index 3a704c2093..6d851edf17 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c @@ -119,12 +119,14 @@ void dump_mac_stats(gNB_MAC_INST *gNB) UE_id, stats->ulsch_total_bytes_scheduled, stats->ulsch_total_bytes_rx); for (int lc_id = 0; lc_id < 63; lc_id++) { - if (stats->lc_bytes_tx[lc_id] > 0) + if (stats->lc_bytes_tx[lc_id] > 0) { stroff+=sprintf(output+stroff, "UE %d: LCID %d: %d bytes TX\n", UE_id, lc_id, stats->lc_bytes_tx[lc_id]); - LOG_D(NR_MAC, "UE %d: LCID %d: %d bytes TX\n", UE_id, lc_id, stats->lc_bytes_tx[lc_id]); - if (stats->lc_bytes_rx[lc_id] > 0) + LOG_D(NR_MAC, "UE %d: LCID %d: %d bytes TX\n", UE_id, lc_id, stats->lc_bytes_tx[lc_id]); + } + if (stats->lc_bytes_rx[lc_id] > 0) { stroff+=sprintf(output+stroff, "UE %d: LCID %d: %d bytes RX\n", UE_id, lc_id, stats->lc_bytes_rx[lc_id]); - LOG_D(NR_MAC, "UE %d: LCID %d: %d bytes RX\n", UE_id, lc_id, stats->lc_bytes_rx[lc_id]); + LOG_D(NR_MAC, "UE %d: LCID %d: %d bytes RX\n", UE_id, lc_id, stats->lc_bytes_rx[lc_id]); + } } } print_meas(&gNB->eNB_scheduler, "DL & UL scheduling timing stats", NULL, NULL); diff --git a/openair2/PHY_INTERFACE/mac_phy_primitives.c b/openair2/PHY_INTERFACE/mac_phy_primitives.c deleted file mode 100644 index 06e06d096d..0000000000 --- a/openair2/PHY_INTERFACE/mac_phy_primitives.c +++ /dev/null @@ -1,283 +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 - */ - -/*________________________mac_phy_primitives.c________________________ - - Authors : Hicham Anouar, Raymond Knopp - Company : EURECOM - Emails : anouar@eurecom.fr, knopp@eurecom.fr -________________________________________________________________*/ - - -//#include "openair_extern.h" - -#ifdef MAC_CONTEXT -#include "LAYER2/MAC/defs.h" -#include "LAYER2/MAC/extern.h" -//#include "extern.h" -#include "defs.h" -#endif //MAC_CONTEXT - - -//#define DEBUG_UE_DECODE_SACH -//#define DEBUG_NODEB_DECODE_SACH - -#ifdef PHY_CONTEXT -#ifdef PHY_EMUL -#include "extern.h" -#include "SIMULATION/simulation_defs.h" -#else //PHY_EMUL -#include "MAC_INTERFACE/extern.h" -#endif //PHY_EMUL - -void clear_macphy_data_req(unsigned char Mod_id) -{ - //msg("CLEAR DATA_REQ\n"); - unsigned char i; - - Macphy_req_table[Mod_id].Macphy_req_cnt = 0; - - for (i=0; iTime_alloc==Phy2->Time_alloc && Phy1->Freq_alloc==Phy2->Freq_alloc)// && Phy1->Coding_fmt==Phy2->Coding_fmt && Phy1->Seq_index==Phy2->Seq_index) - return 1; - else - return 0; - -} -*/ - -MACPHY_DATA_REQ_TABLE_ENTRY* find_data_req_entry(unsigned char Mod_id,MACPHY_REQ_ENTRY_KEY *Search_key) -{ - - unsigned char i; - - //msg("[MAC_PHY]MAC_PHY_REQUEST_CNT=%d\n",Macphy_req_table.Macphy_req_cnt); - if (Macphy_req_table[Mod_id].Macphy_req_cnt > 0) { -#ifdef DEBUG_PHY - // msg("[MACPHY_FIND_REQ] SEARCH KEY=%d\n",Search_key->Key_type); -#endif //DEBUG_PHY - //msg("[MACPHY_FIND_REQ] SEARCH KEY=%d, NB_REQ_MAX=%d\n",Search_key->Key_type,NB_REQ_MAX); - - switch(Search_key->Key_type) { - case PDU_TYPE_KEY: - for(i=0; iKey.Pdu_type) && - (Macphy_req_table[Mod_id].Macphy_req_table_entry[i].Active == 1) ) { - //msg("[MACPHY_FIND] MACPHY_req_table_entry=%p,idx=%d,Phy_resources %p", &Macphy_req_table.Macphy_req_table_entry[i],i,Macphy_req_table.Macphy_req_table_entry[i].Macphy_data_req.Phy_Resources_Entry); - return(&Macphy_req_table[Mod_id].Macphy_req_table_entry[i]); - } - } - - break; - /* - case LCHAN_KEY: - for(i=0;iKey.Lchan_id->Index) && - (Macphy_req_table[Mod_id].Macphy_req_table_entry[i].Active == 1) ) - return(&Macphy_req_table[Mod_id].Macphy_req_table_entry[i]); - } - break; - - case PHY_RESOURCES_KEY: - for(i=0;iTime_alloc == - Search_key->Key.Phy_resources.Time_alloc ) - &&( Macphy_req_table[Mod_id].Macphy_req_table_entry[i].Macphy_data_req.Phy_resources->Freq_alloc == - Search_key->Key.Phy_resources.Freq_alloc ) - &&( Macphy_req_table[Mod_id].Macphy_req_table_entry[i].Macphy_data_req.CH_index == - Search_key->CH_index ) - && ( Macphy_req_table[Mod_id].Macphy_req_table_entry[i].Macphy_data_req.Direction == RX)) - return(&Macphy_req_table[Mod_id].Macphy_req_table_entry[i]); - } - break; - */ - } - } - -#ifndef PHY_EMUL - // msg("[PHY][PHY_MAC] Frame %d : No data request\n",mac_xface->frame); -#endif //PHY_EMUL - - - return (MACPHY_DATA_REQ_TABLE_ENTRY*)0; - -} - - - - - - -void print_active_requests(unsigned char Mod_id) -{ - - int i; - msg("_________________________INST %d , FRAME %d ACTIVE_REQUESTS_________________\n",Mod_id,mac_xface->frame); - - for (i=0; iTime_alloc, - // Macphy_req_table[Mod_id].Macphy_req_table_entry[i].Macphy_data_req.Phy_resources->Freq_alloc); - //if(Macphy_req_table[Mod_id].Macphy_req_table_entry[i].Macphy_data_req.Pdu_type==RACH) - //msg("[RACH_REQ] Rach_pdu %p, Payload %p\n",Macphy_req_table[Mod_id].Macphy_req_table_entry[i].Macphy_data_req.Dir.Req_rx.Pdu.Rach_pdu, - // Macphy_req_table[Mod_id].Macphy_req_table_entry[i].Macphy_data_req.Dir.Req_rx.Pdu.Rach_pdu->Rach_payload); - - } - } -} - - -/*___________________________________________________________________________________________________*/ -#define RCNT Macphy_req_table[Mod_id].Macphy_req_cnt - -MACPHY_DATA_REQ *new_macphy_data_req(unsigned char Mod_id) -{ - /*___________________________________________________________________________________________________*/ - unsigned char i; - - - - for (i=0; iframe,Mod_id,i); - // Macphy_req_table[Mod_id].Macphy_req_table_entry[i%NB_REQ_MAX].Macphy_data_req.Phy_resources=(PHY_RESOURCES*)malloc16(sizeof(PHY_RESOURCES)); - return(&Macphy_req_table[Mod_id].Macphy_req_table_entry[i%NB_REQ_MAX].Macphy_data_req); - } - } - - msg("[OPENAIR][MAC][ERROR] frame %d: No more DATA_REQ !!!!\n",mac_xface->frame); - - print_active_requests(Mod_id); - mac_xface->macphy_exit("new_macphy_data_req: no more DATA_REQ"); - //rt_sleep(nano2count(2000)); - - return((MACPHY_DATA_REQ*)0); -} - - -#endif //PHY_CONTEXT - -#ifdef MAC_CONTEXT -#include "LAYER2/MAC/extern.h" - -// Function called by PHY to indicate available data/measurements for MAC - -/*___________________________________________________________________________________________________*/ -void macphy_data_ind(unsigned char Mod_id,unsigned char Pdu_type,void *pdu,unsigned short rnti) -{ - /*___________________________________________________________________________________________________*/ - //msg("[OPENAIR][MACPHY] Calling mac_resp In\n"); - - int i; - - // if (Req_rx->crc_status[0]!= -1) { //CRC_STATUS - - // msg("[OPENAIR][MACPHY] Calling mac_indicate In\n"); - // Req_rx->Meas.UL_meas=&UL_meas[Mod_id]; - // Req_rx->Meas.DL_meas=&DL_meas[Mod_id]; - - switch (Pdu_type) { - case ULSCH: - - // msg("[OPENAIR][MACPHY] Received RACH, Sending to MAC\n"); - nodeb_decode_ulsch(Mod_id,(ULSCH_PDU *)pdu,rnti); - - break; - - case DLSCH: -#ifdef DEBUG_UE_DECODE_SACH - msg("[MAC][UE][MAC_PHY] TTI %d Inst %d\n",mac_xface->frame,Mod_id); -#endif - - // ue_decode_dlsch(Mod_id-NB_CH_INST, - // (DLSCH_PDU *)pdu,rnti); - - break; - - default: - break; - } - - // msg("Freeing Req %p\n",Macphy_data_req_table_entry); - // } - -} - - - - - -/*PHY_RESOURCES_TABLE_ENTRY *new_phy_resources() { - - - unsigned char i; - - //msg("[OPENAIR][PHY][MAC Interface] New Phy Resource, cnt %d\n",Phy_resources_table.Phy_resources_cnt); - - for (i=0;i Date: Sun, 25 Jul 2021 20:49:31 +0200 Subject: [PATCH 56/91] overkilling: oai support multiple versions of ubuntu --- cmake_targets/CMakeLists.txt | 59 ++++++++++++++++++------------------ 1 file changed, 30 insertions(+), 29 deletions(-) diff --git a/cmake_targets/CMakeLists.txt b/cmake_targets/CMakeLists.txt index a8c33139d9..0460816ff2 100644 --- a/cmake_targets/CMakeLists.txt +++ b/cmake_targets/CMakeLists.txt @@ -89,8 +89,8 @@ if ("${NETTLE_VERSION_MAJOR}" STREQUAL "" OR "${NETTLE_VERSION_MINOR}" STREQUAL message( FATAL_ERROR "The nettle version not detected properly. Try to run build_oai -I again" ) endif() -add_compile_definitions("NETTLE_VERSION_MAJOR=${NETTLE_VERSION_MAJOR}") -add_compile_definitions("NETTLE_VERSION_MINOR=${NETTLE_VERSION_MINOR}") +add_definitions("-DNETTLE_VERSION_MAJOR=${NETTLE_VERSION_MAJOR}") +add_definitions("-DNETTLE_VERSION_MINOR=${NETTLE_VERSION_MINOR}") pkg_search_module(XPM xpm) if(NOT ${XPM_FOUND}) @@ -163,7 +163,7 @@ if (CUDA_FOUND) message ("cuda include ${CUDA_INCLUDE_DIRS}") message ("cuda library ${CUDA_LIBRARY_DIRS}") - add_compile_definitions("-L/usr/local/cuda/lib64") + add_definitions("-L/usr/local/cuda/lib64") SET(CUDA_NVCC_FLAGS "${CUDA_NVCC_FLAGS};-arch=sm_60;") @@ -190,7 +190,7 @@ macro(add_option name val helpstr) set(value ${val}) endif() set(${name} ${value} CACHE STRING "${helpstr}") - add_compile_definitions("${name}=${value}") + add_definitions("-D${name}=${value}") endmacro(add_option) macro(add_boolean_option name val helpstr) @@ -202,7 +202,7 @@ macro(add_boolean_option name val helpstr) set(${name} ${value} CACHE STRING "${helpstr}") set_property(CACHE ${name} PROPERTY TYPE BOOL) if (${value}) - add_compile_definitions("${name}") + add_definitions("-D${name}") endif (${value}) endmacro(add_boolean_option) @@ -213,7 +213,7 @@ macro(add_integer_option name val helpstr) set(value ${val}) endif() set(${name} ${value} CACHE STRING "${helpstr}") - add_compile_definitions("${name}=${value}") + add_definitions("-D${name}=${value}") endmacro(add_integer_option) macro(add_list1_option name val helpstr) @@ -225,7 +225,7 @@ macro(add_list1_option name val helpstr) set(${name} ${value} CACHE STRING "${helpstr}") set_property(CACHE ${name} PROPERTY STRINGS ${ARGN}) if(NOT "${value}" STREQUAL "False") - add_compile_definitions("${name}=${value}") + add_definitions("-D${name}=${value}") endif() endmacro(add_list1_option) @@ -238,7 +238,7 @@ macro(add_list2_option name val helpstr) set(${name} ${value} CACHE STRING "${helpstr}") set_property(CACHE ${name} PROPERTY STRINGS ${ARGN}) if(NOT "${value}" STREQUAL "False") - add_compile_definitions("${value}=1") + add_definitions("-D${value}=1") endif() endmacro(add_list2_option) @@ -251,7 +251,7 @@ macro(add_list_string_option name val helpstr) set(${name} ${value} CACHE STRING "${helpstr}") set_property(CACHE ${name} PROPERTY STRINGS ${ARGN}) if(NOT "${value}" STREQUAL "False") - add_compile_definitions("${name}=\"${value}\"") + add_definitions("-D${name}=\"${value}\"") endif() endmacro(add_list_string_option) @@ -308,18 +308,18 @@ endif() # # add autotools definitions that were maybe used! -add_compile_definitions(STDC_HEADERS=1 HAVE_SYS_TYPES_H=1 HAVE_SYS_STAT_H=1 HAVE_STRING_H=1 HAVE_MEMORY_H=1 HAVE_STRINGS_H=1 HAVE_INTTYPES_H=1 HAVE_STDINT_H=1 HAVE_UNISTD_H=1 HAVE_FCNTL_H=1 HAVE_ARPA_INET_H=1 HAVE_SYS_TIME_H=1 HAVE_SYS_SOCKET_H=1 HAVE_STRERROR=1 HAVE_SOCKET=1 HAVE_MEMSET=1 HAVE_GETTIMEOFDAY=1 HAVE_STDLIB_H=1 HAVE_MALLOC=1 HAVE_LIBSCTP=1) +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_compile_options(-pipe -Wno-packed-bitfield-compat -fPIC -Wall -fno-strict-aliasing -rdynamic) +set(commonOpts "-pipe -Wno-packed-bitfield-compat -fPIC -Wall -fno-strict-aliasing -rdynamic") set(MKVER "'MAKE_VERSION(a,b,c)=((a)*256+(b)*16+c)'") set(CMAKE_C_FLAGS - "${CMAKE_C_FLAGS} ${C_FLAGS_PROCESSOR} -std=gnu99 -funroll-loops -D${MKVER}") + "${CMAKE_C_FLAGS} ${C_FLAGS_PROCESSOR} ${commonOpts} -std=gnu99 -funroll-loops -D${MKVER}") set(CMAKE_CXX_FLAGS - "${CMAKE_CXX_FLAGS} ${C_FLAGS_PROCESSOR} -std=c++11 -D${MKVER}") + "${CMAKE_CXX_FLAGS} ${C_FLAGS_PROCESSOR} ${commonOpts} -std=c++11 -D${MKVER}") if (CUDA_FOUND) - add_compile_definitions(CUDA_FLAG ) + add_definitions(-D CUDA_FLAG ) endif() if (SANITIZE_ADDRESS) @@ -327,7 +327,7 @@ if (SANITIZE_ADDRESS) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address -fno-common") endif () -add_compile_definitions("ASN_DISABLE_OER_SUPPORT") +add_definitions("-DASN_DISABLE_OER_SUPPORT") ######################### set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -ggdb3 -Wl,-rpath -Wl,${CMAKE_CURRENT_BINARY_DIR}") @@ -373,10 +373,11 @@ endif() # Below is a hard-coded info set (FIRMWARE_VERSION "No svn information") -add_compile_definitions("FIRMWARE_VERSION=\"${FIRMWARE_VERSION}\"") -add_compile_definitions("PACKAGE_VERSION=\"Branch: ${GIT_BRANCH} Abrev. Hash: ${GIT_COMMIT_HASH} Date: ${GIT_COMMIT_DATE}\"") -add_compile_definitions("PACKAGE_BUGREPORT=\"openair4g-devel@lists.eurecom.fr\"") -#add_compile_definitions("EMIT_ASN_DEBUG=1") +add_definitions("-DFIRMWARE_VERSION=\"${FIRMWARE_VERSION}\"") +add_definitions("-DPACKAGE_VERSION=\"Branch: ${GIT_BRANCH} Abrev. Hash: ${GIT_COMMIT_HASH} Date: ${GIT_COMMIT_DATE}\"") +add_definitions("-DPACKAGE_BUGREPORT=\"openair4g-devel@lists.eurecom.fr\"") +#add_definitions("-DEMIT_ASN_DEBUG=1") + # Debug related options ######################################### @@ -424,7 +425,7 @@ set (RRC_ASN1_VERSION "Rel15") make_version(LTE_RRC_VERSION 15 6 0) set (RRC_GRAMMAR ${OPENAIR2_DIR}/RRC/LTE/MESSAGES/asn1c/ASN1_files/lte-rrc-15.6.0.asn1) -add_compile_definitions(LTE_RRC_VERSION=${LTE_RRC_VERSION}) +add_definitions(-DLTE_RRC_VERSION=${LTE_RRC_VERSION}) set (RRC_FULL_DIR ${asn1_generated_dir}/RRC_${RRC_ASN1_VERSION}) # Warning: if you modify ASN.1 source file to generate new C files, cmake should be re-run instead of make @@ -456,7 +457,7 @@ include_directories ("${RRC_FULL_DIR}") set (NR_RRC_ASN1_VERSION "NR_Rel16" ) make_version(NR_RRC_VERSION 16 1 0) set (NR_RRC_GRAMMAR ${OPENAIR2_DIR}/RRC/NR/MESSAGES/asn1c/ASN1_files/nr-rrc-16.1.0.asn1) -add_compile_definitions(NR_RRC_VERSION=${NR_RRC_VERSION}) +add_definitions(-DNR_RRC_VERSION=${NR_RRC_VERSION}) set (NR_RRC_FULL_DIR ${asn1_generated_dir}/RRC_${NR_RRC_ASN1_VERSION}) # Warning: if you modify ASN.1 source file to generate new C files, cmake should be re-run instead of make @@ -491,7 +492,7 @@ set(S1AP_DIR ${OPENAIR3_DIR}/S1AP) make_version(S1AP_VERSION 15 6 0) set(S1AP_ASN_FILES "s1ap-15.6.0.asn1") -add_compile_definitions(S1AP_VERSION=${S1AP_VERSION}) +add_definitions(-DS1AP_VERSION=${S1AP_VERSION}) set(S1AP_ASN_DIR ${S1AP_DIR}/MESSAGES/ASN1/${S1AP_RELEASE}) set(S1AP_C_DIR ${asn1_generated_dir}/S1AP_${S1AP_RELEASE}) @@ -548,7 +549,7 @@ set(NGAP_DIR ${OPENAIR3_DIR}/NGAP) make_version(NGAP_VERSION 15 8 0) set(NGAP_ASN_FILES "ngap-15.8.0.asn1") -add_compile_definitions(NGAP_VERSION=${NGAP_VERSION}) +add_definitions(-DNGAP_VERSION=${NGAP_VERSION}) set(NGAP_ASN_DIR ${NGAP_DIR}/MESSAGES/ASN1/ASN1_files) set(NGAP_C_DIR ${asn1_generated_dir}/NGAP_${NGAP_RELEASE}) @@ -615,7 +616,7 @@ elseif (${M2AP_RELEASE} STREQUAL "R15") make_version(M2AP_VERSION 15 1 0) set(M2AP_ASN_FILES m2ap-15.1.0.asn1) endif(${M2AP_RELEASE} STREQUAL "R8") -add_compile_definitions(M2AP_VERSION=${M2AP_VERSION}) +add_definitions(-DM2AP_VERSION=${M2AP_VERSION}) set(M2AP_ASN_DIR ${M2AP_DIR}/MESSAGES/ASN1/${M2AP_RELEASE}) set(M2AP_C_DIR ${asn1_generated_dir}/M2AP_${M2AP_RELEASE}) @@ -688,7 +689,7 @@ elseif (${M3AP_RELEASE} STREQUAL "R15") make_version(M3AP_VERSION 15 1 0) set(M3AP_ASN_FILES m3ap-15.1.0.asn1) endif(${M3AP_RELEASE} STREQUAL "R8") -add_compile_definitions(M3AP_VERSION=${M3AP_VERSION}) +add_definitions(-DM3AP_VERSION=${M3AP_VERSION}) set(M3AP_ASN_DIR ${M3AP_DIR}/MESSAGES/ASN1/${M3AP_RELEASE}) set(M3AP_C_DIR ${asn1_generated_dir}/M3AP_${M3AP_RELEASE}) @@ -746,7 +747,7 @@ set(X2AP_DIR ${OPENAIR2_DIR}/X2AP) make_version(X2AP_VERSION 15 6 0) set(X2AP_ASN_FILES x2ap-15.6.0.asn1) -add_compile_definitions(X2AP_VERSION=${X2AP_VERSION}) +add_definitions(-DX2AP_VERSION=${X2AP_VERSION}) set(X2AP_ASN_DIR ${X2AP_DIR}/MESSAGES/ASN1/${X2AP_RELEASE}) set(X2AP_C_DIR ${asn1_generated_dir}/X2AP_${X2AP_RELEASE}) # Warning: if you modify ASN.1 source file to generate new C files, cmake should be re-run instead of make @@ -799,7 +800,7 @@ if (${F1AP_RELEASE} STREQUAL "R16") make_version(F1AP_VERSION 16 3 1) set (ASN1RELDIR R16.3.1) endif(${F1AP_RELEASE} STREQUAL "R16") -add_compile_definitions(F1AP_VERSION=${F1AP_VERSION}) +add_definitions(-DF1AP_VERSION=${F1AP_VERSION}) set(F1AP_ASN_DIR ${F1AP_DIR}/MESSAGES/ASN1/${ASN1RELDIR}) set(F1AP_ASN_FILES ${F1AP_ASN_DIR}/F1AP-CommonDataTypes.asn @@ -2582,7 +2583,7 @@ include_directories(${NAS_SRC}UE/ESM) include_directories(${NAS_SRC}UE/ESM/SAP) # nbiot -add_compile_definitions("NUMBER_OF_UE_MAX_NB_IoT=16") +add_definitions("-DNUMBER_OF_UE_MAX_NB_IoT=16") set (NBIOT_SOURCES ${OPENAIR2_DIR}/ENB_APP/NB_IoT_config.c ) @@ -2761,7 +2762,7 @@ add_custom_target ( ) # Hack on a test of asn1c version (already dirty) -add_compile_definitions(ASN1_MINIMUM_VERSION=924) +add_definitions(-DASN1_MINIMUM_VERSION=924) ################################# # add executables for operation From 4a5a73bd9cd5aa369564ca7f7516e8bf487eac96 Mon Sep 17 00:00:00 2001 From: Laurent OpenCells Date: Sun, 25 Jul 2021 23:49:41 +0200 Subject: [PATCH 57/91] overkilling: oai support multiple versions of ubuntu --- cmake_targets/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake_targets/CMakeLists.txt b/cmake_targets/CMakeLists.txt index 0460816ff2..394dda5ea2 100644 --- a/cmake_targets/CMakeLists.txt +++ b/cmake_targets/CMakeLists.txt @@ -334,7 +334,7 @@ set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -ggdb3 -Wl,-rpath -Wl,${C ######################### # set a flag for changes in the source code # these changes are related to hardcoded path to include .h files -set(debugOpt "-ggdb3 -feliminate-dwarf2-dups -DMALLOC_CHECK_=3 -fno-delete-null-pointer-checks") +set(debugOpt "-ggdb3 -DMALLOC_CHECK_=3 -fno-delete-null-pointer-checks") set(CMAKE_C_FLAGS_DEBUG "${debugOpt} -Og") set(CMAKE_C_FLAGS_RELWITHDEBINFO "${debugOpt} -O2") set(CMAKE_C_FLAGS_RELEASE "-O3") From 17ee4648c71d876f69f983021734f827fde7fa58 Mon Sep 17 00:00:00 2001 From: francescomani Date: Mon, 26 Jul 2021 11:47:32 +0200 Subject: [PATCH 58/91] fixes in ssb rsrp functions at ue --- openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c | 2 +- openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c | 3 ++- openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c | 2 +- openair2/RRC/NR/rrc_gNB_reconfig.c | 1 + 4 files changed, 5 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 fdf20aa6c3..26d0f370cf 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c @@ -2331,8 +2331,8 @@ uint8_t get_ssb_rsrp_payload(NR_UE_MAC_INST_t *mac, temp_payload |= (rsrp_idx<csi_part1_payload = temp_payload; return bits; diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c index 823e74efb4..b6dbe84d5d 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c @@ -1851,7 +1851,8 @@ void nr_ue_pucch_scheduler(module_id_t module_idP, frame_t frameP, int slotP, in } // CSI - O_CSI = nr_get_csi_measurements(mac, frameP, slotP, pucch); + if (mac->ra.ra_state == RA_SUCCEEDED) + O_CSI = nr_get_csi_measurements(mac, frameP, slotP, pucch); // ACKNACK O_ACK = get_downlink_ack(mac, frameP, slotP, pucch); diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c index 2f4b6ef2c2..c69b254992 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c @@ -2077,7 +2077,7 @@ void nr_csirs_scheduling(int Mod_idP, if((frame*n_slots_frame+slot-offset)%period == 0) { - LOG_I(MAC,"Scheduling CSI-RS in frame %d slot %d\n",frame,slot); + LOG_D(MAC,"Scheduling CSI-RS in frame %d slot %d\n",frame,slot); nfapi_nr_dl_tti_request_pdu_t *dl_tti_csirs_pdu = &dl_req->dl_tti_pdu_list[dl_req->nPDUs]; memset((void*)dl_tti_csirs_pdu,0,sizeof(nfapi_nr_dl_tti_request_pdu_t)); diff --git a/openair2/RRC/NR/rrc_gNB_reconfig.c b/openair2/RRC/NR/rrc_gNB_reconfig.c index e983627b56..20ec2b2bdb 100644 --- a/openair2/RRC/NR/rrc_gNB_reconfig.c +++ b/openair2/RRC/NR/rrc_gNB_reconfig.c @@ -1204,6 +1204,7 @@ void fill_default_secondaryCellGroup(NR_ServingCellConfigCommon_t *servingcellco csires1->resourceType = NR_CSI_ResourceConfig__resourceType_periodic; ASN_SEQUENCE_ADD(&csi_MeasConfig->csi_ResourceConfigToAddModList->list,csires1); + csi_MeasConfig->csi_ReportConfigToAddModList = calloc(1,sizeof(*csi_MeasConfig->csi_ReportConfigToAddModList)); csi_MeasConfig->csi_ReportConfigToReleaseList = NULL; NR_CSI_ReportConfig_t *csirep1 = calloc(1,sizeof(*csirep1)); From d2127b65f36f54bd87cd932d85701b5239b1c73c Mon Sep 17 00:00:00 2001 From: francescomani Date: Tue, 15 Jun 2021 18:04:06 +0200 Subject: [PATCH 59/91] flexible csi configuration including do_csirs config parameter --- openair1/SIMULATION/NR_PHY/dlsim.c | 2 +- openair1/SIMULATION/NR_PHY/ulsim.c | 2 +- openair2/COMMON/rrc_messages_types.h | 1 + openair2/GNB_APP/gnb_config.c | 2 + openair2/GNB_APP/gnb_paramdef.h | 7 +- openair2/LAYER2/NR_MAC_gNB/config.c | 2 +- .../NR_MAC_gNB/gNB_scheduler_primitives.c | 301 +++++++------- openair2/RRC/NR/nr_rrc_defs.h | 1 + openair2/RRC/NR/nr_rrc_proto.h | 8 +- openair2/RRC/NR/rrc_gNB.c | 1 + openair2/RRC/NR/rrc_gNB_nsa.c | 2 + openair2/RRC/NR/rrc_gNB_reconfig.c | 387 ++++++++++++------ 12 files changed, 435 insertions(+), 281 deletions(-) diff --git a/openair1/SIMULATION/NR_PHY/dlsim.c b/openair1/SIMULATION/NR_PHY/dlsim.c index 6cacc960b1..cfe89ce3e9 100644 --- a/openair1/SIMULATION/NR_PHY/dlsim.c +++ b/openair1/SIMULATION/NR_PHY/dlsim.c @@ -758,7 +758,7 @@ int main(int argc, char **argv) prepare_scd(scd); - fill_default_secondaryCellGroup(scc, scd, secondaryCellGroup, 0, 1, n_tx, 0, 0); + fill_default_secondaryCellGroup(scc, scd, secondaryCellGroup, 0, 1, n_tx, 0, 0, 0); /* RRC parameter validation for secondaryCellGroup */ fix_scd(scd); diff --git a/openair1/SIMULATION/NR_PHY/ulsim.c b/openair1/SIMULATION/NR_PHY/ulsim.c index 6fff778bc0..7892833d31 100644 --- a/openair1/SIMULATION/NR_PHY/ulsim.c +++ b/openair1/SIMULATION/NR_PHY/ulsim.c @@ -697,7 +697,7 @@ int main(int argc, char **argv) prepare_scd(scd); - fill_default_secondaryCellGroup(scc, scd, secondaryCellGroup, 0, 1, n_tx, 0, 0); + fill_default_secondaryCellGroup(scc, scd, secondaryCellGroup, 0, 1, n_tx, 0, 0, 0); // xer_fprint(stdout, &asn_DEF_NR_CellGroupConfig, (const void*)secondaryCellGroup); diff --git a/openair2/COMMON/rrc_messages_types.h b/openair2/COMMON/rrc_messages_types.h index 220ef60b3d..ca4011231a 100644 --- a/openair2/COMMON/rrc_messages_types.h +++ b/openair2/COMMON/rrc_messages_types.h @@ -411,6 +411,7 @@ typedef struct NRRrcConfigurationReq_s { int ssb_SubcarrierOffset; int pdsch_AntennaPorts; int pusch_AntennaPorts; + int do_CSIRS; int pusch_TargetSNRx10; int pucch_TargetSNRx10; } gNB_RrcConfigurationReq; diff --git a/openair2/GNB_APP/gnb_config.c b/openair2/GNB_APP/gnb_config.c index 94337ecb58..f0c83715dc 100644 --- a/openair2/GNB_APP/gnb_config.c +++ b/openair2/GNB_APP/gnb_config.c @@ -1045,6 +1045,8 @@ void RCconfig_NRRRC(MessageDef *msg_p, uint32_t i, gNB_RRC_INST *rrc) { NRRRC_CONFIGURATION_REQ (msg_p).pdsch_AntennaPorts = *GNBParamList.paramarray[i][GNB_PDSCH_ANTENNAPORTS_IDX].iptr; printf("pusch_AntennaPorts %d\n",*GNBParamList.paramarray[i][GNB_PUSCH_ANTENNAPORTS_IDX].iptr); NRRRC_CONFIGURATION_REQ (msg_p).pusch_AntennaPorts = *GNBParamList.paramarray[i][GNB_PUSCH_ANTENNAPORTS_IDX].iptr; + printf("Do CSI-RS %d\n",*GNBParamList.paramarray[i][GNB_DO_CSIRS_IDX].iptr); + NRRRC_CONFIGURATION_REQ (msg_p).do_CSIRS = *GNBParamList.paramarray[i][GNB_DO_CSIRS_IDX].iptr; NRRRC_CONFIGURATION_REQ (msg_p).scc = scc; NRRRC_CONFIGURATION_REQ (msg_p).scd = scd; diff --git a/openair2/GNB_APP/gnb_paramdef.h b/openair2/GNB_APP/gnb_paramdef.h index 6d9c9b8342..e2a666c16a 100644 --- a/openair2/GNB_APP/gnb_paramdef.h +++ b/openair2/GNB_APP/gnb_paramdef.h @@ -116,6 +116,7 @@ typedef enum { #define GNB_CONFIG_STRING_SSBSUBCARRIEROFFSET "ssb_SubcarrierOffset" #define GNB_CONFIG_STRING_PDSCHANTENNAPORTS "pdsch_AntennaPorts" #define GNB_CONFIG_STRING_PUSCHANTENNAPORTS "pusch_AntennaPorts" +#define GNB_CONFIG_STRING_DOCSIRS "do_CSIRS" #define GNB_CONFIG_STRING_NRCELLID "nr_cellid" /*-----------------------------------------------------------------------------------------------------------------------------------------*/ @@ -140,7 +141,8 @@ typedef enum { {GNB_CONFIG_STRING_SSBSUBCARRIEROFFSET, NULL, 0, iptr:NULL, defintval:31, TYPE_INT, 0}, \ {GNB_CONFIG_STRING_PDSCHANTENNAPORTS, NULL, 0, iptr:NULL, defintval:1, TYPE_INT, 0}, \ {GNB_CONFIG_STRING_PUSCHANTENNAPORTS, NULL, 0, iptr:NULL, defintval:1, TYPE_INT, 0}, \ -{GNB_CONFIG_STRING_NRCELLID , NULL, 0, u64ptr:NULL, defint64val:1, TYPE_UINT64, 0}, \ +{GNB_CONFIG_STRING_DOCSIRS, NULL, 0, iptr:NULL, defintval:0, TYPE_INT, 0}, \ +{GNB_CONFIG_STRING_NRCELLID , NULL, 0, u64ptr:NULL, defint64val:1, TYPE_UINT64, 0}, \ } #define GNB_GNB_ID_IDX 0 @@ -160,7 +162,8 @@ typedef enum { #define GNB_SSB_SUBCARRIEROFFSET_IDX 14 #define GNB_PDSCH_ANTENNAPORTS_IDX 15 #define GNB_PUSCH_ANTENNAPORTS_IDX 16 -#define GNB_NRCELLID_IDX 17 +#define GNB_DO_CSIRS_IDX 17 +#define GNB_NRCELLID_IDX 18 #define TRACKING_AREA_CODE_OKRANGE {0x0001,0xFFFD} #define GNBPARAMS_CHECK { \ diff --git a/openair2/LAYER2/NR_MAC_gNB/config.c b/openair2/LAYER2/NR_MAC_gNB/config.c index 9428853037..f649f818c9 100644 --- a/openair2/LAYER2/NR_MAC_gNB/config.c +++ b/openair2/LAYER2/NR_MAC_gNB/config.c @@ -457,7 +457,7 @@ int rrc_mac_config_req_gNB(module_id_t Mod_idP, ssb_SubcarrierOffset, pdsch_AntennaPorts, pusch_AntennaPorts, - scc); + scc); LOG_D(NR_MAC, "%s() %s:%d RC.nrmac[Mod_idP]->if_inst->NR_PHY_config_req:%p\n", __FUNCTION__, __FILE__, __LINE__, RC.nrmac[Mod_idP]->if_inst->NR_PHY_config_req); // if in nFAPI mode diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c index c69b254992..14fa71bbd4 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c @@ -2055,8 +2055,6 @@ void nr_csirs_scheduling(int Mod_idP, for (int UE_id = UE_list->head; UE_id >= 0; UE_id = UE_list->next[UE_id]) { - NR_NZP_CSI_RS_Resource_t *nzpcsi; - int period, offset; NR_UE_sched_ctrl_t *sched_ctrl = &UE_info->UE_sched_ctrl[UE_id]; NR_CellGroupConfig_t *CellGroup = UE_info->CellGroup[UE_id]; @@ -2065,182 +2063,185 @@ void nr_csirs_scheduling(int Mod_idP, NR_CSI_MeasConfig_t *csi_measconfig = CellGroup->spCellConfig->spCellConfigDedicated->csi_MeasConfig->choice.setup; - nfapi_nr_dl_tti_request_body_t *dl_req = &gNB_mac->DL_req[CC_id].dl_tti_request_body; - NR_BWP_Downlink_t *bwp=CellGroup->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList->list.array[sched_ctrl->active_bwp->bwp_Id-1]; + if (csi_measconfig->nzp_CSI_RS_ResourceToAddModList != NULL) { - AssertFatal(csi_measconfig->nzp_CSI_RS_ResourceToAddModList->list.count>0,"NO CSI report configuration available"); + NR_NZP_CSI_RS_Resource_t *nzpcsi; + int period, offset; - for (int id = 0; id < csi_measconfig->nzp_CSI_RS_ResourceToAddModList->list.count; id++){ - nzpcsi = csi_measconfig->nzp_CSI_RS_ResourceToAddModList->list.array[id]; - NR_CSI_RS_ResourceMapping_t resourceMapping = nzpcsi->resourceMapping; - csi_period_offset(NULL,nzpcsi,&period,&offset); + nfapi_nr_dl_tti_request_body_t *dl_req = &gNB_mac->DL_req[CC_id].dl_tti_request_body; + NR_BWP_Downlink_t *bwp=CellGroup->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList->list.array[sched_ctrl->active_bwp->bwp_Id-1]; - if((frame*n_slots_frame+slot-offset)%period == 0) { + for (int id = 0; id < csi_measconfig->nzp_CSI_RS_ResourceToAddModList->list.count; id++){ + nzpcsi = csi_measconfig->nzp_CSI_RS_ResourceToAddModList->list.array[id]; + NR_CSI_RS_ResourceMapping_t resourceMapping = nzpcsi->resourceMapping; + csi_period_offset(NULL,nzpcsi,&period,&offset); - LOG_D(MAC,"Scheduling CSI-RS in frame %d slot %d\n",frame,slot); + if((frame*n_slots_frame+slot-offset)%period == 0) { - nfapi_nr_dl_tti_request_pdu_t *dl_tti_csirs_pdu = &dl_req->dl_tti_pdu_list[dl_req->nPDUs]; - memset((void*)dl_tti_csirs_pdu,0,sizeof(nfapi_nr_dl_tti_request_pdu_t)); - dl_tti_csirs_pdu->PDUType = NFAPI_NR_DL_TTI_CSI_RS_PDU_TYPE; - dl_tti_csirs_pdu->PDUSize = (uint8_t)(2+sizeof(nfapi_nr_dl_tti_csi_rs_pdu)); + LOG_I(MAC,"Scheduling CSI-RS in frame %d slot %d\n",frame,slot); - nfapi_nr_dl_tti_csi_rs_pdu_rel15_t *csirs_pdu_rel15 = &dl_tti_csirs_pdu->csi_rs_pdu.csi_rs_pdu_rel15; + nfapi_nr_dl_tti_request_pdu_t *dl_tti_csirs_pdu = &dl_req->dl_tti_pdu_list[dl_req->nPDUs]; + memset((void*)dl_tti_csirs_pdu,0,sizeof(nfapi_nr_dl_tti_request_pdu_t)); + dl_tti_csirs_pdu->PDUType = NFAPI_NR_DL_TTI_CSI_RS_PDU_TYPE; + dl_tti_csirs_pdu->PDUSize = (uint8_t)(2+sizeof(nfapi_nr_dl_tti_csi_rs_pdu)); - csirs_pdu_rel15->bwp_size = NRRIV2BW(bwp->bwp_Common->genericParameters.locationAndBandwidth,275); - csirs_pdu_rel15->bwp_start = NRRIV2PRBOFFSET(bwp->bwp_Common->genericParameters.locationAndBandwidth,275); - csirs_pdu_rel15->subcarrier_spacing = bwp->bwp_Common->genericParameters.subcarrierSpacing; - if (bwp->bwp_Common->genericParameters.cyclicPrefix) - csirs_pdu_rel15->cyclic_prefix = *bwp->bwp_Common->genericParameters.cyclicPrefix; - else - csirs_pdu_rel15->cyclic_prefix = 0; + nfapi_nr_dl_tti_csi_rs_pdu_rel15_t *csirs_pdu_rel15 = &dl_tti_csirs_pdu->csi_rs_pdu.csi_rs_pdu_rel15; - csirs_pdu_rel15->start_rb = resourceMapping.freqBand.startingRB; - csirs_pdu_rel15->nr_of_rbs = resourceMapping.freqBand.nrofRBs; - csirs_pdu_rel15->csi_type = 1; // NZP-CSI-RS - csirs_pdu_rel15->symb_l0 = resourceMapping.firstOFDMSymbolInTimeDomain; - if (resourceMapping.firstOFDMSymbolInTimeDomain2) - csirs_pdu_rel15->symb_l1 = *resourceMapping.firstOFDMSymbolInTimeDomain2; - csirs_pdu_rel15->cdm_type = resourceMapping.cdm_Type; - csirs_pdu_rel15->freq_density = resourceMapping.density.present; - if ((resourceMapping.density.present == NR_CSI_RS_ResourceMapping__density_PR_dot5) - && (resourceMapping.density.choice.dot5 == NR_CSI_RS_ResourceMapping__density__dot5_evenPRBs)) - csirs_pdu_rel15->freq_density--; - csirs_pdu_rel15->scramb_id = nzpcsi->scramblingID; - csirs_pdu_rel15->power_control_offset = nzpcsi->powerControlOffset + 8; - if (nzpcsi->powerControlOffsetSS) - csirs_pdu_rel15->power_control_offset_ss = *nzpcsi->powerControlOffsetSS; - else - csirs_pdu_rel15->power_control_offset_ss = 1; // 0 dB - switch(resourceMapping.frequencyDomainAllocation.present){ - case NR_CSI_RS_ResourceMapping__frequencyDomainAllocation_PR_row1: - csirs_pdu_rel15->row = 1; - csirs_pdu_rel15->freq_domain = ((resourceMapping.frequencyDomainAllocation.choice.row1.buf[0])>>4)&0x0f; - for (int rb = csirs_pdu_rel15->start_rb; rb < (csirs_pdu_rel15->start_rb + csirs_pdu_rel15->nr_of_rbs); rb++) - vrb_map[rb] |= (1 << csirs_pdu_rel15->symb_l0); - break; - case NR_CSI_RS_ResourceMapping__frequencyDomainAllocation_PR_row2: - csirs_pdu_rel15->row = 2; - csirs_pdu_rel15->freq_domain = (((resourceMapping.frequencyDomainAllocation.choice.row2.buf[1]>>4)&0x0f) | - ((resourceMapping.frequencyDomainAllocation.choice.row2.buf[0]<<8)&0xff0)); - for (int rb = csirs_pdu_rel15->start_rb; rb < (csirs_pdu_rel15->start_rb + csirs_pdu_rel15->nr_of_rbs); rb++) - vrb_map[rb] |= (1 << csirs_pdu_rel15->symb_l0); - break; - case NR_CSI_RS_ResourceMapping__frequencyDomainAllocation_PR_row4: - csirs_pdu_rel15->row = 4; - csirs_pdu_rel15->freq_domain = ((resourceMapping.frequencyDomainAllocation.choice.row4.buf[0])>>5)&0x07; - for (int rb = csirs_pdu_rel15->start_rb; rb < (csirs_pdu_rel15->start_rb + csirs_pdu_rel15->nr_of_rbs); rb++) - vrb_map[rb] |= (1 << csirs_pdu_rel15->symb_l0); - break; - case NR_CSI_RS_ResourceMapping__frequencyDomainAllocation_PR_other: - csirs_pdu_rel15->freq_domain = ((resourceMapping.frequencyDomainAllocation.choice.other.buf[0])>>2)&0x3f; - // determining the row of table 7.4.1.5.3-1 in 38.211 - switch(resourceMapping.nrofPorts){ - case NR_CSI_RS_ResourceMapping__nrofPorts_p1: - break; - case NR_CSI_RS_ResourceMapping__nrofPorts_p2: - csirs_pdu_rel15->row = 3; - for (int rb = csirs_pdu_rel15->start_rb; rb < (csirs_pdu_rel15->start_rb + csirs_pdu_rel15->nr_of_rbs); rb++) - vrb_map[rb] |= (1 << csirs_pdu_rel15->symb_l0); - break; - case NR_CSI_RS_ResourceMapping__nrofPorts_p4: - csirs_pdu_rel15->row = 5; - for (int rb = csirs_pdu_rel15->start_rb; rb < (csirs_pdu_rel15->start_rb + csirs_pdu_rel15->nr_of_rbs); rb++) - vrb_map[rb] |= ((1 << csirs_pdu_rel15->symb_l0) | (2 << csirs_pdu_rel15->symb_l0)); - break; - case NR_CSI_RS_ResourceMapping__nrofPorts_p8: - if (resourceMapping.cdm_Type == NR_CSI_RS_ResourceMapping__cdm_Type_cdm4_FD2_TD2) { - csirs_pdu_rel15->row = 8; + csirs_pdu_rel15->bwp_size = NRRIV2BW(bwp->bwp_Common->genericParameters.locationAndBandwidth,275); + csirs_pdu_rel15->bwp_start = NRRIV2PRBOFFSET(bwp->bwp_Common->genericParameters.locationAndBandwidth,275); + csirs_pdu_rel15->subcarrier_spacing = bwp->bwp_Common->genericParameters.subcarrierSpacing; + if (bwp->bwp_Common->genericParameters.cyclicPrefix) + csirs_pdu_rel15->cyclic_prefix = *bwp->bwp_Common->genericParameters.cyclicPrefix; + else + csirs_pdu_rel15->cyclic_prefix = 0; + + csirs_pdu_rel15->start_rb = resourceMapping.freqBand.startingRB; + csirs_pdu_rel15->nr_of_rbs = resourceMapping.freqBand.nrofRBs; + csirs_pdu_rel15->csi_type = 1; // NZP-CSI-RS + csirs_pdu_rel15->symb_l0 = resourceMapping.firstOFDMSymbolInTimeDomain; + if (resourceMapping.firstOFDMSymbolInTimeDomain2) + csirs_pdu_rel15->symb_l1 = *resourceMapping.firstOFDMSymbolInTimeDomain2; + csirs_pdu_rel15->cdm_type = resourceMapping.cdm_Type; + csirs_pdu_rel15->freq_density = resourceMapping.density.present; + if ((resourceMapping.density.present == NR_CSI_RS_ResourceMapping__density_PR_dot5) + && (resourceMapping.density.choice.dot5 == NR_CSI_RS_ResourceMapping__density__dot5_evenPRBs)) + csirs_pdu_rel15->freq_density--; + csirs_pdu_rel15->scramb_id = nzpcsi->scramblingID; + csirs_pdu_rel15->power_control_offset = nzpcsi->powerControlOffset + 8; + if (nzpcsi->powerControlOffsetSS) + csirs_pdu_rel15->power_control_offset_ss = *nzpcsi->powerControlOffsetSS; + else + csirs_pdu_rel15->power_control_offset_ss = 1; // 0 dB + switch(resourceMapping.frequencyDomainAllocation.present){ + case NR_CSI_RS_ResourceMapping__frequencyDomainAllocation_PR_row1: + csirs_pdu_rel15->row = 1; + csirs_pdu_rel15->freq_domain = ((resourceMapping.frequencyDomainAllocation.choice.row1.buf[0])>>4)&0x0f; + for (int rb = csirs_pdu_rel15->start_rb; rb < (csirs_pdu_rel15->start_rb + csirs_pdu_rel15->nr_of_rbs); rb++) + vrb_map[rb] |= (1 << csirs_pdu_rel15->symb_l0); + break; + case NR_CSI_RS_ResourceMapping__frequencyDomainAllocation_PR_row2: + csirs_pdu_rel15->row = 2; + csirs_pdu_rel15->freq_domain = (((resourceMapping.frequencyDomainAllocation.choice.row2.buf[1]>>4)&0x0f) | + ((resourceMapping.frequencyDomainAllocation.choice.row2.buf[0]<<8)&0xff0)); + for (int rb = csirs_pdu_rel15->start_rb; rb < (csirs_pdu_rel15->start_rb + csirs_pdu_rel15->nr_of_rbs); rb++) + vrb_map[rb] |= (1 << csirs_pdu_rel15->symb_l0); + break; + case NR_CSI_RS_ResourceMapping__frequencyDomainAllocation_PR_row4: + csirs_pdu_rel15->row = 4; + csirs_pdu_rel15->freq_domain = ((resourceMapping.frequencyDomainAllocation.choice.row4.buf[0])>>5)&0x07; + for (int rb = csirs_pdu_rel15->start_rb; rb < (csirs_pdu_rel15->start_rb + csirs_pdu_rel15->nr_of_rbs); rb++) + vrb_map[rb] |= (1 << csirs_pdu_rel15->symb_l0); + break; + case NR_CSI_RS_ResourceMapping__frequencyDomainAllocation_PR_other: + csirs_pdu_rel15->freq_domain = ((resourceMapping.frequencyDomainAllocation.choice.other.buf[0])>>2)&0x3f; + // determining the row of table 7.4.1.5.3-1 in 38.211 + switch(resourceMapping.nrofPorts){ + case NR_CSI_RS_ResourceMapping__nrofPorts_p1: + break; + case NR_CSI_RS_ResourceMapping__nrofPorts_p2: + csirs_pdu_rel15->row = 3; + for (int rb = csirs_pdu_rel15->start_rb; rb < (csirs_pdu_rel15->start_rb + csirs_pdu_rel15->nr_of_rbs); rb++) + vrb_map[rb] |= (1 << csirs_pdu_rel15->symb_l0); + break; + case NR_CSI_RS_ResourceMapping__nrofPorts_p4: + csirs_pdu_rel15->row = 5; for (int rb = csirs_pdu_rel15->start_rb; rb < (csirs_pdu_rel15->start_rb + csirs_pdu_rel15->nr_of_rbs); rb++) vrb_map[rb] |= ((1 << csirs_pdu_rel15->symb_l0) | (2 << csirs_pdu_rel15->symb_l0)); - } - else{ - int num_k = 0; - for (int k=0; k<6; k++) - num_k+=(((csirs_pdu_rel15->freq_domain)>>k)&0x01); - if(num_k==4) { - csirs_pdu_rel15->row = 6; - for (int rb = csirs_pdu_rel15->start_rb; rb < (csirs_pdu_rel15->start_rb + csirs_pdu_rel15->nr_of_rbs); rb++) - vrb_map[rb] |= (1 << csirs_pdu_rel15->symb_l0); - } - else { - csirs_pdu_rel15->row = 7; + break; + case NR_CSI_RS_ResourceMapping__nrofPorts_p8: + if (resourceMapping.cdm_Type == NR_CSI_RS_ResourceMapping__cdm_Type_cdm4_FD2_TD2) { + csirs_pdu_rel15->row = 8; for (int rb = csirs_pdu_rel15->start_rb; rb < (csirs_pdu_rel15->start_rb + csirs_pdu_rel15->nr_of_rbs); rb++) vrb_map[rb] |= ((1 << csirs_pdu_rel15->symb_l0) | (2 << csirs_pdu_rel15->symb_l0)); } - } - break; - case NR_CSI_RS_ResourceMapping__nrofPorts_p12: - if (resourceMapping.cdm_Type == NR_CSI_RS_ResourceMapping__cdm_Type_cdm4_FD2_TD2) { - csirs_pdu_rel15->row = 10; + else{ + int num_k = 0; + for (int k=0; k<6; k++) + num_k+=(((csirs_pdu_rel15->freq_domain)>>k)&0x01); + if(num_k==4) { + csirs_pdu_rel15->row = 6; + for (int rb = csirs_pdu_rel15->start_rb; rb < (csirs_pdu_rel15->start_rb + csirs_pdu_rel15->nr_of_rbs); rb++) + vrb_map[rb] |= (1 << csirs_pdu_rel15->symb_l0); + } + else { + csirs_pdu_rel15->row = 7; + for (int rb = csirs_pdu_rel15->start_rb; rb < (csirs_pdu_rel15->start_rb + csirs_pdu_rel15->nr_of_rbs); rb++) + vrb_map[rb] |= ((1 << csirs_pdu_rel15->symb_l0) | (2 << csirs_pdu_rel15->symb_l0)); + } + } + break; + case NR_CSI_RS_ResourceMapping__nrofPorts_p12: + if (resourceMapping.cdm_Type == NR_CSI_RS_ResourceMapping__cdm_Type_cdm4_FD2_TD2) { + csirs_pdu_rel15->row = 10; + for (int rb = csirs_pdu_rel15->start_rb; rb < (csirs_pdu_rel15->start_rb + csirs_pdu_rel15->nr_of_rbs); rb++) + vrb_map[rb] |= ((1 << csirs_pdu_rel15->symb_l0) | (2 << csirs_pdu_rel15->symb_l0)); + } + else { + csirs_pdu_rel15->row = 9; + for (int rb = csirs_pdu_rel15->start_rb; rb < (csirs_pdu_rel15->start_rb + csirs_pdu_rel15->nr_of_rbs); rb++) + vrb_map[rb] |= (1 << csirs_pdu_rel15->symb_l0); + } + break; + case NR_CSI_RS_ResourceMapping__nrofPorts_p16: + if (resourceMapping.cdm_Type == NR_CSI_RS_ResourceMapping__cdm_Type_cdm4_FD2_TD2) + csirs_pdu_rel15->row = 12; + else + csirs_pdu_rel15->row = 11; for (int rb = csirs_pdu_rel15->start_rb; rb < (csirs_pdu_rel15->start_rb + csirs_pdu_rel15->nr_of_rbs); rb++) vrb_map[rb] |= ((1 << csirs_pdu_rel15->symb_l0) | (2 << csirs_pdu_rel15->symb_l0)); - } - else { - csirs_pdu_rel15->row = 9; - for (int rb = csirs_pdu_rel15->start_rb; rb < (csirs_pdu_rel15->start_rb + csirs_pdu_rel15->nr_of_rbs); rb++) - vrb_map[rb] |= (1 << csirs_pdu_rel15->symb_l0); - } - break; - case NR_CSI_RS_ResourceMapping__nrofPorts_p16: - if (resourceMapping.cdm_Type == NR_CSI_RS_ResourceMapping__cdm_Type_cdm4_FD2_TD2) - csirs_pdu_rel15->row = 12; - else - csirs_pdu_rel15->row = 11; - for (int rb = csirs_pdu_rel15->start_rb; rb < (csirs_pdu_rel15->start_rb + csirs_pdu_rel15->nr_of_rbs); rb++) - vrb_map[rb] |= ((1 << csirs_pdu_rel15->symb_l0) | (2 << csirs_pdu_rel15->symb_l0)); - break; - case NR_CSI_RS_ResourceMapping__nrofPorts_p24: - if (resourceMapping.cdm_Type == NR_CSI_RS_ResourceMapping__cdm_Type_cdm4_FD2_TD2) { - csirs_pdu_rel15->row = 14; - for (int rb = csirs_pdu_rel15->start_rb; rb < (csirs_pdu_rel15->start_rb + csirs_pdu_rel15->nr_of_rbs); rb++) - vrb_map[rb] |= ((3 << csirs_pdu_rel15->symb_l0) | (3 << csirs_pdu_rel15->symb_l1)); - } - else{ - if (resourceMapping.cdm_Type == NR_CSI_RS_ResourceMapping__cdm_Type_cdm8_FD2_TD4) { - csirs_pdu_rel15->row = 15; - for (int rb = csirs_pdu_rel15->start_rb; rb < (csirs_pdu_rel15->start_rb + csirs_pdu_rel15->nr_of_rbs); rb++) - vrb_map[rb] |= (7 << csirs_pdu_rel15->symb_l0); - } - else { - csirs_pdu_rel15->row = 13; + break; + case NR_CSI_RS_ResourceMapping__nrofPorts_p24: + if (resourceMapping.cdm_Type == NR_CSI_RS_ResourceMapping__cdm_Type_cdm4_FD2_TD2) { + csirs_pdu_rel15->row = 14; for (int rb = csirs_pdu_rel15->start_rb; rb < (csirs_pdu_rel15->start_rb + csirs_pdu_rel15->nr_of_rbs); rb++) vrb_map[rb] |= ((3 << csirs_pdu_rel15->symb_l0) | (3 << csirs_pdu_rel15->symb_l1)); } - } - break; - case NR_CSI_RS_ResourceMapping__nrofPorts_p32: - if (resourceMapping.cdm_Type == NR_CSI_RS_ResourceMapping__cdm_Type_cdm4_FD2_TD2) { - csirs_pdu_rel15->row = 17; - for (int rb = csirs_pdu_rel15->start_rb; rb < (csirs_pdu_rel15->start_rb + csirs_pdu_rel15->nr_of_rbs); rb++) - vrb_map[rb] |= ((3 << csirs_pdu_rel15->symb_l0) | (3 << csirs_pdu_rel15->symb_l1)); - } - else{ - if (resourceMapping.cdm_Type == NR_CSI_RS_ResourceMapping__cdm_Type_cdm8_FD2_TD4) { - csirs_pdu_rel15->row = 18; - for (int rb = csirs_pdu_rel15->start_rb; rb < (csirs_pdu_rel15->start_rb + csirs_pdu_rel15->nr_of_rbs); rb++) - vrb_map[rb] |= (7 << csirs_pdu_rel15->symb_l0); + else{ + if (resourceMapping.cdm_Type == NR_CSI_RS_ResourceMapping__cdm_Type_cdm8_FD2_TD4) { + csirs_pdu_rel15->row = 15; + for (int rb = csirs_pdu_rel15->start_rb; rb < (csirs_pdu_rel15->start_rb + csirs_pdu_rel15->nr_of_rbs); rb++) + vrb_map[rb] |= (7 << csirs_pdu_rel15->symb_l0); + } + else { + csirs_pdu_rel15->row = 13; + for (int rb = csirs_pdu_rel15->start_rb; rb < (csirs_pdu_rel15->start_rb + csirs_pdu_rel15->nr_of_rbs); rb++) + vrb_map[rb] |= ((3 << csirs_pdu_rel15->symb_l0) | (3 << csirs_pdu_rel15->symb_l1)); + } } - else { - csirs_pdu_rel15->row = 16; + break; + case NR_CSI_RS_ResourceMapping__nrofPorts_p32: + if (resourceMapping.cdm_Type == NR_CSI_RS_ResourceMapping__cdm_Type_cdm4_FD2_TD2) { + csirs_pdu_rel15->row = 17; for (int rb = csirs_pdu_rel15->start_rb; rb < (csirs_pdu_rel15->start_rb + csirs_pdu_rel15->nr_of_rbs); rb++) vrb_map[rb] |= ((3 << csirs_pdu_rel15->symb_l0) | (3 << csirs_pdu_rel15->symb_l1)); } - } - break; - default: - AssertFatal(1==0,"Invalid number of ports in CSI-RS resource\n"); - } - break; - default: - AssertFatal(1==0,"Invalid freqency domain allocation in CSI-RS resource\n"); + else{ + if (resourceMapping.cdm_Type == NR_CSI_RS_ResourceMapping__cdm_Type_cdm8_FD2_TD4) { + csirs_pdu_rel15->row = 18; + for (int rb = csirs_pdu_rel15->start_rb; rb < (csirs_pdu_rel15->start_rb + csirs_pdu_rel15->nr_of_rbs); rb++) + vrb_map[rb] |= (7 << csirs_pdu_rel15->symb_l0); + } + else { + csirs_pdu_rel15->row = 16; + for (int rb = csirs_pdu_rel15->start_rb; rb < (csirs_pdu_rel15->start_rb + csirs_pdu_rel15->nr_of_rbs); rb++) + vrb_map[rb] |= ((3 << csirs_pdu_rel15->symb_l0) | (3 << csirs_pdu_rel15->symb_l1)); + } + } + break; + default: + AssertFatal(1==0,"Invalid number of ports in CSI-RS resource\n"); + } + break; + default: + AssertFatal(1==0,"Invalid freqency domain allocation in CSI-RS resource\n"); + } + dl_req->nPDUs++; } - dl_req->nPDUs++; } } } } - bool find_free_CCE(module_id_t module_id, sub_frame_t slot, int UE_id){ diff --git a/openair2/RRC/NR/nr_rrc_defs.h b/openair2/RRC/NR/nr_rrc_defs.h index 5fd9b5d638..b92b5defe6 100644 --- a/openair2/RRC/NR/nr_rrc_defs.h +++ b/openair2/RRC/NR/nr_rrc_defs.h @@ -448,6 +448,7 @@ typedef struct { int pusch_AntennaPorts; int pusch_TargetSNRx10; int pucch_TargetSNRx10; + int do_CSIRS; NR_BCCH_DL_SCH_Message_t *siblock1; NR_ServingCellConfigCommon_t *servingcellconfigcommon; NR_PDCCH_ConfigSIB1_t *pdcch_ConfigSIB1; diff --git a/openair2/RRC/NR/nr_rrc_proto.h b/openair2/RRC/NR/nr_rrc_proto.h index 20656deff4..811c7a152f 100644 --- a/openair2/RRC/NR/nr_rrc_proto.h +++ b/openair2/RRC/NR/nr_rrc_proto.h @@ -84,15 +84,19 @@ void fill_default_secondaryCellGroup(NR_ServingCellConfigCommon_t *servingcellco NR_CellGroupConfig_t *secondaryCellGroup, int scg_id, int servCellIndex, - int n_physical_antenna_ports, + int dl_antenna_ports, + int do_csirs, int initial_csi_index, int uid); +void config_csirs(NR_ServingCellConfigCommon_t *servingcellconfigcommon, NR_CSI_MeasConfig_t *csi_MeasConfig, int dl_antenna_ports, int do_csirs); + void fill_default_reconfig(NR_ServingCellConfigCommon_t *servingcellconfigcommon, NR_ServingCellConfig_t *servingcellconfigdedicated, NR_RRCReconfiguration_IEs_t *reconfig, NR_CellGroupConfig_t *secondaryCellGroup, - int n_physical_antenna_ports, + int dl_antenna_ports, + int do_csirs, int initial_csi_index, int uid); diff --git a/openair2/RRC/NR/rrc_gNB.c b/openair2/RRC/NR/rrc_gNB.c index 6ef8149bb1..361017fd9f 100755 --- a/openair2/RRC/NR/rrc_gNB.c +++ b/openair2/RRC/NR/rrc_gNB.c @@ -330,6 +330,7 @@ char openair_rrc_gNB_configuration(const module_id_t gnb_mod_idP, gNB_RrcConfigu rrc->carrier.ssb_SubcarrierOffset = configuration->ssb_SubcarrierOffset; rrc->carrier.pdsch_AntennaPorts = configuration->pdsch_AntennaPorts; rrc->carrier.pusch_AntennaPorts = configuration->pusch_AntennaPorts; + rrc->carrier.do_CSIRS = configuration->do_CSIRS; /// System Information INIT pthread_mutex_init(&rrc->cell_info_mutex,NULL); rrc->cell_info_configured = 0; diff --git a/openair2/RRC/NR/rrc_gNB_nsa.c b/openair2/RRC/NR/rrc_gNB_nsa.c index f8cc951bc3..0b7b0745aa 100644 --- a/openair2/RRC/NR/rrc_gNB_nsa.c +++ b/openair2/RRC/NR/rrc_gNB_nsa.c @@ -245,6 +245,7 @@ void rrc_add_nsa_user(gNB_RRC_INST *rrc,struct rrc_gNB_ue_context_s *ue_context_ reconfig_ies, ue_context_p->ue_context.secondaryCellGroup, carrier->pdsch_AntennaPorts, + carrier->do_CSIRS, carrier->initial_csi_index[ue_context_p->local_uid + 1], ue_context_p->local_uid); } else { @@ -253,6 +254,7 @@ void rrc_add_nsa_user(gNB_RRC_INST *rrc,struct rrc_gNB_ue_context_s *ue_context_ reconfig_ies, ue_context_p->ue_context.secondaryCellGroup, carrier->pdsch_AntennaPorts, + carrier->do_CSIRS, carrier->initial_csi_index[ue_context_p->local_uid + 1], ue_context_p->local_uid); } diff --git a/openair2/RRC/NR/rrc_gNB_reconfig.c b/openair2/RRC/NR/rrc_gNB_reconfig.c index 20ec2b2bdb..10134334f0 100644 --- a/openair2/RRC/NR/rrc_gNB_reconfig.c +++ b/openair2/RRC/NR/rrc_gNB_reconfig.c @@ -135,7 +135,8 @@ void fill_default_secondaryCellGroup(NR_ServingCellConfigCommon_t *servingcellco NR_CellGroupConfig_t *secondaryCellGroup, int scg_id, int servCellIndex, - int n_physical_antenna_ports, + int dl_antenna_ports, + int do_csirs, int initial_csi_index, int uid) { AssertFatal(servingcellconfigcommon!=NULL,"servingcellconfigcommon is null\n"); @@ -631,7 +632,7 @@ void fill_default_secondaryCellGroup(NR_ServingCellConfigCommon_t *servingcellco } bwp->bwp_Dedicated->pdsch_Config->choice.setup->dataScramblingIdentityPDSCH = NULL; - if (n_physical_antenna_ports > 1)// for MIMO, we use DMRS Config Type 2 + if (dl_antenna_ports > 1)// for MIMO, we use DMRS Config Type 2 bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->dmrs_Type=calloc(1,sizeof(*bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->dmrs_Type)); else bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->dmrs_Type=NULL; @@ -1030,8 +1031,14 @@ void fill_default_secondaryCellGroup(NR_ServingCellConfigCommon_t *servingcellco NR_PUCCH_SpatialRelationInfo_t *pucchspatial = calloc(1,sizeof(*pucchspatial)); pucchspatial->pucch_SpatialRelationInfoId = 1; pucchspatial->servingCellId = NULL; - pucchspatial->referenceSignal.present = NR_PUCCH_SpatialRelationInfo__referenceSignal_PR_csi_RS_Index; - pucchspatial->referenceSignal.choice.csi_RS_Index = 0; + if(do_csirs) { + pucchspatial->referenceSignal.present = NR_PUCCH_SpatialRelationInfo__referenceSignal_PR_csi_RS_Index; + pucchspatial->referenceSignal.choice.csi_RS_Index = 0; + } + else { + pucchspatial->referenceSignal.present = NR_PUCCH_SpatialRelationInfo__referenceSignal_PR_ssb_Index; + pucchspatial->referenceSignal.choice.ssb_Index = 0; + } pucchspatial->pucch_PathlossReferenceRS_Id = 0; pucchspatial->p0_PUCCH_Id = 1; pucchspatial->closedLoopIndex = NR_PUCCH_SpatialRelationInfo__closedLoopIndex_i0; @@ -1114,53 +1121,57 @@ void fill_default_secondaryCellGroup(NR_ServingCellConfigCommon_t *servingcellco NR_CSI_MeasConfig_t *csi_MeasConfig = calloc(1,sizeof(*csi_MeasConfig)); secondaryCellGroup->spCellConfig->spCellConfigDedicated->csi_MeasConfig->choice.setup = csi_MeasConfig; - csi_MeasConfig->csi_IM_ResourceToAddModList = NULL; + if (do_csirs && dl_antenna_ports > 1) { + csi_MeasConfig->csi_IM_ResourceToAddModList = calloc(1,sizeof(*csi_MeasConfig->csi_IM_ResourceToAddModList)); + NR_CSI_IM_Resource_t *imres0 = calloc(1,sizeof(*imres0)); + imres0->csi_IM_ResourceId = 0; + imres0->csi_IM_ResourceElementPattern = calloc(1,sizeof(*imres0->csi_IM_ResourceElementPattern)); + imres0->csi_IM_ResourceElementPattern->present = NR_CSI_IM_Resource__csi_IM_ResourceElementPattern_PR_pattern1; + imres0->csi_IM_ResourceElementPattern->choice.pattern1 = calloc(1,sizeof(*imres0->csi_IM_ResourceElementPattern->choice.pattern1)); + imres0->csi_IM_ResourceElementPattern->choice.pattern1->subcarrierLocation_p1 = NR_CSI_IM_Resource__csi_IM_ResourceElementPattern__pattern1__subcarrierLocation_p1_s4; + imres0->csi_IM_ResourceElementPattern->choice.pattern1->symbolLocation_p1 = 6; + imres0->freqBand = calloc(1,sizeof(*imres0->freqBand)); + imres0->freqBand->startingRB = 0; + imres0->freqBand->nrofRBs = 108; + imres0->periodicityAndOffset = calloc(1,sizeof(*imres0->periodicityAndOffset)); + imres0->periodicityAndOffset->present = NR_CSI_ResourcePeriodicityAndOffset_PR_slots320; + imres0->periodicityAndOffset->choice.slots320 = 0; + ASN_SEQUENCE_ADD(&csi_MeasConfig->csi_IM_ResourceToAddModList->list,imres0); + csi_MeasConfig->csi_IM_ResourceSetToAddModList = calloc(1,sizeof(*csi_MeasConfig->csi_IM_ResourceSetToAddModList)); + NR_CSI_IM_ResourceSet_t *imset0 = calloc(1,sizeof(*imset0)); + imset0->csi_IM_ResourceSetId = 0; + NR_CSI_IM_ResourceId_t *res0 = calloc(1,sizeof(*res0)); + *res0 = 0; + ASN_SEQUENCE_ADD(&imset0->csi_IM_Resources,res0); + ASN_SEQUENCE_ADD(&csi_MeasConfig->csi_IM_ResourceSetToAddModList->list,imset0); + } + else { + csi_MeasConfig->csi_IM_ResourceToAddModList = NULL; + csi_MeasConfig->csi_IM_ResourceSetToAddModList = NULL; + } + csi_MeasConfig->csi_IM_ResourceToReleaseList = NULL; csi_MeasConfig->csi_IM_ResourceSetToAddModList = NULL; csi_MeasConfig->csi_IM_ResourceSetToReleaseList = NULL; - csi_MeasConfig->nzp_CSI_RS_ResourceSetToAddModList = calloc(1,sizeof(*csi_MeasConfig->nzp_CSI_RS_ResourceSetToAddModList)); - NR_NZP_CSI_RS_ResourceSet_t *nzpcsirs0 = calloc(1,sizeof(*nzpcsirs0)); - nzpcsirs0->nzp_CSI_ResourceSetId = 0; - NR_NZP_CSI_RS_ResourceId_t *nzpid0 = calloc(1,sizeof(*nzpid0)); - *nzpid0 = 0; - ASN_SEQUENCE_ADD(&nzpcsirs0->nzp_CSI_RS_Resources,nzpid0); - nzpcsirs0->repetition = NULL; - nzpcsirs0->aperiodicTriggeringOffset = NULL; - nzpcsirs0->trs_Info = NULL; - ASN_SEQUENCE_ADD(&csi_MeasConfig->nzp_CSI_RS_ResourceSetToAddModList->list,nzpcsirs0); + if (do_csirs) { + csi_MeasConfig->nzp_CSI_RS_ResourceSetToAddModList = calloc(1,sizeof(*csi_MeasConfig->nzp_CSI_RS_ResourceSetToAddModList)); + NR_NZP_CSI_RS_ResourceSet_t *nzpcsirs0 = calloc(1,sizeof(*nzpcsirs0)); + nzpcsirs0->nzp_CSI_ResourceSetId = 0; + NR_NZP_CSI_RS_ResourceId_t *nzpid0 = calloc(1,sizeof(*nzpid0)); + *nzpid0 = 0; + ASN_SEQUENCE_ADD(&nzpcsirs0->nzp_CSI_RS_Resources,nzpid0); + nzpcsirs0->repetition = NULL; + nzpcsirs0->aperiodicTriggeringOffset = NULL; + nzpcsirs0->trs_Info = NULL; + ASN_SEQUENCE_ADD(&csi_MeasConfig->nzp_CSI_RS_ResourceSetToAddModList->list,nzpcsirs0); + } + else + csi_MeasConfig->nzp_CSI_RS_ResourceSetToAddModList = NULL; csi_MeasConfig->nzp_CSI_RS_ResourceSetToReleaseList = NULL; - csi_MeasConfig->nzp_CSI_RS_ResourceToAddModList = calloc(1,sizeof(*csi_MeasConfig->nzp_CSI_RS_ResourceToAddModList)); - - NR_NZP_CSI_RS_Resource_t *nzpcsi0 = calloc(1,sizeof(*nzpcsi0)); - nzpcsi0->nzp_CSI_RS_ResourceId = 0; - NR_CSI_RS_ResourceMapping_t resourceMapping; - resourceMapping.frequencyDomainAllocation.present = NR_CSI_RS_ResourceMapping__frequencyDomainAllocation_PR_row2; - resourceMapping.frequencyDomainAllocation.choice.row2.buf = calloc(2, sizeof(uint8_t)); - resourceMapping.frequencyDomainAllocation.choice.row2.size = 2; - resourceMapping.frequencyDomainAllocation.choice.row2.bits_unused = 4; - resourceMapping.frequencyDomainAllocation.choice.row2.buf[0]=0; - resourceMapping.frequencyDomainAllocation.choice.row2.buf[1]=16; - resourceMapping.nrofPorts = NR_CSI_RS_ResourceMapping__nrofPorts_p1; - resourceMapping.firstOFDMSymbolInTimeDomain = 6; - resourceMapping.firstOFDMSymbolInTimeDomain2 = NULL; - resourceMapping.cdm_Type = NR_CSI_RS_ResourceMapping__cdm_Type_noCDM; - resourceMapping.density.present = NR_CSI_RS_ResourceMapping__density_PR_one; - resourceMapping.density.choice.one = (NULL_t)0; - resourceMapping.freqBand.startingRB = 0; - resourceMapping.freqBand.nrofRBs = 104; - nzpcsi0->resourceMapping = resourceMapping; - nzpcsi0->powerControlOffset = 0; - nzpcsi0->powerControlOffsetSS=calloc(1,sizeof(*nzpcsi0->powerControlOffsetSS)); - *nzpcsi0->powerControlOffsetSS = NR_NZP_CSI_RS_Resource__powerControlOffsetSS_db0; - nzpcsi0->scramblingID = *servingcellconfigcommon->physCellId; - nzpcsi0->periodicityAndOffset = calloc(1,sizeof(*nzpcsi0->periodicityAndOffset)); - nzpcsi0->periodicityAndOffset->present = NR_CSI_ResourcePeriodicityAndOffset_PR_slots320; - nzpcsi0->periodicityAndOffset->choice.slots320 = 0; - nzpcsi0->qcl_InfoPeriodicCSI_RS = NULL; - ASN_SEQUENCE_ADD(&csi_MeasConfig->nzp_CSI_RS_ResourceToAddModList->list,nzpcsi0); + config_csirs(servingcellconfigcommon, csi_MeasConfig,dl_antenna_ports,do_csirs); csi_MeasConfig->csi_SSB_ResourceSetToAddModList = calloc(1,sizeof(*csi_MeasConfig->csi_SSB_ResourceSetToAddModList)); csi_MeasConfig->csi_SSB_ResourceSetToReleaseList = NULL; @@ -1179,18 +1190,21 @@ void fill_default_secondaryCellGroup(NR_ServingCellConfigCommon_t *servingcellco ASN_SEQUENCE_ADD(&csi_MeasConfig->csi_SSB_ResourceSetToAddModList->list,ssbresset0); csi_MeasConfig->csi_ResourceConfigToAddModList = calloc(1,sizeof(*csi_MeasConfig->csi_ResourceConfigToAddModList)); - csi_MeasConfig->csi_ResourceConfigToReleaseList = NULL; - NR_CSI_ResourceConfig_t *csires0 = calloc(1,sizeof(*csires0)); - csires0->csi_ResourceConfigId=0; - 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 = 0; - ASN_SEQUENCE_ADD(&csires0->csi_RS_ResourceSetList.choice.nzp_CSI_RS_SSB->nzp_CSI_RS_ResourceSetList->list,nzp0); - csires0->bwp_Id = 1; - csires0->resourceType = NR_CSI_ResourceConfig__resourceType_periodic; - ASN_SEQUENCE_ADD(&csi_MeasConfig->csi_ResourceConfigToAddModList->list,csires0); + + if (do_csirs) { + csi_MeasConfig->csi_ResourceConfigToReleaseList = NULL; + NR_CSI_ResourceConfig_t *csires0 = calloc(1,sizeof(*csires0)); + csires0->csi_ResourceConfigId=0; + 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 = 0; + ASN_SEQUENCE_ADD(&csires0->csi_RS_ResourceSetList.choice.nzp_CSI_RS_SSB->nzp_CSI_RS_ResourceSetList->list,nzp0); + csires0->bwp_Id = 1; + csires0->resourceType = NR_CSI_ResourceConfig__resourceType_periodic; + ASN_SEQUENCE_ADD(&csi_MeasConfig->csi_ResourceConfigToAddModList->list,csires0); + } NR_CSI_ResourceConfig_t *csires1 = calloc(1,sizeof(*csires1)); csires1->csi_ResourceConfigId=1; @@ -1204,78 +1218,147 @@ void fill_default_secondaryCellGroup(NR_ServingCellConfigCommon_t *servingcellco csires1->resourceType = NR_CSI_ResourceConfig__resourceType_periodic; ASN_SEQUENCE_ADD(&csi_MeasConfig->csi_ResourceConfigToAddModList->list,csires1); + if (do_csirs && dl_antenna_ports > 1) { + NR_CSI_ResourceConfig_t *csires2 = calloc(1,sizeof(*csires2)); + csires2->csi_ResourceConfigId=2; + 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 = 0; + ASN_SEQUENCE_ADD(&csires2->csi_RS_ResourceSetList.choice.csi_IM_ResourceSetList->list,csiim00); + ASN_SEQUENCE_ADD(&csi_MeasConfig->csi_ResourceConfigToAddModList->list,csires2); + } - csi_MeasConfig->csi_ReportConfigToAddModList = calloc(1,sizeof(*csi_MeasConfig->csi_ReportConfigToAddModList)); - csi_MeasConfig->csi_ReportConfigToReleaseList = NULL; - NR_CSI_ReportConfig_t *csirep1 = calloc(1,sizeof(*csirep1)); - csirep1->reportConfigId=0; - csirep1->carrier=NULL; - csirep1->resourcesForChannelMeasurement=0; - csirep1->csi_IM_ResourcesForInterference=NULL; - csirep1->nzp_CSI_RS_ResourcesForInterference=NULL; - csirep1->reportConfigType.present = NR_CSI_ReportConfig__reportConfigType_PR_periodic; - csirep1->reportConfigType.choice.periodic = calloc(1,sizeof(*csirep1->reportConfigType.choice.periodic)); - csirep1->reportConfigType.choice.periodic->reportSlotConfig.present=NR_CSI_ReportPeriodicityAndOffset_PR_slots320; - csirep1->reportConfigType.choice.periodic->reportSlotConfig.choice.slots320 = 9 + (20 * uid) % 320; NR_PUCCH_CSI_Resource_t *pucchcsires1 = calloc(1,sizeof(*pucchcsires1)); pucchcsires1->uplinkBandwidthPartId=1; pucchcsires1->pucch_Resource=2; - ASN_SEQUENCE_ADD(&csirep1->reportConfigType.choice.periodic->pucch_CSI_ResourceList.list,pucchcsires1); - csirep1->reportQuantity.present = NR_CSI_ReportConfig__reportQuantity_PR_cri_RSRP; - csirep1->reportQuantity.choice.cri_RSRP=(NULL_t)0; - csirep1->reportFreqConfiguration = calloc(1,sizeof(*csirep1->reportFreqConfiguration)); - csirep1->reportFreqConfiguration->cqi_FormatIndicator = NULL; - csirep1->reportFreqConfiguration->pmi_FormatIndicator=NULL; - csirep1->reportFreqConfiguration->csi_ReportingBand=NULL; - csirep1->timeRestrictionForChannelMeasurements= NR_CSI_ReportConfig__timeRestrictionForChannelMeasurements_configured; - csirep1->timeRestrictionForInterferenceMeasurements=NR_CSI_ReportConfig__timeRestrictionForInterferenceMeasurements_configured; - csirep1->codebookConfig=NULL; - csirep1->dummy = NULL; - csirep1->groupBasedBeamReporting.present = NR_CSI_ReportConfig__groupBasedBeamReporting_PR_disabled; - csirep1->groupBasedBeamReporting.choice.disabled=calloc(1,sizeof(*csirep1->groupBasedBeamReporting.choice.disabled)); - csirep1->groupBasedBeamReporting.choice.disabled->nrofReportedRS = calloc(1,sizeof(*csirep1->groupBasedBeamReporting.choice.disabled->nrofReportedRS)); - *csirep1->groupBasedBeamReporting.choice.disabled->nrofReportedRS=NR_CSI_ReportConfig__groupBasedBeamReporting__disabled__nrofReportedRS_n1; - csirep1->cqi_Table = NULL; - csirep1->subbandSize = NR_CSI_ReportConfig__subbandSize_value1; - csirep1->non_PMI_PortIndication = NULL; - csirep1->ext1 = NULL; - ASN_SEQUENCE_ADD(&csi_MeasConfig->csi_ReportConfigToAddModList->list,csirep1); + csi_MeasConfig->csi_ReportConfigToAddModList = calloc(1,sizeof(*csi_MeasConfig->csi_ReportConfigToAddModList)); + csi_MeasConfig->csi_ReportConfigToReleaseList = NULL; + if (dl_antenna_ports > 1) { + NR_CSI_ReportConfig_t *csirep1 = calloc(1,sizeof(*csirep1)); + csirep1->reportConfigId=0; + csirep1->carrier=NULL; + csirep1->resourcesForChannelMeasurement=0; + csirep1->csi_IM_ResourcesForInterference=calloc(1,sizeof(*csirep1->csi_IM_ResourcesForInterference)); + *csirep1->csi_IM_ResourcesForInterference=2; + csirep1->nzp_CSI_RS_ResourcesForInterference=NULL; + csirep1->reportConfigType.present = NR_CSI_ReportConfig__reportConfigType_PR_periodic; + csirep1->reportConfigType.choice.periodic = calloc(1,sizeof(*csirep1->reportConfigType.choice.periodic)); + csirep1->reportConfigType.choice.periodic->reportSlotConfig.present=NR_CSI_ReportPeriodicityAndOffset_PR_slots320; + csirep1->reportConfigType.choice.periodic->reportSlotConfig.choice.slots320 = 9 + (20 * uid) % 320; + ASN_SEQUENCE_ADD(&csirep1->reportConfigType.choice.periodic->pucch_CSI_ResourceList.list,pucchcsires1); + csirep1->reportQuantity.present = NR_CSI_ReportConfig__reportQuantity_PR_cri_RI_PMI_CQI; + csirep1->reportQuantity.choice.cri_RI_PMI_CQI=(NULL_t)0; + csirep1->reportFreqConfiguration = calloc(1,sizeof(*csirep1->reportFreqConfiguration)); + csirep1->reportFreqConfiguration->cqi_FormatIndicator = calloc(1,sizeof(*csirep1->reportFreqConfiguration->cqi_FormatIndicator)); + *csirep1->reportFreqConfiguration->cqi_FormatIndicator=NR_CSI_ReportConfig__reportFreqConfiguration__cqi_FormatIndicator_widebandCQI; + csirep1->reportFreqConfiguration->pmi_FormatIndicator = calloc(1,sizeof(*csirep1->reportFreqConfiguration->pmi_FormatIndicator)); + *csirep1->reportFreqConfiguration->pmi_FormatIndicator=NR_CSI_ReportConfig__reportFreqConfiguration__pmi_FormatIndicator_widebandPMI; + csirep1->reportFreqConfiguration->csi_ReportingBand = calloc(1,sizeof(*csirep1->reportFreqConfiguration->csi_ReportingBand)); + csirep1->reportFreqConfiguration->csi_ReportingBand->present = NR_CSI_ReportConfig__reportFreqConfiguration__csi_ReportingBand_PR_subbands7; + csirep1->reportFreqConfiguration->csi_ReportingBand->choice.subbands7.size=1; + csirep1->reportFreqConfiguration->csi_ReportingBand->choice.subbands7.bits_unused=1; + csirep1->reportFreqConfiguration->csi_ReportingBand->choice.subbands7.buf=malloc(1); + csirep1->reportFreqConfiguration->csi_ReportingBand->choice.subbands7.buf[0]=254; + csirep1->timeRestrictionForChannelMeasurements= NR_CSI_ReportConfig__timeRestrictionForChannelMeasurements_configured; + csirep1->timeRestrictionForInterferenceMeasurements=NR_CSI_ReportConfig__timeRestrictionForInterferenceMeasurements_configured; + csirep1->codebookConfig=calloc(1,sizeof(*csirep1->codebookConfig)); + csirep1->codebookConfig->codebookType.present = NR_CodebookConfig__codebookType_PR_type1; + csirep1->codebookConfig->codebookType.choice.type1 = calloc(1,sizeof(*csirep1->codebookConfig->codebookType.choice.type1)); + csirep1->codebookConfig->codebookType.choice.type1->subType.present=NR_CodebookConfig__codebookType__type1__subType_PR_typeI_SinglePanel; + csirep1->codebookConfig->codebookType.choice.type1->subType.choice.typeI_SinglePanel=calloc(1,sizeof(*csirep1->codebookConfig->codebookType.choice.type1->subType.choice.typeI_SinglePanel)); + csirep1->codebookConfig->codebookType.choice.type1->subType.choice.typeI_SinglePanel->nrOfAntennaPorts.present= + NR_CodebookConfig__codebookType__type1__subType__typeI_SinglePanel__nrOfAntennaPorts_PR_two; + csirep1->codebookConfig->codebookType.choice.type1->subType.choice.typeI_SinglePanel->nrOfAntennaPorts.choice.two= + calloc(1,sizeof(*csirep1->codebookConfig->codebookType.choice.type1->subType.choice.typeI_SinglePanel->nrOfAntennaPorts.choice.two)); + csirep1->codebookConfig->codebookType.choice.type1->subType.choice.typeI_SinglePanel->nrOfAntennaPorts.choice.two->twoTX_CodebookSubsetRestriction.size=1; + csirep1->codebookConfig->codebookType.choice.type1->subType.choice.typeI_SinglePanel->nrOfAntennaPorts.choice.two->twoTX_CodebookSubsetRestriction.bits_unused=2; + csirep1->codebookConfig->codebookType.choice.type1->subType.choice.typeI_SinglePanel->nrOfAntennaPorts.choice.two->twoTX_CodebookSubsetRestriction.buf=malloc(1); + csirep1->codebookConfig->codebookType.choice.type1->subType.choice.typeI_SinglePanel->nrOfAntennaPorts.choice.two->twoTX_CodebookSubsetRestriction.buf[0]=0xfc; + csirep1->codebookConfig->codebookType.choice.type1->subType.choice.typeI_SinglePanel->typeI_SinglePanel_ri_Restriction.size=1; + csirep1->codebookConfig->codebookType.choice.type1->subType.choice.typeI_SinglePanel->typeI_SinglePanel_ri_Restriction.bits_unused=0; + csirep1->codebookConfig->codebookType.choice.type1->subType.choice.typeI_SinglePanel->typeI_SinglePanel_ri_Restriction.buf=malloc(1); + csirep1->codebookConfig->codebookType.choice.type1->subType.choice.typeI_SinglePanel->typeI_SinglePanel_ri_Restriction.buf[0]=0x03; + csirep1->codebookConfig->codebookType.choice.type1->codebookMode=1; + csirep1->dummy = NULL; + csirep1->groupBasedBeamReporting.present = NR_CSI_ReportConfig__groupBasedBeamReporting_PR_disabled; + csirep1->groupBasedBeamReporting.choice.disabled=calloc(1,sizeof(*csirep1->groupBasedBeamReporting.choice.disabled)); + //csirep1->groupBasedBeamReporting.choice.disabled->nrofReportedRS = calloc(1,sizeof(*csirep1->groupBasedBeamReporting.choice.disabled->nrofReportedRS)); + //*csirep1->groupBasedBeamReporting.choice.disabled->nrofReportedRS=NR_CSI_ReportConfig__groupBasedBeamReporting__disabled__nrofReportedRS_n1; + csirep1->cqi_Table = calloc(1,sizeof(*csirep1->cqi_Table)); + *csirep1->cqi_Table = NR_CSI_ReportConfig__cqi_Table_table1; + csirep1->subbandSize = NR_CSI_ReportConfig__subbandSize_value2; + csirep1->non_PMI_PortIndication = NULL; + csirep1->ext1 = NULL; + ASN_SEQUENCE_ADD(&csi_MeasConfig->csi_ReportConfigToAddModList->list,csirep1); + } - NR_CSI_ReportConfig_t *csirep2 = calloc(1,sizeof(*csirep2)); - csirep2->reportConfigId=1; - csirep2->carrier=NULL; - csirep2->resourcesForChannelMeasurement=1; - csirep2->csi_IM_ResourcesForInterference=NULL; - csirep2->nzp_CSI_RS_ResourcesForInterference=NULL; - csirep2->reportConfigType.present = NR_CSI_ReportConfig__reportConfigType_PR_periodic; - csirep2->reportConfigType.choice.periodic = calloc(1,sizeof(*csirep2->reportConfigType.choice.periodic)); - csirep2->reportConfigType.choice.periodic->reportSlotConfig.present=NR_CSI_ReportPeriodicityAndOffset_PR_slots320; - csirep2->reportConfigType.choice.periodic->reportSlotConfig.choice.slots320 = 29 + (20 * uid) % 320; - ASN_SEQUENCE_ADD(&csirep2->reportConfigType.choice.periodic->pucch_CSI_ResourceList.list,pucchcsires1); - csirep2->reportQuantity.present = NR_CSI_ReportConfig__reportQuantity_PR_ssb_Index_RSRP; - csirep2->reportQuantity.choice.ssb_Index_RSRP=(NULL_t)0; - csirep2->reportFreqConfiguration = calloc(1,sizeof(*csirep2->reportFreqConfiguration)); - csirep2->reportFreqConfiguration->cqi_FormatIndicator=NR_CSI_ReportConfig__reportFreqConfiguration__cqi_FormatIndicator_widebandCQI; - csirep2->reportFreqConfiguration->pmi_FormatIndicator=NR_CSI_ReportConfig__reportFreqConfiguration__pmi_FormatIndicator_widebandPMI; - csirep2->reportFreqConfiguration->csi_ReportingBand=NULL; - csirep2->timeRestrictionForChannelMeasurements= NR_CSI_ReportConfig__timeRestrictionForChannelMeasurements_configured; - csirep2->timeRestrictionForInterferenceMeasurements=NR_CSI_ReportConfig__timeRestrictionForInterferenceMeasurements_configured; - csirep2->codebookConfig= NULL; - - csirep2->dummy = NULL; - csirep2->groupBasedBeamReporting.present = NR_CSI_ReportConfig__groupBasedBeamReporting_PR_disabled; - csirep2->groupBasedBeamReporting.choice.disabled=calloc(1,sizeof(*csirep2->groupBasedBeamReporting.choice.disabled)); - csirep2->groupBasedBeamReporting.choice.disabled->nrofReportedRS = calloc(1,sizeof(*csirep2->groupBasedBeamReporting.choice.disabled->nrofReportedRS)); - *csirep2->groupBasedBeamReporting.choice.disabled->nrofReportedRS=NR_CSI_ReportConfig__groupBasedBeamReporting__disabled__nrofReportedRS_n1; - - csirep2->cqi_Table = calloc(1,sizeof(*csirep2->cqi_Table)); - *csirep2->cqi_Table = NR_CSI_ReportConfig__cqi_Table_table1; - csirep2->subbandSize = NR_CSI_ReportConfig__subbandSize_value1; - csirep2->non_PMI_PortIndication = NULL; - csirep2->ext1 = NULL; - - ASN_SEQUENCE_ADD(&csi_MeasConfig->csi_ReportConfigToAddModList->list,csirep2); + if (do_csirs) { + NR_CSI_ReportConfig_t *csirep2 = calloc(1,sizeof(*csirep2)); + csirep2->reportConfigId=1; + csirep2->carrier=NULL; + csirep2->resourcesForChannelMeasurement=0; + csirep2->csi_IM_ResourcesForInterference=NULL; + csirep2->nzp_CSI_RS_ResourcesForInterference=NULL; + csirep2->reportConfigType.present = NR_CSI_ReportConfig__reportConfigType_PR_periodic; + csirep2->reportConfigType.choice.periodic = calloc(1,sizeof(*csirep2->reportConfigType.choice.periodic)); + csirep2->reportConfigType.choice.periodic->reportSlotConfig.present=NR_CSI_ReportPeriodicityAndOffset_PR_slots320; + csirep2->reportConfigType.choice.periodic->reportSlotConfig.choice.slots320 = 29 + (20 * uid) % 320; + ASN_SEQUENCE_ADD(&csirep2->reportConfigType.choice.periodic->pucch_CSI_ResourceList.list,pucchcsires1); + csirep2->reportQuantity.present = NR_CSI_ReportConfig__reportQuantity_PR_cri_RSRP; + csirep2->reportQuantity.choice.cri_RSRP=(NULL_t)0; + csirep2->reportFreqConfiguration = calloc(1,sizeof(*csirep2->reportFreqConfiguration)); + csirep2->reportFreqConfiguration->cqi_FormatIndicator = NULL; + csirep2->reportFreqConfiguration->pmi_FormatIndicator=NULL; + csirep2->reportFreqConfiguration->csi_ReportingBand=NULL; + csirep2->timeRestrictionForChannelMeasurements= NR_CSI_ReportConfig__timeRestrictionForChannelMeasurements_configured; + csirep2->timeRestrictionForInterferenceMeasurements=NR_CSI_ReportConfig__timeRestrictionForInterferenceMeasurements_configured; + csirep2->codebookConfig=NULL; + csirep2->dummy = NULL; + csirep2->groupBasedBeamReporting.present = NR_CSI_ReportConfig__groupBasedBeamReporting_PR_disabled; + csirep2->groupBasedBeamReporting.choice.disabled=calloc(1,sizeof(*csirep2->groupBasedBeamReporting.choice.disabled)); + csirep2->groupBasedBeamReporting.choice.disabled->nrofReportedRS = calloc(1,sizeof(*csirep2->groupBasedBeamReporting.choice.disabled->nrofReportedRS)); + *csirep2->groupBasedBeamReporting.choice.disabled->nrofReportedRS=NR_CSI_ReportConfig__groupBasedBeamReporting__disabled__nrofReportedRS_n1; + csirep2->cqi_Table = NULL; + csirep2->subbandSize = NR_CSI_ReportConfig__subbandSize_value1; + csirep2->non_PMI_PortIndication = NULL; + csirep2->ext1 = NULL; + ASN_SEQUENCE_ADD(&csi_MeasConfig->csi_ReportConfigToAddModList->list,csirep2); + } + else{ + NR_CSI_ReportConfig_t *csirep2 = calloc(1,sizeof(*csirep2)); + csirep2->reportConfigId=1; + csirep2->carrier=NULL; + csirep2->resourcesForChannelMeasurement=1; + csirep2->csi_IM_ResourcesForInterference=NULL; + csirep2->nzp_CSI_RS_ResourcesForInterference=NULL; + csirep2->reportConfigType.present = NR_CSI_ReportConfig__reportConfigType_PR_periodic; + csirep2->reportConfigType.choice.periodic = calloc(1,sizeof(*csirep2->reportConfigType.choice.periodic)); + csirep2->reportConfigType.choice.periodic->reportSlotConfig.present=NR_CSI_ReportPeriodicityAndOffset_PR_slots320; + csirep2->reportConfigType.choice.periodic->reportSlotConfig.choice.slots320 = 29 + (20 * uid) % 320; + ASN_SEQUENCE_ADD(&csirep2->reportConfigType.choice.periodic->pucch_CSI_ResourceList.list,pucchcsires1); + csirep2->reportQuantity.present = NR_CSI_ReportConfig__reportQuantity_PR_ssb_Index_RSRP; + csirep2->reportQuantity.choice.ssb_Index_RSRP=(NULL_t)0; + csirep2->reportFreqConfiguration = calloc(1,sizeof(*csirep2->reportFreqConfiguration)); + csirep2->reportFreqConfiguration->cqi_FormatIndicator=NR_CSI_ReportConfig__reportFreqConfiguration__cqi_FormatIndicator_widebandCQI; + csirep2->reportFreqConfiguration->pmi_FormatIndicator=NR_CSI_ReportConfig__reportFreqConfiguration__pmi_FormatIndicator_widebandPMI; + csirep2->reportFreqConfiguration->csi_ReportingBand=NULL; + csirep2->timeRestrictionForChannelMeasurements= NR_CSI_ReportConfig__timeRestrictionForChannelMeasurements_configured; + csirep2->timeRestrictionForInterferenceMeasurements=NR_CSI_ReportConfig__timeRestrictionForInterferenceMeasurements_configured; + csirep2->codebookConfig= NULL; + csirep2->dummy = NULL; + csirep2->groupBasedBeamReporting.present = NR_CSI_ReportConfig__groupBasedBeamReporting_PR_disabled; + csirep2->groupBasedBeamReporting.choice.disabled=calloc(1,sizeof(*csirep2->groupBasedBeamReporting.choice.disabled)); + csirep2->groupBasedBeamReporting.choice.disabled->nrofReportedRS = calloc(1,sizeof(*csirep2->groupBasedBeamReporting.choice.disabled->nrofReportedRS)); + *csirep2->groupBasedBeamReporting.choice.disabled->nrofReportedRS=NR_CSI_ReportConfig__groupBasedBeamReporting__disabled__nrofReportedRS_n1; + csirep2->cqi_Table = calloc(1,sizeof(*csirep2->cqi_Table)); + *csirep2->cqi_Table = NR_CSI_ReportConfig__cqi_Table_table1; + csirep2->subbandSize = NR_CSI_ReportConfig__subbandSize_value1; + csirep2->non_PMI_PortIndication = NULL; + csirep2->ext1 = NULL; + ASN_SEQUENCE_ADD(&csi_MeasConfig->csi_ReportConfigToAddModList->list,csirep2); + } secondaryCellGroup->spCellConfig->spCellConfigDedicated->sCellDeactivationTimer=NULL; secondaryCellGroup->spCellConfig->spCellConfigDedicated->crossCarrierSchedulingConfig=NULL; @@ -1286,11 +1369,65 @@ void fill_default_secondaryCellGroup(NR_ServingCellConfigCommon_t *servingcellco } + +void config_csirs(NR_ServingCellConfigCommon_t *servingcellconfigcommon, NR_CSI_MeasConfig_t *csi_MeasConfig, int dl_antenna_ports, int do_csirs) { + + if (do_csirs) { + csi_MeasConfig->nzp_CSI_RS_ResourceToAddModList = calloc(1,sizeof(*csi_MeasConfig->nzp_CSI_RS_ResourceToAddModList)); + NR_NZP_CSI_RS_Resource_t *nzpcsi0 = calloc(1,sizeof(*nzpcsi0)); + nzpcsi0->nzp_CSI_RS_ResourceId = 0; + NR_CSI_RS_ResourceMapping_t resourceMapping; + switch (dl_antenna_ports) { + case 1: + resourceMapping.frequencyDomainAllocation.present = NR_CSI_RS_ResourceMapping__frequencyDomainAllocation_PR_row2; + resourceMapping.frequencyDomainAllocation.choice.row2.buf = calloc(2, sizeof(uint8_t)); + resourceMapping.frequencyDomainAllocation.choice.row2.size = 2; + resourceMapping.frequencyDomainAllocation.choice.row2.bits_unused = 4; + resourceMapping.frequencyDomainAllocation.choice.row2.buf[0]=0; + resourceMapping.frequencyDomainAllocation.choice.row2.buf[1]=16; + resourceMapping.nrofPorts = NR_CSI_RS_ResourceMapping__nrofPorts_p1; + resourceMapping.cdm_Type = NR_CSI_RS_ResourceMapping__cdm_Type_noCDM; + break; + case 2: + resourceMapping.frequencyDomainAllocation.present = NR_CSI_RS_ResourceMapping__frequencyDomainAllocation_PR_other; + resourceMapping.frequencyDomainAllocation.choice.row2.buf = calloc(2, sizeof(uint8_t)); + resourceMapping.frequencyDomainAllocation.choice.row2.size = 1; + resourceMapping.frequencyDomainAllocation.choice.row2.bits_unused = 2; + resourceMapping.frequencyDomainAllocation.choice.row2.buf[0]=4; + resourceMapping.nrofPorts = NR_CSI_RS_ResourceMapping__nrofPorts_p2; + resourceMapping.cdm_Type = NR_CSI_RS_ResourceMapping__cdm_Type_fd_CDM2; + break; + default: + AssertFatal(1==0,"Number of ports not yet supported\n"); + } + resourceMapping.firstOFDMSymbolInTimeDomain = 6; + resourceMapping.firstOFDMSymbolInTimeDomain2 = NULL; + resourceMapping.density.present = NR_CSI_RS_ResourceMapping__density_PR_one; + resourceMapping.density.choice.one = (NULL_t)0; + resourceMapping.freqBand.startingRB = 0; + resourceMapping.freqBand.nrofRBs = 108; + nzpcsi0->resourceMapping = resourceMapping; + nzpcsi0->powerControlOffset = 0; + nzpcsi0->powerControlOffsetSS=calloc(1,sizeof(*nzpcsi0->powerControlOffsetSS)); + *nzpcsi0->powerControlOffsetSS = NR_NZP_CSI_RS_Resource__powerControlOffsetSS_db0; + nzpcsi0->scramblingID = *servingcellconfigcommon->physCellId; + nzpcsi0->periodicityAndOffset = calloc(1,sizeof(*nzpcsi0->periodicityAndOffset)); + nzpcsi0->periodicityAndOffset->present = NR_CSI_ResourcePeriodicityAndOffset_PR_slots320; + nzpcsi0->periodicityAndOffset->choice.slots320 = 0; + nzpcsi0->qcl_InfoPeriodicCSI_RS = NULL; + ASN_SEQUENCE_ADD(&csi_MeasConfig->nzp_CSI_RS_ResourceToAddModList->list,nzpcsi0); + } + else + csi_MeasConfig->nzp_CSI_RS_ResourceToAddModList = NULL; +} + + void fill_default_reconfig(NR_ServingCellConfigCommon_t *servingcellconfigcommon, NR_ServingCellConfig_t *servingcellconfigdedicated, NR_RRCReconfiguration_IEs_t *reconfig, NR_CellGroupConfig_t *secondaryCellGroup, - int n_physical_antenna_ports, + int dl_antenna_ports, + int do_csirs, int initial_csi_index, int uid) { AssertFatal(servingcellconfigcommon!=NULL,"servingcellconfigcommon is null\n"); @@ -1304,9 +1441,11 @@ void fill_default_reconfig(NR_ServingCellConfigCommon_t *servingcellconfigcommon secondaryCellGroup, 1, 1, - n_physical_antenna_ports, + dl_antenna_ports, + do_csirs, initial_csi_index, uid); + xer_fprint(stdout, &asn_DEF_NR_CellGroupConfig, (const void*)secondaryCellGroup); char scg_buffer[1024]; From 0f1d787a907b04d4e5e25eddf15764b032e5ea9e Mon Sep 17 00:00:00 2001 From: Laurent OpenCells Date: Mon, 26 Jul 2021 15:47:57 +0200 Subject: [PATCH 60/91] fix obsolete system call --- .../ETHERNET/USERSPACE/LIB/ethernet_lib.c | 49 ++++++++++--------- 1 file changed, 26 insertions(+), 23 deletions(-) diff --git a/targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.c b/targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.c index f35a18eb0e..c15bdc37cb 100644 --- a/targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.c +++ b/targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.c @@ -218,11 +218,6 @@ int ethernet_tune(openair0_device *device, struct timeval timeout; struct ifreq ifr; char system_cmd[256]; - int rname[] = { CTL_NET, NET_CORE, NET_CORE_RMEM_MAX }; - int wname[] = { CTL_NET, NET_CORE, NET_CORE_WMEM_MAX }; - int namelen=3; - int newval[1]; - int newlen=sizeof(newval); int ret=0; // int i=0; @@ -362,28 +357,36 @@ int ethernet_tune(openair0_device *device, } break; case KERNEL_RCV_BUF_MAX_SIZE: - newval[0] = value; - ret=sysctl(rname, namelen, NULL, 0, newval, newlen); - if (ret) { - fprintf(stderr,"[ETHERNET] Error using sysctl():%s\n",strerror(errno)); - } else { - printf("[ETHERNET] Kernel network receive buffer max size is set to %u\n",(unsigned int)newval[0]); - } - break; + ret=snprintf(system_cmd,sizeof(system_cmd),"sysctl -w net.core.rmem_max=%d",value); + if (ret > 0) { + ret=system(system_cmd); + if (ret == -1) { + fprintf (stderr,"[ETHERNET] Can't start shell to execute %s %s",system_cmd, strerror(errno)); + } else { + printf ("[ETHERNET] status of %s is %d\n", system_cmd, WEXITSTATUS(ret)); + } + printf("[ETHERNET] net core rmem %s\n",system_cmd); + } else { + perror("[ETHERNET] Can't set net core rmem\n"); + } + break; case KERNEL_SND_BUF_MAX_SIZE: - newval[0] = value; - ret=sysctl(wname, namelen, NULL, 0, newval, newlen); - if (ret) { - fprintf(stderr,"[ETHERNET] Error using sysctl():%s\n",strerror(errno)); - } else { - printf("[ETHERNET] Kernel network send buffer max size is set to %u\n",(unsigned int)newval[0]); - } - break; - + ret=snprintf(system_cmd,sizeof(system_cmd),"sysctl -w net.core.wmem_max=%d",value); + if (ret > 0) { + ret=system(system_cmd); + if (ret == -1) { + fprintf (stderr,"[ETHERNET] Can't start shell to execute %s %s",system_cmd, strerror(errno)); + } else { + printf ("[ETHERNET] status of %s is %d\n", system_cmd, WEXITSTATUS(ret)); + } + printf("[ETHERNET] net core wmem %s\n",system_cmd); + } else { + perror("[ETHERNET] Can't set net core wmem\n"); + } + break; default: break; } - return 0; } From ea6cd95009dd5b6c2edee516eeeb36a63cb9dce7 Mon Sep 17 00:00:00 2001 From: francescomani Date: Thu, 17 Jun 2021 12:55:43 +0200 Subject: [PATCH 61/91] bugfix in rrc configuration --- openair2/RRC/NR/rrc_gNB_reconfig.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openair2/RRC/NR/rrc_gNB_reconfig.c b/openair2/RRC/NR/rrc_gNB_reconfig.c index 10134334f0..596aaf8dc1 100644 --- a/openair2/RRC/NR/rrc_gNB_reconfig.c +++ b/openair2/RRC/NR/rrc_gNB_reconfig.c @@ -1235,7 +1235,7 @@ void fill_default_secondaryCellGroup(NR_ServingCellConfigCommon_t *servingcellco csi_MeasConfig->csi_ReportConfigToAddModList = calloc(1,sizeof(*csi_MeasConfig->csi_ReportConfigToAddModList)); csi_MeasConfig->csi_ReportConfigToReleaseList = NULL; - if (dl_antenna_ports > 1) { + if (do_csirs && dl_antenna_ports > 1) { NR_CSI_ReportConfig_t *csirep1 = calloc(1,sizeof(*csirep1)); csirep1->reportConfigId=0; csirep1->carrier=NULL; From ac4ae0e0fdac7ca638fe205adf57619b0a90826e Mon Sep 17 00:00:00 2001 From: spclab Date: Tue, 27 Jul 2021 15:10:54 +0530 Subject: [PATCH 62/91] Hardcodings removed fully, system runs but unstable --- executables/nr-gnb.c | 17 ++- nfapi/oai_integration/nfapi_pnf.c | 34 +++--- nfapi/oai_integration/nfapi_vnf.c | 16 ++- nfapi/open-nFAPI/nfapi/src/nfapi_p7.c | 3 +- nfapi/open-nFAPI/pnf/src/pnf_p7.c | 109 +++--------------- nfapi/open-nFAPI/vnf/src/vnf_p7.c | 5 +- nfapi/open-nFAPI/vnf/src/vnf_p7_interface.c | 49 +++++--- openair1/PHY/NR_TRANSPORT/nr_dci_tools.c | 8 +- openair1/PHY/NR_TRANSPORT/pucch_rx.c | 4 +- openair1/SCHED_NR/fapi_nr_l1.c | 8 +- openair1/SCHED_NR/phy_procedures_nr_gNB.c | 10 +- .../LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c | 7 +- .../LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c | 5 +- openair2/NR_PHY_INTERFACE/NR_IF_Module.c | 6 +- 14 files changed, 110 insertions(+), 171 deletions(-) diff --git a/executables/nr-gnb.c b/executables/nr-gnb.c index 7c74cab8ff..166ebd69b6 100644 --- a/executables/nr-gnb.c +++ b/executables/nr-gnb.c @@ -133,7 +133,7 @@ void tx_func(void *param) { } void rx_func(void *param) { - + processingData_L1_t *info = (processingData_L1_t *) param; PHY_VARS_gNB *gNB = info->gNB; int frame_rx = info->frame_rx; @@ -146,15 +146,12 @@ void rx_func(void *param) { start_meas(&softmodem_stats_rxtx_sf); // ******************************************************************* - // NFAPI not yet supported for NR - this code has to be revised + if (NFAPI_MODE == NFAPI_MODE_PNF) { // I am a PNF and I need to let nFAPI know that we have a (sub)frame tick - //add_subframe(&frame, &subframe, 4); - //oai_subframe_ind(proc->frame_tx, proc->subframe_tx); - //LOG_D(PHY, "oai_subframe_ind(frame:%u, subframe:%d) - NOT CALLED ********\n", frame, subframe); + //LOG_D(PHY, "oai_slot_ind(frame:%u, slot:%d) ********\n", frame_rx, slot_rx); start_meas(&nfapi_meas); - // oai_subframe_ind(frame_rx, slot_rx); - oai_slot_ind(frame_rx, slot_rx); + oai_slot_ind(frame_tx, slot_tx); stop_meas(&nfapi_meas); /*if (gNB->UL_INFO.rx_ind.rx_indication_body.number_of_pdus|| @@ -217,6 +214,7 @@ void rx_func(void *param) { gNB->pucch[j]->pucch_pdu.rnti = 0; pucch_removed++; } + #if 0 for (j = 0; j < NUMBER_OF_NR_PDCCH_MAX; j++) gNB->pdcch_pdu[j].frame = -1; @@ -258,8 +256,7 @@ void rx_func(void *param) { // Call the scheduler - if (NFAPI_MODE == NFAPI_MONOLITHIC){ - start_meas(&gNB->ul_indication_stats); + start_meas(&gNB->ul_indication_stats); pthread_mutex_lock(&gNB->UL_INFO_mutex); gNB->UL_INFO.frame = frame_rx; gNB->UL_INFO.slot = slot_rx; @@ -268,7 +265,7 @@ void rx_func(void *param) { gNB->if_inst->NR_UL_indication(&gNB->UL_INFO); pthread_mutex_unlock(&gNB->UL_INFO_mutex); stop_meas(&gNB->ul_indication_stats); - } + notifiedFIFO_elt_t *res; diff --git a/nfapi/oai_integration/nfapi_pnf.c b/nfapi/oai_integration/nfapi_pnf.c index d1a0ee5941..0783aa26b3 100644 --- a/nfapi/oai_integration/nfapi_pnf.c +++ b/nfapi/oai_integration/nfapi_pnf.c @@ -1150,14 +1150,13 @@ int pnf_phy_ul_dci_req(gNB_L1_rxtx_proc_t *proc, nfapi_pnf_p7_config_t *pnf_p7, struct PHY_VARS_gNB_s *gNB = RC.gNB[0]; if (proc ==NULL) proc = &gNB->proc.L1_proc; - + //int slot_tx = req->Slot + 6; //Ref for PNF is slot_rx, so align slot number with tx thread before passing UL_DCI info for (int i=0; inumPdus; i++) { //LOG_D(PHY,"[PNF] HI_DCI0_REQ sfn_sf:%d PDU[%d]\n", NFAPI_SFNSF2DEC(req->sfn_sf), i); if (req->ul_dci_pdu_list[i].PDUType == 0) { //LOG_D(PHY,"[PNF] HI_DCI0_REQ sfn_sf:%d PDU[%d] - NFAPI_HI_DCI0_DCI_PDU_TYPE\n", NFAPI_SFNSF2DEC(req->sfn_sf), i); nfapi_nr_ul_dci_request_pdus_t *ul_dci_req_pdu = &req->ul_dci_pdu_list[i]; - int SFN=req->SFN+2; - handle_nfapi_nr_ul_dci_pdu(gNB, SFN, req->Slot, ul_dci_req_pdu); + handle_nfapi_nr_ul_dci_pdu(gNB, req->SFN, req->Slot, ul_dci_req_pdu); } else { LOG_E(PHY,"[PNF] UL_DCI_REQ sfn_slot:%d PDU[%d] - unknown pdu type:%d\n", NFAPI_SFNSLOT2DEC(req->SFN, req->Slot), i, req->ul_dci_pdu_list[i].PDUType); @@ -1217,21 +1216,21 @@ int pnf_phy_dl_tti_req(gNB_L1_rxtx_proc_t *proc, nfapi_pnf_p7_config_t *pnf_p7, int sfn = req->SFN; int slot = req->Slot; - + //int slot_tx = slot + 6; // ref for PNF is slot_rx, so increment by slot ahead struct PHY_VARS_gNB_s *gNB = RC.gNB[0]; if (proc==NULL) proc = &gNB->proc.L1_proc; nfapi_nr_dl_tti_request_pdu_t *dl_tti_pdu_list = req->dl_tti_request_body.dl_tti_pdu_list; if (req->dl_tti_request_body.nPDUs) - NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() TX:%d/%d RX:%d/%d; sfn:%d, slot:%d, nGroup:%u, nPDUs: %u, nUE: %u, PduIdx: %u,\n", - __FUNCTION__, proc->frame_tx, proc->slot_tx, proc->frame_rx, proc->slot_rx, // TODO: change subframes to slot - req->SFN, - req->Slot, - req->dl_tti_request_body.nGroup, - req->dl_tti_request_body.nPDUs, - req->dl_tti_request_body.nUe, - req->dl_tti_request_body.PduIdx); + // NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() TX:%d/%d RX:%d/%d; sfn:%d, slot:%d, nGroup:%u, nPDUs: %u, nUE: %u, PduIdx: %u,\n", + // __FUNCTION__, proc->frame_tx, proc->slot_tx, proc->frame_rx, proc->slot_rx, // TODO: change subframes to slot + // req->SFN, + // req->Slot, + // req->dl_tti_request_body.nGroup, + // req->dl_tti_request_body.nPDUs, + // req->dl_tti_request_body.nUe, + // req->dl_tti_request_body.PduIdx); for (int i=0; idl_tti_request_body.nPDUs; i++) { // TODO: enable after adding gNB PDCCH: @@ -1435,13 +1434,10 @@ int pnf_phy_tx_req(nfapi_pnf_p7_config_t *pnf_p7, nfapi_tx_request_t *req) { int pnf_phy_ul_tti_req(gNB_L1_rxtx_proc_t *proc, nfapi_pnf_p7_config_t *pnf_p7, nfapi_nr_ul_tti_request_t *req) { - // if (0)LOG_D(PHY,"[PNF] UL_CONFIG_REQ %s() sfn_sf:%d pdu:%d rach_prach_frequency_resources:%d srs_present:%u\n", - // __FUNCTION__, - // NFAPI_SFNSF2DEC(req->sfn_sf), - // req->ul_config_request_body.number_of_pdus, - // req->ul_config_request_body.rach_prach_frequency_resources, - // req->ul_config_request_body.srs_present - // ); + LOG_D(PHY,"[PNF] UL_TTI_REQ recvd, writing into structs, SFN/slot:%d.%d pdu:%d \n", + req->SFN,req->Slot, + req->n_pdus + ); if (RC.ru == 0) { return -1; diff --git a/nfapi/oai_integration/nfapi_vnf.c b/nfapi/oai_integration/nfapi_vnf.c index 80757089c6..e86c932483 100644 --- a/nfapi/oai_integration/nfapi_vnf.c +++ b/nfapi/oai_integration/nfapi_vnf.c @@ -596,7 +596,7 @@ extern pthread_mutex_t nfapi_sync_mutex; extern int nfapi_sync_var; int phy_sync_indication(struct nfapi_vnf_p7_config *config, uint8_t sync) { - printf("[VNF] SYNC %s\n", sync==1 ? "ACHIEVED" : "LOST"); + //printf("[VNF] SYNC %s\n", sync==1 ? "ACHIEVED" : "LOST"); if (sync==1 && nfapi_sync_var!=0) { @@ -1019,7 +1019,9 @@ int phy_cqi_indication(struct nfapi_vnf_p7_config *config, nfapi_cqi_indication_ int phy_nr_crc_indication(nfapi_nr_crc_indication_t *ind) { struct PHY_VARS_gNB_s *gNB = RC.gNB[0]; pthread_mutex_lock(&gNB->UL_INFO_mutex); - ind->number_crcs = 1; + + gNB->UL_INFO.crc_ind = *ind; + if (ind->number_crcs > 0) gNB->UL_INFO.crc_ind.crc_list = malloc(sizeof(nfapi_nr_crc_t)*ind->number_crcs); @@ -1035,6 +1037,8 @@ int phy_nr_rx_data_indication(nfapi_nr_rx_data_indication_t *ind) { struct PHY_VARS_gNB_s *gNB = RC.gNB[0]; pthread_mutex_lock(&gNB->UL_INFO_mutex); + gNB->UL_INFO.rx_ind = *ind; + if (ind->number_of_pdus > 0) gNB->UL_INFO.rx_ind.pdu_list = malloc(sizeof(nfapi_nr_rx_data_pdu_t)*ind->number_of_pdus); @@ -1051,12 +1055,14 @@ int phy_nr_uci_indication(nfapi_nr_uci_indication_t *ind) { struct PHY_VARS_gNB_s *gNB = RC.gNB[0]; pthread_mutex_lock(&gNB->UL_INFO_mutex); + gNB->UL_INFO.uci_ind = *ind; + if (ind->num_ucis > 0) gNB->UL_INFO.uci_ind.uci_list = malloc(sizeof(nfapi_nr_uci_t)*ind->num_ucis); for (int i=0; inum_ucis; i++) memcpy(&gNB->UL_INFO.uci_ind.uci_list[i], &ind->uci_list[i], sizeof(ind->uci_list[0])); - + //printf("UCI ind written to UL_info: num_ucis: %d, PDU_type : %d. \n", ind->num_ucis, ind->uci_list[0].pdu_type); pthread_mutex_unlock(&gNB->UL_INFO_mutex); return 1; @@ -1066,6 +1072,8 @@ int phy_nr_srs_indication(nfapi_nr_srs_indication_t *ind) { struct PHY_VARS_gNB_s *gNB = RC.gNB[0]; pthread_mutex_lock(&gNB->UL_INFO_mutex); + gNB->UL_INFO.srs_ind = *ind; + if (ind->number_of_pdus > 0) gNB->UL_INFO.srs_ind.pdu_list = malloc(sizeof(nfapi_nr_srs_indication_pdu_t)*ind->number_of_pdus); @@ -1087,6 +1095,8 @@ int phy_nr_rach_indication(nfapi_nr_rach_indication_t *ind) { struct PHY_VARS_gNB_s *gNB = RC.gNB[0]; pthread_mutex_lock(&gNB->UL_INFO_mutex); + gNB->UL_INFO.rach_ind = *ind; + if (ind->number_of_pdus > 0) gNB->UL_INFO.rach_ind.pdu_list = malloc(sizeof(nfapi_nr_prach_indication_pdu_t)*ind->number_of_pdus); diff --git a/nfapi/open-nFAPI/nfapi/src/nfapi_p7.c b/nfapi/open-nFAPI/nfapi/src/nfapi_p7.c index de2316e4d7..e18aa7fda2 100755 --- a/nfapi/open-nFAPI/nfapi/src/nfapi_p7.c +++ b/nfapi/open-nFAPI/nfapi/src/nfapi_p7.c @@ -4126,7 +4126,7 @@ static uint8_t unpack_dl_tti_pdsch_pdu_rel15_value(void* tlv, uint8_t **ppReadPa static uint8_t unpack_dl_tti_ssb_pdu_rel15_value(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { - printf("ssb received and unpacked. \n"); + //printf("ssb received and unpacked. \n"); nfapi_nr_dl_tti_ssb_pdu_rel15_t* value = (nfapi_nr_dl_tti_ssb_pdu_rel15_t*)tlv; return( @@ -6429,7 +6429,6 @@ static uint8_t unpack_nr_crc_indication(uint8_t **ppReadPackedMsg, uint8_t *end, return 0; } - printf("Done \n"); return 1; } diff --git a/nfapi/open-nFAPI/pnf/src/pnf_p7.c b/nfapi/open-nFAPI/pnf/src/pnf_p7.c index 5c4dfa8c9f..8786e9e53c 100644 --- a/nfapi/open-nFAPI/pnf/src/pnf_p7.c +++ b/nfapi/open-nFAPI/pnf/src/pnf_p7.c @@ -935,9 +935,9 @@ int pnf_p7_slot_ind(pnf_p7_t* pnf_p7, uint16_t phy_id, uint16_t sfn, uint16_t sl // save the curren time, sfn and slot pnf_p7->slot_start_time_hr = pnf_get_current_time_hr(); - // pnf_p7->sfn = sfn; + pnf_p7->sfn = sfn; - // pnf_p7->slot = slot; + pnf_p7->slot = slot; @@ -1559,26 +1559,23 @@ uint8_t is_nr_p7_request_in_window(uint16_t sfn,uint16_t slot, const char* name, // } // } - struct timespec curr_time; - clock_gettime(CLOCK_MONOTONIC, &curr_time); - printf("PNF SFN:%d, PNF slot:%d, VNF SFN:%d, VNF slot:%d, SFN offset:%d, Curr time;%d.%d. \n",phy->sfn,phy->slot,sfn,slot, phy->sfn - sfn,curr_time.tv_sec,curr_time.tv_nsec); if(current_sfn_slot_dec <= recv_sfn_slot_dec + timing_window){ in_window = 1; - NFAPI_TRACE(NFAPI_TRACE_NOTE, "[%d] %s is in window %d\n", current_sfn_slot_dec, name, recv_sfn_slot_dec); + //NFAPI_TRACE(NFAPI_TRACE_NOTE, "[%d] %s is in window %d\n", current_sfn_slot_dec, name, recv_sfn_slot_dec); } else if(current_sfn_slot_dec + NFAPI_MAX_SFNSLOTDEC <= recv_sfn_slot_dec + timing_window){ //checking for wrap in_window = 1; - NFAPI_TRACE(NFAPI_TRACE_NOTE, "[%d] %s is in window %d\n", current_sfn_slot_dec, name, recv_sfn_slot_dec); + //NFAPI_TRACE(NFAPI_TRACE_NOTE, "[%d] %s is in window %d\n", current_sfn_slot_dec, name, recv_sfn_slot_dec); } else { - //NFAPI_TRACE(NFAPI_TRACE_NOTE, "[%d] %s is out of window %d (delta:%d) [max:%d]\n", current_sfn_slot_dec, name, recv_sfn_slot_dec, (current_sfn_slot_dec - recv_sfn_slot_dec), timing_window); + NFAPI_TRACE(NFAPI_TRACE_NOTE, "[%d] %s is out of window %d (delta:%d) [max:%d]\n", current_sfn_slot_dec, name, recv_sfn_slot_dec, (current_sfn_slot_dec - recv_sfn_slot_dec), timing_window); }//Need to add more cases - in_window = 0; // gokul + return in_window; } @@ -1848,7 +1845,7 @@ void pnf_handle_ul_tti_request(void* pRecvMsg, int recvMsgLen, pnf_p7_t* pnf_p7) struct timespec t; clock_gettime(CLOCK_MONOTONIC, &t); - NFAPI_TRACE(NFAPI_TRACE_INFO,"%s() %ld.%09ld POPULATE UL_TTI_REQ sfn_slot:%d buffer_index:%d\n", __FUNCTION__, t.tv_sec, t.tv_nsec, sfn_slot_dec, buffer_index); + //NFAPI_TRACE(NFAPI_TRACE_INFO,"%s() %ld.%09ld POPULATE UL_TTI_REQ sfn_slot:%d buffer_index:%d\n", __FUNCTION__, t.tv_sec, t.tv_nsec, sfn_slot_dec, buffer_index); if(pnf_p7->slot_buffer[buffer_index].ul_tti_req != 0) { @@ -2133,7 +2130,7 @@ void pnf_handle_tx_data_request(void* pRecvMsg, int recvMsgLen, pnf_p7_t* pnf_p7 struct timespec t; clock_gettime(CLOCK_MONOTONIC, &t); - NFAPI_TRACE(NFAPI_TRACE_INFO,"%s() %ld.%09ld POPULATE TX_DATA_REQ sfn_sf:%d buffer_index:%d\n", __FUNCTION__, t.tv_sec, t.tv_nsec, sfn_slot_dec, buffer_index); + //NFAPI_TRACE(NFAPI_TRACE_INFO,"%s() %ld.%09ld POPULATE TX_DATA_REQ sfn_sf:%d buffer_index:%d\n", __FUNCTION__, t.tv_sec, t.tv_nsec, sfn_slot_dec, buffer_index); #if 0 if (0 && NFAPI_SFNSF2DEC(req->sfn_sf)%100==0) NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() TX_REQ.req sfn_sf:%d pdus:%d - TX_REQ is within window\n", __FUNCTION__, @@ -3202,43 +3199,9 @@ int pnf_p7_message_pump(pnf_p7_t* pnf_p7) return 0; } -struct timespec pnf_timespec_add(struct timespec lhs, struct timespec rhs) -{ - struct timespec result; - - result.tv_sec = lhs.tv_sec + rhs.tv_sec; - result.tv_nsec = lhs.tv_nsec + rhs.tv_nsec; - - if(result.tv_nsec > 1e9) - { - result.tv_sec++; - result.tv_nsec-= 1e9; - } - - return result; -} - -struct timespec pnf_timespec_sub(struct timespec lhs, struct timespec rhs) -{ - struct timespec result; - 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 - { - 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) { - uint16_t pnf_frame = 0; - uint8_t pnf_slot = 0; // initialize the mutex lock if(pthread_mutex_init(&(pnf_p7->mutex), NULL) != 0) { @@ -3311,23 +3274,6 @@ int pnf_nr_p7_message_pump(pnf_p7_t* pnf_p7) } 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 timeout; - timeout.tv_sec = 0; - timeout.tv_nsec = 500000; - - 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; @@ -3337,26 +3283,11 @@ int pnf_nr_p7_message_pump(pnf_p7_t* pnf_p7) FD_ZERO(&rfds); FD_SET(pnf_p7->p7_sock, &rfds); - clock_gettime(CLOCK_MONOTONIC, &pselect_start); + struct timeval timeout; + timeout.tv_sec = 100; + timeout.tv_usec = 0; - //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); + selectRetval = select(pnf_p7->p7_sock+1, &rfds, NULL, NULL, &timeout); uint32_t now_hr_time = pnf_get_current_time_hr(); @@ -3366,19 +3297,7 @@ int pnf_nr_p7_message_pump(pnf_p7_t* pnf_p7) if(selectRetval == 0) { // timeout - - //update slot start timing - slot_start = pnf_timespec_add(slot_start, slot_duration); - - //increment sfn/slot - if (pnf_slot == 19) - pnf_frame = (pnf_frame + 1) % 1024; - pnf_slot = (pnf_slot + 1) % 20; - pnf_p7->sfn = pnf_frame; - pnf_p7->slot = pnf_slot; - - struct timespec curr_time; - clock_gettime(CLOCK_MONOTONIC, &curr_time); + continue; } else if (selectRetval == -1 && (errno == EINTR)) { @@ -3396,7 +3315,7 @@ int pnf_nr_p7_message_pump(pnf_p7_t* pnf_p7) if(FD_ISSET(pnf_p7->p7_sock, &rfds)) { - pnf_nr_nfapi_p7_read_dispatch_message(pnf_p7, now_hr_time); + pnf_nr_nfapi_p7_read_dispatch_message(pnf_p7, now_hr_time); } } NFAPI_TRACE(NFAPI_TRACE_ERROR, "PNF_P7 Terminating..\n"); diff --git a/nfapi/open-nFAPI/vnf/src/vnf_p7.c b/nfapi/open-nFAPI/vnf/src/vnf_p7.c index 443ccc3d49..11885d7c48 100644 --- a/nfapi/open-nFAPI/vnf/src/vnf_p7.c +++ b/nfapi/open-nFAPI/vnf/src/vnf_p7.c @@ -457,7 +457,7 @@ int send_mac_subframe_indications(vnf_p7_t* vnf_p7) int vnf_send_p7_msg(vnf_p7_t* vnf_p7, nfapi_vnf_p7_connection_info_t* p7_info, uint8_t* msg, const uint32_t len) { int sendto_result = sendto(vnf_p7->socket, msg, len, 0, (struct sockaddr*)&(p7_info->remote_addr), sizeof(p7_info->remote_addr)); - //printf("\nSending p7 message sfn=%d,slot=%d\n",vnf_p7->p7_connections->sfn,vnf_p7->p7_connections->slot); + //printf("P7 msg sent \n"); if(sendto_result != len) { NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() sendto_result %d %d\n", __FUNCTION__, sendto_result, errno); @@ -534,7 +534,7 @@ int vnf_nr_p7_pack_and_send_p7_msg(vnf_p7_t* vnf_p7, nfapi_p7_message_header_t* nfapi_p7_update_transmit_timestamp(buffer, calculate_transmit_timestamp(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); - //printf("segment %d \n", segment); + } } else @@ -551,7 +551,6 @@ int vnf_nr_p7_pack_and_send_p7_msg(vnf_p7_t* vnf_p7, nfapi_p7_message_header_t* } p7_connection->sequence_number++; - return send_result; } else diff --git a/nfapi/open-nFAPI/vnf/src/vnf_p7_interface.c b/nfapi/open-nFAPI/vnf/src/vnf_p7_interface.c index d7e2fa5311..b84003ab6e 100644 --- a/nfapi/open-nFAPI/vnf/src/vnf_p7_interface.c +++ b/nfapi/open-nFAPI/vnf/src/vnf_p7_interface.c @@ -97,7 +97,7 @@ struct timespec timespec_sub(struct timespec lhs, struct timespec rhs) // send indications to mac int nfapi_nr_vnf_p7_start(nfapi_vnf_p7_config_t* config) { - uint16_t vnf_frame; uint8_t vnf_slot; + uint16_t vnf_frame; uint8_t vnf_slot; uint16_t slot_scheduled; if(config == 0) return -1; @@ -265,6 +265,21 @@ int nfapi_nr_vnf_p7_start(nfapi_vnf_p7_config_t* config) } */ + if(setup_time > 10 && slot_scheduled == 0){ + + // Call the scheduler + struct PHY_VARS_gNB_s *gNB = RC.gNB[0]; + pthread_mutex_lock(&gNB->UL_INFO_mutex); + gNB->UL_INFO.frame = vnf_frame; + gNB->UL_INFO.slot = vnf_slot; + + gNB->UL_INFO.module_id = gNB->Mod_id; + gNB->UL_INFO.CC_id = gNB->CC_id; + gNB->if_inst->NR_UL_indication(&gNB->UL_INFO); + pthread_mutex_unlock(&gNB->UL_INFO_mutex); + //printf("Scheduler called at SFN/slot %d.%d. \n",vnf_frame,vnf_slot); + slot_scheduled = 1; + } //long wraps = pselect_timeout.tv_nsec % 1e9; @@ -410,18 +425,18 @@ struct timespec current_time; clock_gettime(CLOCK_MONOTONIC, ¤t_time); // pselect timed out - if(setup_time > 10){ - // Call the scheduler - struct PHY_VARS_gNB_s *gNB = RC.gNB[0]; - pthread_mutex_lock(&gNB->UL_INFO_mutex); - gNB->UL_INFO.frame = vnf_frame; - gNB->UL_INFO.slot = vnf_slot; + // if(setup_time > 10){ + // // Call the scheduler + // struct PHY_VARS_gNB_s *gNB = RC.gNB[0]; + // pthread_mutex_lock(&gNB->UL_INFO_mutex); + // gNB->UL_INFO.frame = vnf_frame; + // gNB->UL_INFO.slot = vnf_slot; - gNB->UL_INFO.module_id = gNB->Mod_id; - gNB->UL_INFO.CC_id = gNB->CC_id; - gNB->if_inst->NR_UL_indication(&gNB->UL_INFO); - pthread_mutex_unlock(&gNB->UL_INFO_mutex); - } + // gNB->UL_INFO.module_id = gNB->Mod_id; + // gNB->UL_INFO.CC_id = gNB->CC_id; + // gNB->if_inst->NR_UL_indication(&gNB->UL_INFO); + // pthread_mutex_unlock(&gNB->UL_INFO_mutex); + // } while(curr != 0) { @@ -437,7 +452,7 @@ struct timespec current_time; { curr->slot++; } - printf("Frame = %d, slot = %d in VNF main loop. \n",curr->sfn,curr->slot); + //printf("Frame = %d, slot = %d in VNF main loop. \n",curr->sfn,curr->slot); vnf_frame = curr->sfn; vnf_slot = curr->slot; struct timespec curr_time; @@ -450,17 +465,14 @@ struct timespec current_time; curr = curr->next; } send_mac_slot_indications(vnf_p7); - + slot_scheduled = 0; } else if(selectRetval > 0) { // have a p7 message if(FD_ISSET(vnf_p7->socket, &rfds)) { - printf("P7 message received \n"); - vnf_nr_p7_read_dispatch_message(vnf_p7); - - + vnf_nr_p7_read_dispatch_message(vnf_p7); } } else @@ -902,7 +914,6 @@ int nfapi_vnf_p7_ul_tti_req(nfapi_vnf_p7_config_t* config, nfapi_nr_ul_tti_reque { 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); } diff --git a/openair1/PHY/NR_TRANSPORT/nr_dci_tools.c b/openair1/PHY/NR_TRANSPORT/nr_dci_tools.c index c562dfaa41..c04bb308e2 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_dci_tools.c +++ b/openair1/PHY/NR_TRANSPORT/nr_dci_tools.c @@ -211,8 +211,8 @@ int16_t find_nr_pdcch(int frame,int slot, PHY_VARS_gNB *gNB,find_type_t type) { for (i=0; ipdcch_pdu[i].frame,gNB->pdcch_pdu[i].slot,first_free_index); if ((gNB->pdcch_pdu[i].frame == frame) && - (gNB->pdcch_pdu[i].slot==slot)) return i; - else if ( gNB->pdcch_pdu[i].frame==-1 && first_free_index==-1) first_free_index=i; + (gNB->pdcch_pdu[i].slot==slot)) {return i;} + else if ( gNB->pdcch_pdu[i].frame==-1 && first_free_index==-1) {first_free_index=i;} } if (type == SEARCH_EXIST) return -1; @@ -227,7 +227,7 @@ void nr_fill_dci(PHY_VARS_gNB *gNB, nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu_rel15 = &pdcch_pdu->pdcch_pdu_rel15; NR_gNB_DLSCH_t *dlsch; - + //printf("find pdcch from nr_fill_dci \n"); int pdcch_id = find_nr_pdcch(frame,slot,gNB,SEARCH_EXIST_OR_FREE); AssertFatal(pdcch_id>=0 && pdcch_idpdcch_pdu[pdcch_id].pdcch_pdu,(void*)pdcch_pdu,sizeof(*pdcch_pdu)); @@ -285,7 +285,7 @@ void nr_fill_ul_dci(PHY_VARS_gNB *gNB, nfapi_nr_ul_dci_request_pdus_t *pdcch_pdu) { nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu_rel15 = &pdcch_pdu->pdcch_pdu.pdcch_pdu_rel15; - + //printf("find ul dci from fill_ul_dci \n"); int pdcch_id = find_nr_ul_dci(frame,slot,gNB,SEARCH_EXIST_OR_FREE); AssertFatal(pdcch_id>=0 && pdcch_idul_pdcch_pdu[pdcch_id].pdcch_pdu,(void*)pdcch_pdu,sizeof(*pdcch_pdu)); diff --git a/openair1/PHY/NR_TRANSPORT/pucch_rx.c b/openair1/PHY/NR_TRANSPORT/pucch_rx.c index d0359a3fa1..eeaf993c61 100644 --- a/openair1/PHY/NR_TRANSPORT/pucch_rx.c +++ b/openair1/PHY/NR_TRANSPORT/pucch_rx.c @@ -88,8 +88,8 @@ void nr_fill_pucch(PHY_VARS_gNB *gNB, int frame, int slot, nfapi_nr_pucch_pdu_t *pucch_pdu) { - if (NFAPI_MODE == NFAPI_MODE_PNF) - gNB->pucch[0]->active = 0; + // if (NFAPI_MODE == NFAPI_MODE_PNF) + // gNB->pucch[0]->active = 0; int id = nr_find_pucch(pucch_pdu->rnti,frame,slot,gNB); AssertFatal( (id>=0) && (idnumDlDci:%d\n",frame,slot, slot, pdcch_pdu->pdcch_pdu_rel15.numDlDci); + LOG_D(PHY,"Frame %d, Slot %d: DCI processing - pdcch_pdu_rel15->numDlDci:%d\n",frame,slot, pdcch_pdu->pdcch_pdu_rel15.numDlDci); // copy dci configuration into gNB structure // gNB->pdcch_pdu = pdcch_pdu; @@ -119,7 +119,7 @@ void handle_nfapi_nr_ul_dci_pdu(PHY_VARS_gNB *gNB, int frame, int slot, nfapi_nr_ul_dci_request_pdus_t *ul_dci_request_pdu) { - LOG_D(PHY,"Frame %d, Slot %d: UL DCI processing - proc:slot_tx:%d pdcch_pdu_rel15->numDlDci:%d\n",frame,slot, slot, ul_dci_request_pdu->pdcch_pdu.pdcch_pdu_rel15.numDlDci); + LOG_D(PHY,"Frame %d, Slot %d: UL DCI processing - pdcch_pdu_rel15->numDlDci:%d\n",frame,slot, ul_dci_request_pdu->pdcch_pdu.pdcch_pdu_rel15.numDlDci); // copy dci configuration into gNB structure // gNB->ul_dci_pdu = ul_dci_request_pdu; @@ -236,8 +236,10 @@ void nr_schedule_response(NR_Sched_Rsp_t *Sched_INFO){ } } + //printf("Inside NR schedule response SFN/slot %d.%d. \n",frame,slot); if(NFAPI_MODE != NFAPI_MONOLITHIC && number_ul_tti_pdu>0) - { + { + //printf("SFN/slot %d.%d Sending ul tti req \n",frame,slot); oai_nfapi_ul_tti_req(UL_tti_req); } diff --git a/openair1/SCHED_NR/phy_procedures_nr_gNB.c b/openair1/SCHED_NR/phy_procedures_nr_gNB.c index 76b35b6378..c410805560 100644 --- a/openair1/SCHED_NR/phy_procedures_nr_gNB.c +++ b/openair1/SCHED_NR/phy_procedures_nr_gNB.c @@ -147,16 +147,16 @@ void phy_procedures_gNB_TX(PHY_VARS_gNB *gNB, } VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_gNB_COMMON_TX,1); - if (NFAPI_MODE == NFAPI_MONOLITHIC || NFAPI_MODE == NFAPI_MODE_PNF) { + for (int i=0; iLmax; i++) { if (gNB->ssb[i].active) { nr_common_signal_procedures(gNB,frame,slot,gNB->ssb[i].ssb_pdu); gNB->ssb[i].active = false; } } - } + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_gNB_COMMON_TX,0); - + //printf("find pdcch from TX func \n"); int pdcch_pdu_id=find_nr_pdcch(frame,slot,gNB,SEARCH_EXIST); int ul_pdcch_pdu_id=find_nr_ul_dci(frame,slot,gNB,SEARCH_EXIST); @@ -556,6 +556,7 @@ int phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx) { for (int i=0;ipucch[i]; if (pucch) { + LOG_D(PHY, "SFN/slot = %d.%d, pucch[%d]->active = %d \n", frame_rx, slot_rx, i,pucch->active); if ((pucch->active == 1) && (pucch->frame == frame_rx) && (pucch->slot == slot_rx) ) { @@ -585,7 +586,9 @@ int phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx) { pucch_pdu); gNB->UL_INFO.uci_ind.num_ucis += 1; + //printf("SFN/slot %d.%d pucch active of index %d set to 0. \n", frame_rx, slot_rx, i); pucch->active = 0; + //printf("Decode pucch num ucis +=1 in %d.%d \n",frame_rx,slot_rx); break; case 2: num_ucis = gNB->UL_INFO.uci_ind.num_ucis; @@ -602,6 +605,7 @@ int phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx) { pucch_pdu); gNB->UL_INFO.uci_ind.num_ucis += 1; + //printf("SFN/slot %d.%d pucch active of index %d set to 0. \n", frame_rx, slot_rx, i); pucch->active = 0; break; default: diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c index 93a2d87345..fde53c3d0c 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c @@ -60,7 +60,7 @@ void nr_fill_nfapi_pucch(module_id_t mod_id, memset(pucch_pdu, 0, sizeof(nfapi_nr_pucch_pdu_t)); future_ul_tti_req->n_pdus += 1; - LOG_I(MAC, + LOG_D(MAC, "%4d.%2d Scheduling pucch reception in %4d.%2d: bits SR %d, ACK %d, CSI %d on res %d\n", frame, slot, @@ -144,7 +144,7 @@ void nr_schedule_pucch(int Mod_idP, || frameP != curr_pucch->frame || slotP != curr_pucch->ul_slot) continue; - LOG_I(NR_MAC,"Scheduling PUCCH[%d] RX for UE %d in %d.%d O_ack %d\n",i,UE_id,curr_pucch->frame,curr_pucch->ul_slot,O_ack); + LOG_D(NR_MAC,"Scheduling PUCCH[%d] RX for UE %d in %d.%d O_ack %d\n",i,UE_id,curr_pucch->frame,curr_pucch->ul_slot,O_ack); nr_fill_nfapi_pucch(Mod_idP, frameP, slotP, curr_pucch, UE_id); memset(curr_pucch, 0, sizeof(*curr_pucch)); } @@ -983,6 +983,7 @@ static NR_UE_harq_t *find_harq(module_id_t mod_id, frame_t frame, sub_frame_t sl harq->feedback_slot, frame, slot); + //printf("handling harq \n"); remove_front_nr_list(&sched_ctrl->feedback_dl_harq); handle_dl_harq(mod_id, UE_id, pid, 0); pid = sched_ctrl->feedback_dl_harq.head; @@ -1022,12 +1023,14 @@ void handle_nr_uci_pucch_0_1(module_id_t mod_id, for (int harq_bit = 0; harq_bit < uci_01->harq->num_harq; harq_bit++) { const uint8_t harq_value = uci_01->harq->harq_list[harq_bit].harq_value; const uint8_t harq_confidence = uci_01->harq->harq_confidence_level; + //printf("handle uci 0_1 find harq SFN/slot %d.%d \n",frame,slot); NR_UE_harq_t *harq = find_harq(mod_id, frame, slot, UE_id); if (!harq) break; DevAssert(harq->is_waiting); const int8_t pid = sched_ctrl->feedback_dl_harq.head; remove_front_nr_list(&sched_ctrl->feedback_dl_harq); + //printf("handling harq \n"); handle_dl_harq(mod_id, UE_id, pid, harq_value == 1 && harq_confidence == 0); } } diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c index a3ab18735e..3ec7facbfb 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c @@ -1330,8 +1330,7 @@ void nr_schedule_ulsch(module_id_t module_id, frame_t frame, sub_frame_t slot) if (harq_id < 0) { /* PP has not selected a specific HARQ Process, get a new one */ harq_id = sched_ctrl->available_ul_harq.head; - // if(NFAPI_MODE == NFAPI_MODE_VNF) - // harq_id = 1; + //printf("SFN/slot %d.%d harq id = %d \n", frame, slot, harq_id); AssertFatal(harq_id >= 0, "no free HARQ process available for UE %d\n", UE_id); @@ -1351,8 +1350,6 @@ void nr_schedule_ulsch(module_id_t module_id, frame_t frame, sub_frame_t slot) add_tail_nr_list(&sched_ctrl->feedback_ul_harq, harq_id); cur_harq->feedback_slot = sched_pusch->slot; cur_harq->is_waiting = true; - // if (NFAPI_MODE == NFAPI_MODE_VNF) - // cur_harq->is_waiting = 0; int rnti_types[2] = { NR_RNTI_C, 0 }; diff --git a/openair2/NR_PHY_INTERFACE/NR_IF_Module.c b/openair2/NR_PHY_INTERFACE/NR_IF_Module.c index edc3a7909b..f90361f564 100644 --- a/openair2/NR_PHY_INTERFACE/NR_IF_Module.c +++ b/openair2/NR_PHY_INTERFACE/NR_IF_Module.c @@ -88,7 +88,7 @@ void handle_nr_uci(NR_UL_IND_t *UL_info) { if(NFAPI_MODE == NFAPI_MODE_PNF) { if (UL_info->uci_ind.num_ucis>0) { - //LOG_D(PHY,"UL_info->crc_ind.crc_indication_body.number_of_crcs:%d CRC_IND:SFN/SF:%d\n", UL_info->crc_ind.crc_indication_body.number_of_crcs, NFAPI_SFNSF2DEC(UL_info->crc_ind.sfn_sf)); + LOG_I(PHY,"PNF Sending UL_info->num_ucis:%d PDU_type: %d, SFN/SF:%d.%d \n", UL_info->uci_ind.num_ucis, UL_info->uci_ind.uci_list[0].pdu_type ,UL_info->frame, UL_info->slot); oai_nfapi_nr_uci_indication(&UL_info->uci_ind); UL_info->uci_ind.num_ucis = 0; } @@ -99,7 +99,7 @@ void handle_nr_uci(NR_UL_IND_t *UL_info) const sub_frame_t slot = UL_info->slot; int num_ucis = UL_info->uci_ind.num_ucis; nfapi_nr_uci_t *uci_list = UL_info->uci_ind.uci_list; - + //printf("handling UCI SFN/slot: %d.%d, num_ucis: %d \n", frame,slot, num_ucis); for (int i = 0; i < num_ucis; i++) { switch (uci_list[i].pdu_type) { case NFAPI_NR_UCI_PUSCH_PDU_TYPE: @@ -107,12 +107,14 @@ void handle_nr_uci(NR_UL_IND_t *UL_info) break; case NFAPI_NR_UCI_FORMAT_0_1_PDU_TYPE: { + //printf("handle uci format 0_1 \n"); const nfapi_nr_uci_pucch_pdu_format_0_1_t *uci_pdu = &uci_list[i].pucch_pdu_format_0_1; handle_nr_uci_pucch_0_1(mod_id, frame, slot, uci_pdu); break; } case NFAPI_NR_UCI_FORMAT_2_3_4_PDU_TYPE: { + //printf("handle uci format 2_3_4 \n"); const nfapi_nr_uci_pucch_pdu_format_2_3_4_t *uci_pdu = &uci_list[i].pucch_pdu_format_2_3_4; handle_nr_uci_pucch_2_3_4(mod_id, frame, slot, uci_pdu); break; From fe2fa4ce8de33d13db41529ab09abae0888b2540 Mon Sep 17 00:00:00 2001 From: francescomani Date: Thu, 29 Jul 2021 11:26:47 +0200 Subject: [PATCH 63/91] adding comments for transform precoding --- openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c | 1 + openair1/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c | 1 + openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c | 6 +++--- openair1/SIMULATION/NR_PHY/ulsim.c | 5 ++++- 4 files changed, 9 insertions(+), 4 deletions(-) diff --git a/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c b/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c index fac5ad46ac..ee8c93ffc1 100644 --- a/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c +++ b/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c @@ -129,6 +129,7 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB, //------------------generate DMRS------------------// + // transform precoding = 1 means disabled if (pusch_pdu->transform_precoding == 1) { nr_pusch_dmrs_rx(gNB, Ns, gNB->nr_gold_pusch_dmrs[pusch_pdu->scid][Ns][symbol], &pilot[0], 1000, 0, nb_rb_pusch, (pusch_pdu->bwp_start + pusch_pdu->rb_start)*NR_NB_SC_PER_RB, pusch_pdu->dmrs_config_type); diff --git a/openair1/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c b/openair1/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c index 12170d187a..19b30c0bec 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c +++ b/openair1/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c @@ -1317,6 +1317,7 @@ int nr_rx_pusch(PHY_VARS_gNB *gNB, rel15_ul->rb_size); stop_meas(&gNB->ulsch_mrc_stats); + // transform precoding = 0 means enabled if (rel15_ul->transform_precoding == 0) { #ifdef __AVX2__ diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c b/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c index 12481b985a..4ada19ba33 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c @@ -252,7 +252,7 @@ void nr_ue_ulsch_procedures(PHY_VARS_NR_UE *UE, uint8_t u = 0, v = 0; int16_t *dmrs_seq = NULL; - // enbaled + // if transform precoding is enbaled (value 0) if (pusch_pdu->transform_precoding == 0) { uint32_t nb_re_pusch=nb_rb * NR_NB_SC_PER_RB; @@ -354,7 +354,7 @@ void nr_ue_ulsch_procedures(PHY_VARS_NR_UE *UE, if ((ul_dmrs_symb_pos >> l) & 0x01) { is_dmrs_sym = 1; - // disabled + // transform precoding disabled (value 1) if (pusch_pdu->transform_precoding == 1){ if (dmrs_type == pusch_dmrs_type1) @@ -405,7 +405,7 @@ void nr_ue_ulsch_procedures(PHY_VARS_NR_UE *UE, } if (is_dmrs == 1) { - // if enabled + // if transform precoding is enabled if (pusch_pdu->transform_precoding == 0) { ((int16_t*)txdataF[ap])[(sample_offsetF)<<1] = (Wt[l_prime[0]]*Wf[k_prime]*AMP*dmrs_seq[2*dmrs_idx]) >> 15; diff --git a/openair1/SIMULATION/NR_PHY/ulsim.c b/openair1/SIMULATION/NR_PHY/ulsim.c index 7892833d31..aa3dbeadfe 100644 --- a/openair1/SIMULATION/NR_PHY/ulsim.c +++ b/openair1/SIMULATION/NR_PHY/ulsim.c @@ -566,7 +566,7 @@ int main(int argc, char **argv) case 'Z': - transform_precoding = 0; + transform_precoding = 0; // enabled num_dmrs_cdm_grps_no_data = 2; mcs_table = 3; @@ -840,6 +840,7 @@ int main(int argc, char **argv) uint16_t number_dmrs_symbols = get_dmrs_symbols_in_slot(l_prime_mask, nb_symb_sch); uint8_t nb_re_dmrs = (dmrs_config_type == pusch_dmrs_type1) ? 6 : 4; + // if transform precoding is enabled if (transform_precoding == 0) { AssertFatal(enable_ptrs == 0, "PTRS NOT SUPPORTED IF TRANSFORM PRECODING IS ENABLED\n"); @@ -1045,6 +1046,7 @@ int main(int argc, char **argv) pusch_pdu->pusch_ptrs.ptrs_ports_list = (nfapi_nr_ptrs_ports_t *) malloc(2*sizeof(nfapi_nr_ptrs_ports_t)); pusch_pdu->pusch_ptrs.ptrs_ports_list[0].ptrs_re_offset = 0; + // if transform precoding is enabled if (transform_precoding == 0) { pusch_pdu->dfts_ofdm.low_papr_group_number = *scc->physCellId % 30; // U as defined in 38.211 section 6.4.1.1.1.2 @@ -1105,6 +1107,7 @@ int main(int argc, char **argv) ul_config.ul_config_list[0].pusch_config_pdu.transform_precoding = transform_precoding; + // if transform precoding is enabled if (transform_precoding == 0) { ul_config.ul_config_list[0].pusch_config_pdu.dfts_ofdm.low_papr_group_number = *scc->physCellId % 30;// U as defined in 38.211 section 6.4.1.1.1.2 From c3612b969fabb5cdd2570a85312fb19605ca41a3 Mon Sep 17 00:00:00 2001 From: Laurent OpenCells Date: Thu, 29 Jul 2021 11:56:59 +0200 Subject: [PATCH 64/91] fix regression on cuda test --- cmake_targets/CMakeLists.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/cmake_targets/CMakeLists.txt b/cmake_targets/CMakeLists.txt index 394dda5ea2..16fe7b1eab 100644 --- a/cmake_targets/CMakeLists.txt +++ b/cmake_targets/CMakeLists.txt @@ -319,7 +319,8 @@ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${C_FLAGS_PROCESSOR} ${commonOpts} -std=c++11 -D${MKVER}") if (CUDA_FOUND) - add_definitions(-D CUDA_FLAG ) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DCUDA_FLAG") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DCUDA_FLAG") endif() if (SANITIZE_ADDRESS) From 8d7636bb1ea7c963c64f2f64c69b3ee4520a4c28 Mon Sep 17 00:00:00 2001 From: francescomani Date: Thu, 29 Jul 2021 14:31:38 +0200 Subject: [PATCH 65/91] temp fix for SIB1 coreset --- openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c | 12 ++++++++++-- .../LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c | 5 ++++- openair2/RRC/NR/MESSAGES/asn1_msg.c | 1 + 3 files changed, 15 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 1d3f69d876..220b4a921e 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c @@ -941,7 +941,11 @@ void nr_generate_Msg2(module_id_t module_idP, int CC_id, frame_t frameP, sub_fra pdsch_TimeDomainAllocationList = scc->downlinkConfigCommon->initialDownlinkBWP->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList; } BWPStart = NRRIV2PRBOFFSET(genericParameters->locationAndBandwidth, MAX_BWP_SIZE); - coreset = get_coreset(scc,bwp, ss, NR_SearchSpace__searchSpaceType_PR_common); + + if (*ss->controlResourceSetId == 0) + coreset = nr_mac->sched_ctrlCommon->coreset; // this is coreset 0 + else + coreset = get_coreset(scc, bwp, ss, NR_SearchSpace__searchSpaceType_PR_common); AssertFatal(coreset!=NULL,"Coreset cannot be null for RA-Msg2\n"); @@ -1191,7 +1195,11 @@ void nr_generate_Msg4(module_id_t module_idP, int CC_id, frame_t frameP, sub_fra genericParameters= &scc->downlinkConfigCommon->initialDownlinkBWP->genericParameters; pdsch_TimeDomainAllocationList = scc->downlinkConfigCommon->initialDownlinkBWP->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList; } - coreset = get_coreset(scc,bwp, ss, NR_SearchSpace__searchSpaceType_PR_common); + + if (*ss->controlResourceSetId == 0) + coreset = nr_mac->sched_ctrlCommon->coreset; // this is coreset 0 + else + coreset = get_coreset(scc, bwp, ss, NR_SearchSpace__searchSpaceType_PR_common); AssertFatal(coreset!=NULL,"Coreset cannot be null for RA-Msg4\n"); diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c index 546602427a..508d218c78 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c @@ -1863,7 +1863,10 @@ int add_new_nr_ue(module_id_t mod_idP, rnti_t rntiP, NR_CellGroupConfig_t *CellG sched_ctrl->active_bwp = bwpList ? bwpList->list.array[bwp_id - 1] : NULL; const int target_ss = sched_ctrl->active_bwp ? NR_SearchSpace__searchSpaceType_PR_ue_Specific : NR_SearchSpace__searchSpaceType_PR_common; sched_ctrl->search_space = get_searchspace(scc, sched_ctrl->active_bwp ? sched_ctrl->active_bwp->bwp_Dedicated : NULL, target_ss); - sched_ctrl->coreset = get_coreset(scc, sched_ctrl->active_bwp, sched_ctrl->search_space, target_ss); + if (*sched_ctrl->search_space->controlResourceSetId == 0) + sched_ctrl->coreset = RC.nrmac[mod_idP]->sched_ctrlCommon->coreset; // this is coreset 0 + else + sched_ctrl->coreset = get_coreset(scc, sched_ctrl->active_bwp, sched_ctrl->search_space, target_ss); const struct NR_UplinkConfig__uplinkBWP_ToAddModList *ubwpList = servingCellConfig ? servingCellConfig->uplinkConfig->uplinkBWP_ToAddModList : NULL; if (ubwpList) AssertFatal(ubwpList->list.count == 1, "uplinkBWP_ToAddModList has %d BWP!\n", diff --git a/openair2/RRC/NR/MESSAGES/asn1_msg.c b/openair2/RRC/NR/MESSAGES/asn1_msg.c index e36644afb0..4399d2c403 100755 --- a/openair2/RRC/NR/MESSAGES/asn1_msg.c +++ b/openair2/RRC/NR/MESSAGES/asn1_msg.c @@ -426,6 +426,7 @@ uint8_t do_SIB1_NR(rrc_gNB_carrier_data_t *carrier, } sib1->servingCellConfigCommon->downlinkConfigCommon.initialDownlinkBWP.pdcch_ConfigCommon = configuration->scc->downlinkConfigCommon->initialDownlinkBWP->pdcch_ConfigCommon; + sib1->servingCellConfigCommon->downlinkConfigCommon.initialDownlinkBWP.pdcch_ConfigCommon->choice.setup->commonControlResourceSet = NULL; sib1->servingCellConfigCommon->downlinkConfigCommon.initialDownlinkBWP.pdcch_ConfigCommon->choice.setup->commonSearchSpaceList = CALLOC(1,sizeof(struct NR_PDCCH_ConfigCommon__commonSearchSpaceList)); asn_set_empty(&sib1->servingCellConfigCommon->downlinkConfigCommon.initialDownlinkBWP.pdcch_ConfigCommon->choice.setup->commonSearchSpaceList->list); From d9fdbe6338324cb71a8bfa3a84450538105ac98f Mon Sep 17 00:00:00 2001 From: francescomani Date: Thu, 29 Jul 2021 15:59:02 +0200 Subject: [PATCH 66/91] fix for pucch prb size --- openair1/SCHED_NR_UE/pucch_uci_ue_nr.c | 8 +++----- openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c | 1 + 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/openair1/SCHED_NR_UE/pucch_uci_ue_nr.c b/openair1/SCHED_NR_UE/pucch_uci_ue_nr.c index 88ea3a2524..2dbe6dcb9a 100644 --- a/openair1/SCHED_NR_UE/pucch_uci_ue_nr.c +++ b/openair1/SCHED_NR_UE/pucch_uci_ue_nr.c @@ -341,15 +341,13 @@ void pucch_procedures_ue_nr(PHY_VARS_NR_UE *ue, int tx_amp; -#if defined(EXMIMO) || defined(OAI_USRP) || defined(OAI_BLADERF) || defined(OAI_LMSSDR) || defined(OAI_ADRV9371_ZC706) - tx_amp = nr_get_tx_amp(pucch_tx_power, ue->tx_power_max_dBm, ue->frame_parms.N_RB_UL, nb_of_prbs); -#else - tx_amp = AMP; -#endif + if (tx_amp == 0) + tx_amp = AMP; + LOG_D(PHY,"Generation of PUCCH format %d at frame.slot %d.%d\n",pucch_pdu->format_type,proc->frame_tx,nr_slot_tx); diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c index 26d0f370cf..02680e7bbc 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c @@ -1414,6 +1414,7 @@ void nr_ue_configure_pucch(NR_UE_MAC_INST_t *mac, pucch_pdu->prb_start = pucchres->startingPRB; pucch_pdu->freq_hop_flag = pucchres->intraSlotFrequencyHopping!= NULL ? 1 : 0; pucch_pdu->second_hop_prb = pucchres->secondHopPRB!= NULL ? *pucchres->secondHopPRB : 0; + pucch_pdu->prb_size = 1; // format 0 or 1 if ((O_SR+O_CSI+O_SR) > (sizeof(uint64_t)*8)) { LOG_E(MAC,"PUCCH number of UCI bits exceeds payload size : at line %d in function %s of file %s \n", LINE_FILE , __func__, FILE_NAME); From 5c744429c9548507571df2deda29d61aaa590c4b Mon Sep 17 00:00:00 2001 From: francescomani Date: Mon, 2 Aug 2021 12:47:32 +0200 Subject: [PATCH 67/91] bugfix: not scheduling pucch transmission at UE when there is only negative SR --- openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c index b6dbe84d5d..4522e292ac 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c @@ -1891,6 +1891,10 @@ void nr_ue_pucch_scheduler(module_id_t module_idP, frame_t frameP, int slotP, in N_UCI = O_SR + O_ACK + O_CSI; + // do no transmit pucch if only SR scheduled and it is negative + if ((O_ACK + O_CSI) == 0 && pucch->sr_payload == 0) + return; + if (N_UCI > 0) { pucch->resource_set_id = find_pucch_resource_set(mac, N_UCI); From 39307247c92b3ce04571cff856885737eca1d63d Mon Sep 17 00:00:00 2001 From: francescomani Date: Mon, 2 Aug 2021 12:49:50 +0200 Subject: [PATCH 68/91] change error log to log_d to avoid flooding of error messages at ue --- 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 02680e7bbc..1d18c8ef3e 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c @@ -1552,7 +1552,7 @@ int16_t get_pucch_tx_power_ue(NR_UE_MAC_INST_t *mac, int16_t G_b_f_c = 0; if (pucch_Config->spatialRelationInfoToAddModList != NULL) { /* FFS TODO NR */ - LOG_E(MAC,"PUCCH Spatial relation infos are not yet implemented : at line %d in function %s of file %s \n", LINE_FILE , __func__, __FILE__); + LOG_D(MAC,"PUCCH Spatial relation infos are not yet implemented : at line %d in function %s of file %s \n", LINE_FILE , __func__, __FILE__); return (PUCCH_POWER_DEFAULT); } From a518701a27d7fbca19a4300b851964c0a218b49f Mon Sep 17 00:00:00 2001 From: Raphael Defosseux Date: Tue, 3 Aug 2021 11:52:31 +0200 Subject: [PATCH 69/91] feat(docker): adding conf template to gNB container image Signed-off-by: Raphael Defosseux --- .../enb.band7.tm1.25PRB.usrpb210.conf | 36 ++- .../enb.band7.tm1.fr1.25PRB.usrpb210.conf | 274 +++++++++--------- .../gnb.band78.tm1.fr1.106PRB.usrpb210.conf | 130 ++++----- docker/Dockerfile.gNB.rhel8.2 | 31 +- docker/Dockerfile.gNB.ubuntu18 | 31 +- docker/Dockerfile.nrUE.rhel8.2 | 2 +- docker/Dockerfile.phySim.rhel8.2 | 2 +- docker/Dockerfile.ran.rhel8.2 | 3 + docker/Dockerfile.ran.ubuntu18 | 6 +- docker/scripts/enb_entrypoint.sh | 2 + docker/scripts/enb_parameters.yaml | 6 +- docker/scripts/generateTemplate.py | 5 +- docker/scripts/gnb_entrypoint.sh | 62 ++++ docker/scripts/gnb_parameters.yaml | 64 ++++ 14 files changed, 375 insertions(+), 279 deletions(-) create mode 100755 docker/scripts/gnb_entrypoint.sh create mode 100644 docker/scripts/gnb_parameters.yaml diff --git a/ci-scripts/conf_files/enb.band7.tm1.25PRB.usrpb210.conf b/ci-scripts/conf_files/enb.band7.tm1.25PRB.usrpb210.conf index f29fc163b3..6fc8401236 100644 --- a/ci-scripts/conf_files/enb.band7.tm1.25PRB.usrpb210.conf +++ b/ci-scripts/conf_files/enb.band7.tm1.25PRB.usrpb210.conf @@ -6,10 +6,8 @@ eNBs = ( { ////////// Identification parameters: - eNB_ID = 0xe00; - + eNB_ID = 0xe01; cell_type = "CELL_MACRO_ENB"; - eNB_name = "eNB-Eurecom-LTEBox"; // Tracking area code, 0x0000 and 0xfffe are reserved values @@ -128,24 +126,25 @@ eNBs = 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_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; + //SSB central frequency of NR secondary cell group (for ENDC NSA) + nr_scg_ssb_freq = 641272; } ); - srb1_parameters : { # timer_poll_retransmit = (ms) [5, 10, 15, 20,... 250, 300, 350, ... 500] @@ -175,6 +174,7 @@ eNBs = SCTP_OUTSTREAMS = 2; }; + enable_measurement_reports = "no"; ////////// MME parameters: mme_ip_address = ( { ipv4 = "CI_MME_IP_ADDR"; @@ -185,10 +185,8 @@ eNBs = } ); - enable_measurement_reports = "no"; - ///X2 - enable_x2 = "no"; + enable_x2 = "no"; t_reloc_prep = 1000; /* unit: millisecond */ tx2_reloc_overall = 2000; /* unit: millisecond */ t_dc_prep = 1000; /* unit: millisecond */ diff --git a/ci-scripts/conf_files/enb.band7.tm1.fr1.25PRB.usrpb210.conf b/ci-scripts/conf_files/enb.band7.tm1.fr1.25PRB.usrpb210.conf index fff3cd1b9a..454649f20d 100644 --- a/ci-scripts/conf_files/enb.band7.tm1.fr1.25PRB.usrpb210.conf +++ b/ci-scripts/conf_files/enb.band7.tm1.fr1.25PRB.usrpb210.conf @@ -5,110 +5,106 @@ Asn1_verbosity = "none"; eNBs = ( { - # real_time choice in {hard, rt-preempt, no} - real_time = "no"; ////////// Identification parameters: eNB_ID = 0xe01; cell_type = "CELL_MACRO_ENB"; eNB_name = "eNB-Eurecom-LTEBox"; // Tracking area code, 0x0000 and 0xfffe are reserved values - tracking_area_code = 1; - plmn_list = ( - { mcc = 222; mnc = 01; mnc_length = 2; } - ); + tracking_area_code = 1; + plmn_list = ( { mcc = 222; mnc = 01; mnc_length = 2; } ); tr_s_preference = "local_mac" + // In seconds + rrc_inactivity_threshold = 0; + ////////// Physical parameters: component_carriers = ( { - node_function = "eNodeB_3GPP"; - node_timing = "synch_to_ext_device"; - node_synch_ref = 0; - nb_antenna_ports = 1; - ue_TransmissionMode = 1; - frame_type = "FDD"; - tdd_config = 3; - tdd_config_s = 0; - prefix_type = "NORMAL"; - eutra_band = 7; - downlink_frequency = 2680000000L; - uplink_frequency_offset = -120000000; - - Nid_cell = 0; - N_RB_DL = 25; - Nid_cell_mbsfn = 0; - nb_antennas_tx = 1; - nb_antennas_rx = 1; - prach_root = 0; - tx_gain = 90; - rx_gain = 115; - pbch_repetition = "FALSE"; - - 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 = -29; - pdsch_p_b = 0; - pusch_n_SB = 1; - pusch_enable64QAM = "DISABLE"; - pusch_hoppingMode = "interSubFrame"; - pusch_hoppingOffset = 0; - pusch_groupHoppingEnabled = "ENABLE"; - pusch_groupAssignment = 0; - pusch_sequenceHoppingEnabled = "DISABLE"; - pusch_nDMRS1 = 1; - phich_duration = "NORMAL"; - phich_resource = "ONESIXTH"; - srs_enable = "DISABLE"; + 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 = 2680000000L; + uplink_frequency_offset = -120000000; + Nid_cell = 0; + N_RB_DL = 25; + Nid_cell_mbsfn = 0; + nb_antenna_ports = 1; + nb_antennas_tx = 1; + nb_antennas_rx = 1; + tx_gain = 90; + rx_gain = 115; + 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= -29; + pdsch_p_b = 0; + pusch_n_SB = 1; + pusch_enable64QAM = "DISABLE"; + pusch_hoppingMode = "interSubFrame"; + pusch_hoppingOffset = 0; + pusch_groupHoppingEnabled = "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 =; + srs_BandwidthConfig =; + srs_SubframeConfig =; + srs_ackNackST =; + srs_MaxUpPts =; */ - pusch_p0_Nominal = -96; - pusch_alpha = "AL1"; - pucch_p0_Nominal = -96; - msg3_delta_Preamble = 6; - pucch_deltaF_Format1 = "deltaF2"; - pucch_deltaF_Format1b = "deltaF3"; - pucch_deltaF_Format2 = "deltaF0"; - pucch_deltaF_Format2a = "deltaF0"; - pucch_deltaF_Format2b = "deltaF0"; + pusch_p0_Nominal = -96; + pusch_alpha = "AL1"; + pucch_p0_Nominal = -96; + 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_numberOfRA_Preambles = 64; + rach_preamblesGroupAConfig = "DISABLE"; /* - rach_sizeOfRA_PreamblesGroupA = ; - rach_messageSizeGroupA = ; - rach_messagePowerOffsetGroupB = ; + 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; + 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; + 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"; @@ -120,25 +116,25 @@ eNBs = 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_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"; + 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_numRetx = 1; discRxPool_numRepetition = 2; - discRxPool_ResourceConfig_prb_Num = 5; + 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_offsetIndicator_choice = 0; discRxPool_ResourceConfig_subframeBitmap_present = "prBs40"; discRxPool_ResourceConfig_subframeBitmap_choice_bs_buf = "f0ffffffff"; discRxPool_ResourceConfig_subframeBitmap_choice_bs_size = 5; @@ -190,7 +186,7 @@ eNBs = ); ///X2 - enable_x2 = "yes"; + enable_x2 = "yes"; t_reloc_prep = 1000; /* unit: millisecond */ tx2_reloc_overall = 2000; /* unit: millisecond */ t_dc_prep = 1000; /* unit: millisecond */ @@ -198,39 +194,19 @@ eNBs = NETWORK_INTERFACES : { - ENB_INTERFACE_NAME_FOR_S1_MME = "eth1"; + ENB_INTERFACE_NAME_FOR_S1_MME = "eth0"; ENB_IPV4_ADDRESS_FOR_S1_MME = "CI_ENB_IP_ADDR"; - - ENB_INTERFACE_NAME_FOR_S1U = "eth1"; + ENB_INTERFACE_NAME_FOR_S1U = "eth0"; ENB_IPV4_ADDRESS_FOR_S1U = "CI_ENB_IP_ADDR"; ENB_PORT_FOR_S1U = 2152; # Spec 2152 - ENB_IPV4_ADDRESS_FOR_X2C = "CI_ENB_IP_ADDR"; ENB_PORT_FOR_X2C = 36422; # Spec 36422 }; - - log_config : - { - global_log_level ="info"; - global_log_verbosity ="high"; - hw_log_level ="info"; - hw_log_verbosity ="medium"; - phy_log_level ="info"; - phy_log_verbosity ="medium"; - mac_log_level ="info"; - mac_log_verbosity ="high"; - rlc_log_level ="debug"; - rlc_log_verbosity ="high"; - pdcp_log_level ="info"; - pdcp_log_verbosity ="high"; - rrc_log_level ="info"; - rrc_log_verbosity ="medium"; - }; - } ); -MACRLCs = ( +MACRLCs = +( { num_cc = 1; tr_s_preference = "local_L1"; @@ -238,37 +214,52 @@ MACRLCs = ( phy_test_mode = 0; puSch10xSnr = 160; puCch10xSnr = 160; - } -); - -THREAD_STRUCT = ( - { - parallel_config = "PARALLEL_RU_L1_TRX_SPLIT"; - worker_config = "WORKER_ENABLE"; } ); -L1s = ( +L1s = +( { - num_cc = 1; + num_cc = 1; tr_n_preference = "local_mac"; - } + } ); -RUs = ( - { - local_rf = "yes" - nb_tx = 1 - nb_rx = 1 - att_tx = 3 - att_rx = 0; - bands = [7]; +RUs = +( + { + local_rf = "yes" + nb_tx = 1 + nb_rx = 1 + att_tx = 3 + att_rx = 0; + bands = [7]; max_pdschReferenceSignalPower = -27; max_rxgain = 115; - eNB_instances = [0]; -# clock_src = "external"; + eNB_instances = [0]; +# clock_src = "external"; } -); +); + +THREAD_STRUCT = +( + { + #three config for level of parallelism "PARALLEL_SINGLE_THREAD", "PARALLEL_RU_L1_SPLIT", or "PARALLEL_RU_L1_TRX_SPLIT" + parallel_config = "PARALLEL_RU_L1_TRX_SPLIT"; + #two option for worker "WORKER_DISABLE" or "WORKER_ENABLE" + worker_config = "WORKER_ENABLE"; + } +); + +NETWORK_CONTROLLER : +{ + FLEXRAN_ENABLED = "no"; + FLEXRAN_INTERFACE_NAME = "eth0"; + FLEXRAN_IPV4_ADDRESS = "CI_FLEXRAN_CTL_IP_ADDR"; + FLEXRAN_PORT = 2210; + FLEXRAN_CACHE = "/mnt/oai_agent_cache"; + FLEXRAN_AWAIT_RECONF = "no"; +}; log_config : { @@ -286,4 +277,5 @@ log_config : pdcp_log_verbosity ="high"; rrc_log_level ="info"; rrc_log_verbosity ="medium"; - }; +}; + diff --git a/ci-scripts/conf_files/gnb.band78.tm1.fr1.106PRB.usrpb210.conf b/ci-scripts/conf_files/gnb.band78.tm1.fr1.106PRB.usrpb210.conf index 7a8e694a63..33855f2c0e 100644 --- a/ci-scripts/conf_files/gnb.band78.tm1.fr1.106PRB.usrpb210.conf +++ b/ci-scripts/conf_files/gnb.band78.tm1.fr1.106PRB.usrpb210.conf @@ -8,7 +8,6 @@ gNBs = { ////////// Identification parameters: gNB_ID = 0xe00; - cell_type = "CELL_MACRO_GNB"; gNB_name = "gNB-Eurecom-5GNRBox"; @@ -185,102 +184,101 @@ gNBs = ////////// MME parameters: - mme_ip_address = ( { ipv4 = "CI_MME_IP_ADDR"; - ipv6 = "192:168:30::17"; - port = 36412 ; - active = "yes"; - preference = "ipv4"; - } - ); +# mme_ip_address = ( { ipv4 = "CI_MME_IP_ADDR"; +# ipv6 = "192:168:30::17"; +# port = 36412 ; +# active = "yes"; +# preference = "ipv4"; +# } +# ); ///X2 - enable_x2 = "yes"; + enable_x2 = "yes"; t_reloc_prep = 1000; /* unit: millisecond */ tx2_reloc_overall = 2000; /* unit: millisecond */ t_dc_prep = 1000; /* unit: millisecond */ t_dc_overall = 2000; /* unit: millisecond */ - target_enb_x2_ip_address = ( - { ipv4 = "CI_FR1_CTL_ENB_IP_ADDR"; - ipv6 = "192:168:30::17"; - preference = "ipv4"; - } - ); + + target_enb_x2_ip_address = ( { ipv4 = "CI_FR1_CTL_ENB_IP_ADDR"; + ipv6 = "192:168:30::17"; + preference = "ipv4"; + } + ); NETWORK_INTERFACES : { - - GNB_INTERFACE_NAME_FOR_S1_MME = "eth0"; - GNB_IPV4_ADDRESS_FOR_S1_MME = "CI_GNB_IP_ADDR"; - GNB_INTERFACE_NAME_FOR_S1U = "eth0"; - GNB_IPV4_ADDRESS_FOR_S1U = "CI_GNB_IP_ADDR"; - GNB_PORT_FOR_S1U = 2152; # Spec 2152 - GNB_IPV4_ADDRESS_FOR_X2C = "CI_GNB_IP_ADDR"; - GNB_PORT_FOR_X2C = 36422; # Spec 36422 + GNB_INTERFACE_NAME_FOR_S1_MME = "eth0"; + GNB_IPV4_ADDRESS_FOR_S1_MME = "CI_GNB_IP_ADDR"; + GNB_INTERFACE_NAME_FOR_S1U = "eth0"; + GNB_IPV4_ADDRESS_FOR_S1U = "CI_GNB_IP_ADDR"; + GNB_PORT_FOR_S1U = 2152; # Spec 2152 + GNB_IPV4_ADDRESS_FOR_X2C = "CI_GNB_IP_ADDR"; + GNB_PORT_FOR_X2C = 36422; # Spec 36422 }; + } ); MACRLCs = ( - { - num_cc = 1; - tr_s_preference = "local_L1"; - tr_n_preference = "local_RRC"; - pusch_TargetSNRx10 = 200; - pucch_TargetSNRx10 = 200; - } + { + num_cc = 1; + tr_s_preference = "local_L1"; + tr_n_preference = "local_RRC"; + pusch_TargetSNRx10 = 200; + pucch_TargetSNRx10 = 200; + } ); L1s = ( - { - num_cc = 1; - tr_n_preference = "local_mac"; - pusch_proc_threads = 6; - } + { + num_cc = 1; + tr_n_preference = "local_mac"; + pusch_proc_threads = 6; + } ); RUs = ( - { - local_rf = "yes" - nb_tx = 1 - nb_rx = 1 - att_tx = 3 - att_rx = 0; - bands = [7]; - max_pdschReferenceSignalPower = -27; - max_rxgain = 111; - eNB_instances = [0]; -# clock_src = "external"; - } + { + local_rf = "yes" + nb_tx = 1 + nb_rx = 1 + att_tx = 3 + att_rx = 0; + bands = [7]; + max_pdschReferenceSignalPower = -27; + max_rxgain = 111; + eNB_instances = [0]; +# clock_src = "external"; + } ); THREAD_STRUCT = ( { #three config for level of parallelism "PARALLEL_SINGLE_THREAD", "PARALLEL_RU_L1_SPLIT", or "PARALLEL_RU_L1_TRX_SPLIT" parallel_config = "PARALLEL_RU_L1_TRX_SPLIT"; - //parallel_config = "PARALLEL_SINGLE_THREAD"; #two option for worker "WORKER_DISABLE" or "WORKER_ENABLE" worker_config = "WORKER_ENABLE"; } ); - log_config : - { - global_log_level ="info"; - global_log_verbosity ="medium"; - hw_log_level ="info"; - hw_log_verbosity ="medium"; - phy_log_level ="info"; - phy_log_verbosity ="medium"; - mac_log_level ="info"; - mac_log_verbosity ="high"; - rlc_log_level ="info"; - rlc_log_verbosity ="medium"; - pdcp_log_level ="info"; - pdcp_log_verbosity ="medium"; - rrc_log_level ="info"; - rrc_log_verbosity ="medium"; - }; +log_config : +{ + global_log_level ="info"; + global_log_verbosity ="medium"; + hw_log_level ="info"; + hw_log_verbosity ="medium"; + phy_log_level ="info"; + phy_log_verbosity ="medium"; + mac_log_level ="info"; + mac_log_verbosity ="high"; + rlc_log_level ="info"; + rlc_log_verbosity ="medium"; + pdcp_log_level ="info"; + pdcp_log_verbosity ="medium"; + rrc_log_level ="info"; + rrc_log_verbosity ="medium"; +}; uicc: { -opc = "testopc"; + opc = "testopc"; }; diff --git a/docker/Dockerfile.gNB.rhel8.2 b/docker/Dockerfile.gNB.rhel8.2 index 6969c691fd..248b154693 100644 --- a/docker/Dockerfile.gNB.rhel8.2 +++ b/docker/Dockerfile.gNB.rhel8.2 @@ -25,7 +25,7 @@ # #--------------------------------------------------------------------- -FROM localhost/ran-build:latest AS gnb-build +FROM ran-build:latest AS gnb-build RUN rm -Rf /oai-ran WORKDIR /oai-ran @@ -37,11 +37,9 @@ RUN /bin/sh oaienv && \ mkdir -p log && \ ./build_oai --gNB --ninja -w USRP --verbose-ci -#debug -#RUN ldconfig -v -#RUN ldd /oai-ran/targets/bin/nr-softmodem.Rel15 -#RUN ls -lst /oai-ran/targets/bin -#RUN ls -lst /oai-ran/cmake_targets/ran_build/build/*.so +RUN yum install -y python3-pip && \ + pip3 install --ignore-installed pyyaml && \ + python3 ./docker/scripts/generateTemplate.py ./docker/scripts/gnb_parameters.yaml #start from scratch for target executable FROM registry.access.redhat.com/ubi8/ubi:latest as oai-gnb @@ -62,6 +60,7 @@ RUN yum repolist --disablerepo=* && \ WORKDIR /opt/oai-gnb/bin COPY --from=gnb-build /oai-ran/targets/bin/nr-softmodem.Rel15 . +COPY --from=gnb-build /oai-ran/docker/scripts/gnb_entrypoint.sh entrypoint.sh WORKDIR /usr/local/lib/ COPY --from=gnb-build /oai-ran/targets/bin/liboai_eth_transpro.so.Rel15 . @@ -99,23 +98,10 @@ COPY --from=gnb-build /lib64/libboost_timer.so.1.66.0 /lib64 COPY --from=gnb-build /usr/local/lib64/libuhd.so.4.0.0 /usr/local/lib64 RUN ldconfig -#debug -#RUN ldd /opt/oai-gnb/bin/nr-softmodem.Rel15 -#RUN ldd /usr/local/lib/liboai_eth_transpro.so.Rel15 -#RUN ldd /usr/local/lib/libtcp_bridge_oai.so.Rel15 -#RUN ldd /usr/local/lib/librfsimulator.so.Rel15 -#RUN ldd /usr/local/lib/liboai_usrpdevif.so.Rel15 -#RUN ldd /usr/local/lib/libcoding.so -#RUN ldd /usr/local/lib/libparams_libconfig.so -#RUN ldd /usr/local/lib/libdfts.so -#RUN ldd /usr/local/lib/libldpc.so -#RUN ldd /usr/local/lib/libldpc_optim.so -#RUN ldd /usr/local/lib/libldpc_optim8seg.so -#RUN ldd /usr/local/lib/libldpc_orig.so # Copy the relevant configuration files for gNB WORKDIR /opt/oai-gnb/etc -COPY --from=gnb-build /oai-ran/ci-scripts/conf_files/gnb.* . +COPY --from=gnb-build /oai-ran/docker/etc . WORKDIR /opt/oai-gnb #EXPOSE 2152/udp # S1U, GTP/UDP @@ -125,6 +111,5 @@ WORKDIR /opt/oai-gnb #EXPOSE 50000/udp # IF5 / ORI (control) #EXPOSE 50001/udp # IF5 / ECPRI (data) -#CMD ["/opt/oai-gnb/bin/nr-softmodem", "-O", "/opt/oai-gnb/etc/gnb.conf"] -#ENTRYPOINT ["/opt/oai-gnb/bin/entrypoint.sh"] -CMD ["sleep", "infinity"] +ENTRYPOINT ["/opt/oai-gnb/bin/entrypoint.sh"] +CMD ["/opt/oai-gnb/bin/nr-softmodem", "-O", "/opt/oai-gnb/etc/gnb.conf"] diff --git a/docker/Dockerfile.gNB.ubuntu18 b/docker/Dockerfile.gNB.ubuntu18 index 276d6989c4..3660baf79e 100644 --- a/docker/Dockerfile.gNB.ubuntu18 +++ b/docker/Dockerfile.gNB.ubuntu18 @@ -37,23 +37,21 @@ RUN /bin/sh oaienv && \ mkdir -p log && \ ./build_oai --gNB --ninja -w USRP --verbose-ci -#debug -RUN ldconfig -v -RUN ldd /oai-ran/targets/bin/nr-softmodem.Rel15 -RUN ls -lst /oai-ran/targets/bin -RUN ls -lst /oai-ran/cmake_targets/ran_build/build/*.so +RUN apt-get install -y python3-pip && \ + pip3 install --ignore-installed pyyaml && \ + python3 ./docker/scripts/generateTemplate.py ./docker/scripts/gnb_parameters.yaml #start from scratch for target executable FROM ubuntu:bionic as oai-gnb ENV DEBIAN_FRONTEND=noninteractive ENV TZ=Europe -RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone RUN apt-get update && \ DEBIAN_FRONTEND=noninteractive apt-get upgrade --yes && \ DEBIAN_FRONTEND=noninteractive apt-get install --yes \ software-properties-common \ libsctp1 \ + tzdata \ libnettle6 \ libblas3 \ libatlas3-base \ @@ -76,6 +74,7 @@ RUN apt-get update && \ WORKDIR /opt/oai-gnb/bin COPY --from=gnb-build /oai-ran/targets/bin/nr-softmodem.Rel15 . +COPY --from=gnb-build /oai-ran/docker/scripts/gnb_entrypoint.sh entrypoint.sh WORKDIR /usr/local/lib/ COPY --from=gnb-build /oai-ran/targets/bin/liboai_eth_transpro.so.Rel15 . @@ -96,23 +95,10 @@ RUN /bin/bash -c "ln -s /usr/local/lib/librfsimulator.so.Rel15 /usr/local/lib/li COPY --from=gnb-build /usr/local/lib/libprotobuf-c.so.1 . RUN ldconfig -#debug -#RUN ldd /opt/oai-gnb/bin/nr-softmodem.Rel15 -#RUN ldd /usr/local/lib/liboai_eth_transpro.so.Rel15 -#RUN ldd /usr/local/lib/libtcp_bridge_oai.so.Rel15 -#RUN ldd /usr/local/lib/librfsimulator.so.Rel15 -#RUN ldd /usr/local/lib/liboai_usrpdevif.so.Rel15 -#RUN ldd /usr/local/lib/libcoding.so -#RUN ldd /usr/local/lib/libparams_libconfig.so -#RUN ldd /usr/local/lib/libdfts.so -#RUN ldd /usr/local/lib/libldpc.so -#RUN ldd /usr/local/lib/libldpc_optim.so -#RUN ldd /usr/local/lib/libldpc_optim8seg.so -#RUN ldd /usr/local/lib/libldpc_orig.so # Copy the relevant configuration files for gNB WORKDIR /opt/oai-gnb/etc -COPY --from=gnb-build /oai-ran/ci-scripts/conf_files/gnb.* ./ +COPY --from=gnb-build /oai-ran/docker/etc . WORKDIR /opt/oai-gnb #EXPOSE 2152/udp # S1U, GTP/UDP @@ -122,6 +108,5 @@ WORKDIR /opt/oai-gnb #EXPOSE 50000/udp # IF5 / ORI (control) #EXPOSE 50001/udp # IF5 / ECPRI (data) -#CMD ["/opt/oai-gnb/bin/nr-softmodem", "-O", "/opt/oai-gnb/etc/gnb.conf"] -#ENTRYPOINT ["/opt/oai-gnb/bin/entrypoint.sh"] -CMD ["sleep", "infinity"] +ENTRYPOINT ["/opt/oai-gnb/bin/entrypoint.sh"] +CMD ["/opt/oai-gnb/bin/nr-softmodem", "-O", "/opt/oai-gnb/etc/gnb.conf"] diff --git a/docker/Dockerfile.nrUE.rhel8.2 b/docker/Dockerfile.nrUE.rhel8.2 index 01988fd6ff..b71d0ed906 100644 --- a/docker/Dockerfile.nrUE.rhel8.2 +++ b/docker/Dockerfile.nrUE.rhel8.2 @@ -25,7 +25,7 @@ # #--------------------------------------------------------------------- -FROM localhost/ran-build:latest AS nr-ue-build +FROM ran-build:latest AS nr-ue-build RUN rm -Rf /oai-ran WORKDIR /oai-ran diff --git a/docker/Dockerfile.phySim.rhel8.2 b/docker/Dockerfile.phySim.rhel8.2 index 4472ece363..2333098bd7 100644 --- a/docker/Dockerfile.phySim.rhel8.2 +++ b/docker/Dockerfile.phySim.rhel8.2 @@ -25,7 +25,7 @@ # #--------------------------------------------------------------------- -FROM localhost/ran-build:develop AS phy-sim-build +FROM ran-build:develop AS phy-sim-build RUN rm -Rf /oai-ran WORKDIR /oai-ran diff --git a/docker/Dockerfile.ran.rhel8.2 b/docker/Dockerfile.ran.rhel8.2 index 2e4bd586bf..cc9a1972a1 100644 --- a/docker/Dockerfile.ran.rhel8.2 +++ b/docker/Dockerfile.ran.rhel8.2 @@ -44,8 +44,11 @@ RUN rm -f /etc/rhsm-host && \ file \ psmisc \ git \ + # python3-pip and pyyaml are used for conf template generation + python3-pip #unzip is needed for protobuf unzip && \ + pip3 install --ignore-installed pyyaml && \ echo "/usr/local/lib" > /etc/ld.so.conf.d/local-lib.conf && \ echo "/usr/local/lib64" >> /etc/ld.so.conf.d/local-lib.conf diff --git a/docker/Dockerfile.ran.ubuntu18 b/docker/Dockerfile.ran.ubuntu18 index 730366da74..4b296408fd 100644 --- a/docker/Dockerfile.ran.ubuntu18 +++ b/docker/Dockerfile.ran.ubuntu18 @@ -42,7 +42,10 @@ RUN apt-get update && \ git \ xxd \ #unzip is needed for protobuf - unzip + unzip \ + # python3-pip for conf template generation + python3-pip && \ + pip3 install --ignore-installed pyyaml # 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" @@ -56,4 +59,3 @@ RUN /bin/sh oaienv && \ cd cmake_targets && \ mkdir -p log && \ ./build_oai -I -w USRP - diff --git a/docker/scripts/enb_entrypoint.sh b/docker/scripts/enb_entrypoint.sh index 6810a86416..4ac86ef1b7 100755 --- a/docker/scripts/enb_entrypoint.sh +++ b/docker/scripts/enb_entrypoint.sh @@ -4,6 +4,8 @@ set -euo pipefail PREFIX=/opt/oai-enb RRC_INACTIVITY_THRESHOLD=${RRC_INACTIVITY_THRESHOLD:-0} +ENABLE_MEASUREMENT_REPORTS=${ENABLE_MEASUREMENT_REPORTS:-no} +ENABLE_X2=${ENABLE_X2:-no} # Based another env var, pick one template to use if [[ -v USE_FDD_CU ]]; then ln -s $PREFIX/etc/cu.fdd.conf $PREFIX/etc/enb.conf; fi diff --git a/docker/scripts/enb_parameters.yaml b/docker/scripts/enb_parameters.yaml index 749600f47d..58715a7152 100644 --- a/docker/scripts/enb_parameters.yaml +++ b/docker/scripts/enb_parameters.yaml @@ -123,7 +123,7 @@ - key: bands env: "@UTRA_BAND_ID@" - - filePrefix: enb.band7.tm1.25PRB.usrpb210 + - filePrefix: enb.band7.tm1.fr1.25PRB.usrpb210.conf outputfilename: "enb.fdd.conf" config: - key: Active_eNBs @@ -147,6 +147,10 @@ env: "@NID_CELL@" - key: N_RB_DL env: "@NB_PRB@" + - key: enable_measurement_reports + env: "@ENABLE_MEASUREMENT_REPORTS@" + - key: enable_x2 + env: "@ENABLE_X2@" - key: ipv4 env: "@MME_S1C_IP_ADDRESS@" - key: ENB_INTERFACE_NAME_FOR_S1_MME diff --git a/docker/scripts/generateTemplate.py b/docker/scripts/generateTemplate.py index 5ce0d146e5..9c45d5d43c 100644 --- a/docker/scripts/generateTemplate.py +++ b/docker/scripts/generateTemplate.py @@ -48,18 +48,19 @@ def main(): "du.band7.tm1.25PRB": f'{data[0]["paths"]["dest_dir"]}/{outputfilename}', "rru.fdd": f'{data[0]["paths"]["dest_dir"]}/{outputfilename}', "rru.tdd": f'{data[0]["paths"]["dest_dir"]}/{outputfilename}', - "enb.band7.tm1.25PRB.usrpb210": f'{data[0]["paths"]["dest_dir"]}/{outputfilename}', + "enb.band7.tm1.fr1.25PRB.usrpb210.conf": f'{data[0]["paths"]["dest_dir"]}/{outputfilename}', "enb.band40.tm1.25PRB.FairScheduler.usrpb210": f'{data[0]["paths"]["dest_dir"]}/{outputfilename}', "rcc.band7.tm1.nfapi": f'{data[0]["paths"]["dest_dir"]}/{outputfilename}', "rcc.band7.tm1.if4p5.lo.25PRB": f'{data[0]["paths"]["dest_dir"]}/{outputfilename}', "rcc.band40.tm1.25PRB": f'{data[0]["paths"]["dest_dir"]}/{outputfilename}', + "gnb.band78.tm1.fr1.106PRB.usrpb210.conf": f'{data[0]["paths"]["dest_dir"]}/{outputfilename}', "ue.nfapi": f'{data[0]["paths"]["dest_dir"]}/{outputfilename}', "ue_sim_ci": f'{data[0]["paths"]["dest_dir"]}/{outputfilename}' } print('inputfile = ' + inputfile) if filePrefix in prefix_outputfile: outputfile1 = prefix_outputfile[filePrefix] - + directory = f'{data[0]["paths"]["dest_dir"]}' if not os.path.exists(directory): os.makedirs(directory, exist_ok=True) diff --git a/docker/scripts/gnb_entrypoint.sh b/docker/scripts/gnb_entrypoint.sh new file mode 100755 index 0000000000..09af2753bc --- /dev/null +++ b/docker/scripts/gnb_entrypoint.sh @@ -0,0 +1,62 @@ +#!/bin/bash + +set -euo pipefail + +PREFIX=/opt/oai-gnb +ENABLE_X2=${ENABLE_X2:-yes} + +# Based another env var, pick one template to use +if [[ -v USE_TDD_MONO ]]; then ln -s $PREFIX/etc/gnb.tdd.conf $PREFIX/etc/gnb.conf; fi + +# Only this template will be manipulated +CONFIG_FILES=`ls $PREFIX/etc/gnb.conf || true` + +for c in ${CONFIG_FILES}; do + # grep variable names (format: ${VAR}) from template to be rendered + VARS=$(grep -oP '@[a-zA-Z0-9_]+@' ${c} | sort | uniq | xargs) + + # create sed expressions for substituting each occurrence of ${VAR} + # with the value of the environment variable "VAR" + EXPRESSIONS="" + for v in ${VARS}; do + NEW_VAR=`echo $v | sed -e "s#@##g"` + if [[ "${!NEW_VAR}x" == "x" ]]; then + echo "Error: Environment variable '${NEW_VAR}' is not set." \ + "Config file '$(basename $c)' requires all of $VARS." + exit 1 + fi + EXPRESSIONS="${EXPRESSIONS};s|${v}|${!NEW_VAR}|g" + done + EXPRESSIONS="${EXPRESSIONS#';'}" + + # render template and inline replace config file + sed -i "${EXPRESSIONS}" ${c} +done + +# Load the USRP binaries +if [[ -v USE_B2XX ]]; then + /usr/lib/uhd/utils/uhd_images_downloader.py -t b2xx +elif [[ -v USE_X3XX ]]; then + /usr/lib/uhd/utils/uhd_images_downloader.py -t x3xx +elif [[ -v USE_N3XX ]]; then + /usr/lib/uhd/utils/uhd_images_downloader.py -t n3xx +fi + +echo "==================================" +echo "== Starting gNB soft modem" +if [[ -v USE_ADDITIONAL_OPTIONS ]]; then + echo "Additional option(s): ${USE_ADDITIONAL_OPTIONS}" + new_args=() + while [[ $# -gt 0 ]]; do + new_args+=("$1") + shift + done + for word in ${USE_ADDITIONAL_OPTIONS}; do + new_args+=("$word") + done + echo "${new_args[@]}" + exec "${new_args[@]}" +else + echo "$@" + exec "$@" +fi diff --git a/docker/scripts/gnb_parameters.yaml b/docker/scripts/gnb_parameters.yaml new file mode 100644 index 0000000000..1992aecff5 --- /dev/null +++ b/docker/scripts/gnb_parameters.yaml @@ -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 +# */ + +--- +- paths: + source_dir: "ci-scripts/conf_files/" + dest_dir: docker/etc + +- configurations: + - filePrefix: gnb.band78.tm1.fr1.106PRB.usrpb210.conf + outputfilename: "gnb.tdd.conf" + config: + - key: Active_gNBs + env: "@GNB_NAME@" + - key: gNB_name + env: "@GNB_NAME@" + - key: plmn_list + env: + mcc: "@MCC@" + mnc: "@MNC@" + mnc_length: "@MNC_LENGTH@" + - key: tracking_area_code + env: "@TAC@" + - key: enable_x2 + env: "@ENABLE_X2@" + - key: ipv4 + env: "@ENB_X2_IP_ADDRESS@" + - key: GNB_INTERFACE_NAME_FOR_S1_MME + env: "@GNB_S1C_IF_NAME@" + - key: GNB_IPV4_ADDRESS_FOR_S1_MME + env: "@GNB_S1C_IP_ADDRESS@" + - key: GNB_INTERFACE_NAME_FOR_S1U + env: "@GNB_S1U_IF_NAME@" + - key: GNB_IPV4_ADDRESS_FOR_S1U + env: "@GNB_S1U_IP_ADDRESS@" + - key: GNB_IPV4_ADDRESS_FOR_X2C + env: "@GNB_X2_IP_ADDRESS@" + - key: rrc_inactivity_threshold + env: "@RRC_INACTIVITY_THRESHOLD@" + - key: FLEXRAN_ENABLED + env: "@FLEXRAN_ENABLED@" + - key: FLEXRAN_INTERFACE_NAME + env: "@FLEXRAN_INTERFACE_NAME@" + - key: FLEXRAN_IPV4_ADDRESS + env: "@FLEXRAN_IPV4_ADDRESS@" + From 85b8f78d71cb6a5b9897a3952291fba88022afbd Mon Sep 17 00:00:00 2001 From: Gokul Srinivasan Date: Tue, 3 Aug 2021 17:57:11 +0530 Subject: [PATCH 70/91] process ID overflow bugfix --- executables/nr-gnb.c | 2 +- nfapi/oai_integration/nfapi_pnf.c | 4 +- nfapi/oai_integration/nfapi_vnf.c | 4 +- nfapi/open-nFAPI/pnf/src/pnf_p7.c | 256 ++++++--------- nfapi/open-nFAPI/vnf/src/vnf_p7.c | 12 +- nfapi/open-nFAPI/vnf/src/vnf_p7_interface.c | 296 ++++-------------- .../PHY/LTE_UE_TRANSPORT/dlsch_decoding.c | 10 +- openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c | 4 +- .../LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c | 11 +- openair2/NR_PHY_INTERFACE/NR_IF_Module.c | 5 +- 10 files changed, 171 insertions(+), 433 deletions(-) diff --git a/executables/nr-gnb.c b/executables/nr-gnb.c index 166ebd69b6..beda127cfd 100644 --- a/executables/nr-gnb.c +++ b/executables/nr-gnb.c @@ -151,7 +151,7 @@ void rx_func(void *param) { // I am a PNF and I need to let nFAPI know that we have a (sub)frame tick //LOG_D(PHY, "oai_slot_ind(frame:%u, slot:%d) ********\n", frame_rx, slot_rx); start_meas(&nfapi_meas); - oai_slot_ind(frame_tx, slot_tx); + oai_slot_ind(frame_rx, slot_rx); stop_meas(&nfapi_meas); /*if (gNB->UL_INFO.rx_ind.rx_indication_body.number_of_pdus|| diff --git a/nfapi/oai_integration/nfapi_pnf.c b/nfapi/oai_integration/nfapi_pnf.c index 0783aa26b3..da8912e6a9 100644 --- a/nfapi/oai_integration/nfapi_pnf.c +++ b/nfapi/oai_integration/nfapi_pnf.c @@ -1253,8 +1253,8 @@ int pnf_phy_dl_tti_req(gNB_L1_rxtx_proc_t *proc, nfapi_pnf_p7_config_t *pnf_p7, } else if (dl_tti_pdu_list[i].PDUType == NFAPI_NR_DL_TTI_PDSCH_PDU_TYPE) { nfapi_nr_dl_tti_pdsch_pdu *pdsch_pdu = &dl_tti_pdu_list[i].pdsch_pdu; nfapi_nr_dl_tti_pdsch_pdu_rel15_t *rel15_pdu = &pdsch_pdu->pdsch_pdu_rel15; - //nfapi_nr_tx_data_request_t *tx_data = tx_data_request[sfn][slot][rel15_pdu->pduIndex]; - nfapi_nr_pdu_t *tx_data = tx_data_request[sfn][slot][0]; + //nfapi_nr_tx_data_request_t *tx_data = tx_data_request[sfn][slot][rel15_pdu->pduIndex]; + nfapi_nr_pdu_t *tx_data = tx_data_request[sfn][slot][rel15_pdu->pduIndex]; if (tx_data != NULL) { int UE_id = find_nr_dlsch(rel15_pdu->rnti,gNB,SEARCH_EXIST_OR_FREE); diff --git a/nfapi/oai_integration/nfapi_vnf.c b/nfapi/oai_integration/nfapi_vnf.c index e86c932483..1bc2f70d93 100644 --- a/nfapi/oai_integration/nfapi_vnf.c +++ b/nfapi/oai_integration/nfapi_vnf.c @@ -1620,8 +1620,8 @@ void configure_nr_nfapi_vnf(char *vnf_addr, int vnf_p5_port) { nfapi_setmode(NFAPI_MODE_VNF); memset(&vnf, 0, sizeof(vnf)); memset(vnf.p7_vnfs, 0, sizeof(vnf.p7_vnfs)); - vnf.p7_vnfs[0].timing_window = 32; - vnf.p7_vnfs[0].periodic_timing_enabled = 1; + vnf.p7_vnfs[0].timing_window = 30; + vnf.p7_vnfs[0].periodic_timing_enabled = 0; vnf.p7_vnfs[0].aperiodic_timing_enabled = 0; vnf.p7_vnfs[0].periodic_timing_period = 10; vnf.p7_vnfs[0].config = nfapi_vnf_p7_config_create(); diff --git a/nfapi/open-nFAPI/pnf/src/pnf_p7.c b/nfapi/open-nFAPI/pnf/src/pnf_p7.c index 8786e9e53c..0b75d3c7ec 100644 --- a/nfapi/open-nFAPI/pnf/src/pnf_p7.c +++ b/nfapi/open-nFAPI/pnf/src/pnf_p7.c @@ -156,17 +156,16 @@ nfapi_dl_config_request_t* allocate_nfapi_dl_config_request(pnf_p7_t* pnf_p7) void deallocate_nfapi_dl_tti_request(nfapi_nr_dl_tti_request_t* req, pnf_p7_t* pnf_p7) { //printf("%s() SFN/SF:%d %s req:%p pdu_list:%p\n", __FUNCTION__, NFAPI_SFNSF2DEC(req->sfn_sf), pnf_p7->_public.codec_config.deallocate ? "DEALLOCATE" : "FREE", req, req->dl_config_request_body.dl_config_pdu_list); - /* - if(pnf_p7->_public.codec_config.deallocate) - { - //nfapi_nr_dl_tti_request_pdu_t *temp = &req->dl_tti_pdu_list; - (pnf_p7->_public.codec_config.deallocate)(req); - } - else - { - free(req); - } -*/ + + // if(pnf_p7->_public.codec_config.deallocate) + // { + // (pnf_p7->_public.codec_config.deallocate)(req); + // } + // else + // { + // free(req); + // } + pnf_p7_free(pnf_p7, req); } @@ -915,14 +914,13 @@ void send_dummy_subframe(pnf_p7_t* pnf_p7, uint16_t sfn_sf) int pnf_p7_slot_ind(pnf_p7_t* pnf_p7, uint16_t phy_id, uint16_t sfn, uint16_t slot) -{ +{ + //This function is aligned with rx sfn/slot + // We could either send an event to the p7 thread have have it run the // subframe or we could handle it here and lock access to the subframe // buffers. If we do it on the p7 thread then we run the risk of blocking // on the udp send. - // - // todo : start a timer to give us more of the 1 ms tick before send back - // the frame // todo : consider a more efficent lock mechasium //uint16_t NUM_SLOTS = 20;//10* 2^mu @@ -935,21 +933,21 @@ int pnf_p7_slot_ind(pnf_p7_t* pnf_p7, uint16_t phy_id, uint16_t sfn, uint16_t sl // save the curren time, sfn and slot pnf_p7->slot_start_time_hr = pnf_get_current_time_hr(); - pnf_p7->sfn = sfn; - - pnf_p7->slot = slot; - - - + slot_ahead = 6; uint32_t sfn_slot_tx = sfnslot_add_slot(sfn, slot, slot_ahead); - uint16_t sfn_tx = sfn_slot_tx>>6; - uint16_t slot_tx = sfn_slot_tx & 0X3F; + uint16_t sfn_tx = NFAPI_SFNSLOT2SFN(sfn_slot_tx); + uint8_t slot_tx = NFAPI_SFNSLOT2SLOT(sfn_slot_tx); - // uint32_t tx_sfn_slot_dec = NFAPI_SFNSLOT2DEC(sfn,slot); - uint32_t tx_slot_dec = NFAPI_SFNSLOT2DEC(sfn,slot); + //We align the pnf_p7 sfn/slot with tx sfn/slot, and vnf is synced with pnf_p7 sfn/slot. This is so that the scheduler runs slot_ahead from rx thread. + pnf_p7->sfn = sfn_tx; + pnf_p7->slot = slot_tx; - //uint32_t tx_sfn_slot_dec = NFAPI_SFNSLOT2DEC(sfn_slot_tx); + uint32_t slot_dec = NFAPI_SFNSLOT2DEC(sfn, slot); + uint8_t buffer_index_rx = slot_dec % 20; + + uint32_t tx_slot_dec = NFAPI_SFNSLOT2DEC(sfn_tx,slot_tx); + uint8_t buffer_index_tx = tx_slot_dec % 20; // If the subframe_buffer has been configured if(pnf_p7->_public.slot_buffer_size!= 0) // for now value is same as sf_buffer_size @@ -976,28 +974,20 @@ int pnf_p7_slot_ind(pnf_p7_t* pnf_p7, uint16_t phy_id, uint16_t sfn, uint16_t sl pnf_p7->slot_shift = 0; } - uint32_t slot_dec = NFAPI_SFNSLOT2DEC(sfn, slot); - uint8_t buffer_index = slot_dec % pnf_p7->_public.slot_buffer_size; + nfapi_pnf_p7_slot_buffer_t* rx_slot_buffer = &(pnf_p7->slot_buffer[buffer_index_rx]); - nfapi_pnf_p7_slot_buffer_t* slot_buffer = &(pnf_p7->slot_buffer[buffer_index]); - // see where the PNF_P7 slot buffer its getting filled - - uint8_t tx_buffer_index = tx_slot_dec % pnf_p7->_public.slot_buffer_size; - nfapi_pnf_p7_slot_buffer_t* tx_slot_buffer = &(pnf_p7->slot_buffer[tx_buffer_index]); + nfapi_pnf_p7_slot_buffer_t* tx_slot_buffer = &(pnf_p7->slot_buffer[buffer_index_tx]); if (0) NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() shift:%d slot_buffer->sfn_sf:%d tx_slot_buffer->sfn_slot:%d sfn_sf:%d subframe_buffer[buffer_index:%u dl_config_req:%p tx_req:%p] " "TX:sfn_sf:%d:tx_buffer_index:%d[dl_config_req:%p tx_req:%p]\n", __FUNCTION__, pnf_p7->slot_shift, - NFAPI_SFNSLOT2DEC(slot_buffer->sfn, slot_buffer->slot), + NFAPI_SFNSLOT2DEC(rx_slot_buffer->sfn, rx_slot_buffer->slot), NFAPI_SFNSLOT2DEC(tx_slot_buffer->sfn, tx_slot_buffer->slot), - slot_dec, buffer_index, slot_buffer->dl_tti_req, slot_buffer->tx_data_req, - tx_slot_dec, tx_buffer_index, tx_slot_buffer->dl_tti_req, tx_slot_buffer->tx_data_req); + slot_dec, buffer_index_rx, rx_slot_buffer->dl_tti_req, rx_slot_buffer->tx_data_req, + tx_slot_dec, buffer_index_tx, tx_slot_buffer->dl_tti_req, tx_slot_buffer->tx_data_req); //TODO: Change later if required - - // if the subframe buffer sfn sf is set then we have atlease 1 message - // from the vnf. // todo : how to handle the messages we don't have, send dummies for // now @@ -1006,12 +996,15 @@ int pnf_p7_slot_ind(pnf_p7_t* pnf_p7, uint16_t phy_id, uint16_t sfn, uint16_t sl //printf("tx_slot_buff_sfn - %d, tx_slot_buf_slot - %d, sfn_tx = %d, sllot_tx - %d \n",tx_slot_buffer->sfn,tx_slot_buffer->slot,sfn_tx,slot_tx); // if(tx_slot_buffer->slot == slot_tx && tx_slot_buffer->sfn == sfn_tx) // { - - if(tx_slot_buffer->tx_data_req != 0) + + //checking in the tx slot buffers to see if a p7 msg is present. todo: what if it's a mixed slot? + + if(tx_slot_buffer->tx_data_req != 0 && tx_slot_buffer->tx_data_req->SFN == sfn_tx && tx_slot_buffer->tx_data_req->Slot == slot_tx) { if(pnf_p7->_public.tx_data_req_fn) - { + { + //NFAPI_TRACE(NFAPI_TRACE_INFO, "Calling tx_data_req_fn in SFN/slot %d.%d \n",sfn,slot); (pnf_p7->_public.tx_data_req_fn)(&(pnf_p7->_public), tx_slot_buffer->tx_data_req); } } @@ -1027,11 +1020,11 @@ int pnf_p7_slot_ind(pnf_p7_t* pnf_p7, uint16_t phy_id, uint16_t sfn, uint16_t sl } } - - if(tx_slot_buffer->dl_tti_req != 0) + if(tx_slot_buffer->dl_tti_req != 0 && tx_slot_buffer->dl_tti_req->SFN == sfn_tx && tx_slot_buffer->dl_tti_req->Slot == slot_tx) { if(pnf_p7->_public.dl_tti_req_fn) { + LOG_D(PHY, "Process dl_tti SFN/slot %d.%d buffer index: %d \n",sfn_tx,slot_tx,buffer_index_tx); (pnf_p7->_public.dl_tti_req_fn)(NULL, &(pnf_p7->_public), tx_slot_buffer->dl_tti_req); } } @@ -1047,10 +1040,11 @@ int pnf_p7_slot_ind(pnf_p7_t* pnf_p7, uint16_t phy_id, uint16_t sfn, uint16_t sl } - if(tx_slot_buffer->ul_dci_req!= 0) + if(tx_slot_buffer->ul_dci_req!= 0 && tx_slot_buffer->ul_dci_req->SFN == sfn_tx && tx_slot_buffer->ul_dci_req->Slot == slot_tx) { if(pnf_p7->_public.ul_dci_req_fn) { + //NFAPI_TRACE(NFAPI_TRACE_INFO, "Calling UL_dci_req_fn in SFN/slot %d.%d \n",sfn,slot); (pnf_p7->_public.ul_dci_req_fn)(NULL, &(pnf_p7->_public), tx_slot_buffer->ul_dci_req); } } @@ -1064,27 +1058,14 @@ int pnf_p7_slot_ind(pnf_p7_t* pnf_p7, uint16_t phy_id, uint16_t sfn, uint16_t sl (pnf_p7->_public.ul_dci_req_fn)(NULL, &(pnf_p7->_public), pnf_p7->_public.dummy_slot.ul_dci_req); } } - if(tx_slot_buffer->ul_tti_req != 0) - { - if(pnf_p7->_public.ul_tti_req_fn) - { - (pnf_p7->_public.ul_tti_req_fn)(NULL, &(pnf_p7->_public), tx_slot_buffer->ul_tti_req); - } - } - else - { - // send dummy - if(pnf_p7->_public.ul_tti_req_fn && pnf_p7->_public.dummy_slot.ul_tti_req) - { - pnf_p7->_public.dummy_slot.ul_tti_req->SFN = sfn_tx; - pnf_p7->_public.dummy_slot.ul_tti_req->Slot = slot_tx; - (pnf_p7->_public.ul_tti_req_fn)(NULL, &(pnf_p7->_public), pnf_p7->_public.dummy_slot.ul_tti_req); - } - } + + //deallocate slot buffers after passing down the PDUs to PHY processing + if(tx_slot_buffer->dl_tti_req != 0) { deallocate_nfapi_dl_tti_request(tx_slot_buffer->dl_tti_req, pnf_p7); tx_slot_buffer->dl_tti_req = 0; + LOG_D(PHY,"SFN/slot %d.%d Buffer index : %d freed \n",sfn_tx,slot_tx,buffer_index_tx); } if(tx_slot_buffer->tx_data_req != 0) @@ -1098,72 +1079,51 @@ int pnf_p7_slot_ind(pnf_p7_t* pnf_p7, uint16_t phy_id, uint16_t sfn, uint16_t sl deallocate_nfapi_ul_dci_request(tx_slot_buffer->ul_dci_req, pnf_p7); tx_slot_buffer->ul_dci_req = 0; } + + + //checking in the rx slot buffers to see if a p7 msg is present. + + if(rx_slot_buffer->ul_tti_req != 0 && rx_slot_buffer->ul_tti_req->SFN == sfn && rx_slot_buffer->ul_tti_req->Slot == slot) + { + if(pnf_p7->_public.ul_tti_req_fn) + { + //NFAPI_TRACE(NFAPI_TRACE_INFO, "Calling UL_tti_req_fn in SFN/slot %d.%d \n",sfn,slot); + (pnf_p7->_public.ul_tti_req_fn)(NULL, &(pnf_p7->_public), rx_slot_buffer->ul_tti_req); + } + } else { - // If we ever need to "send" a dummy ul_config this won't work!!! - // send_dummy_subframe(pnf_p7, sfn_sf_tx); + // send dummy + if(pnf_p7->_public.ul_tti_req_fn && pnf_p7->_public.dummy_slot.ul_tti_req) + { + pnf_p7->_public.dummy_slot.ul_tti_req->SFN = sfn; + pnf_p7->_public.dummy_slot.ul_tti_req->Slot = slot; + (pnf_p7->_public.ul_tti_req_fn)(NULL, &(pnf_p7->_public), pnf_p7->_public.dummy_slot.ul_tti_req); + } + } + if(rx_slot_buffer->ul_tti_req != 0) + { + deallocate_nfapi_ul_tti_request(rx_slot_buffer->ul_tti_req, pnf_p7); + rx_slot_buffer->ul_tti_req = 0; - // send_dummy_slot(pnf_p7, sfn_tx, slot_tx); } + //reset slot buffer - - if(slot_buffer->sfn == sfn && slot_buffer->slot == slot ) + if ( rx_slot_buffer->dl_tti_req == 0 && + rx_slot_buffer->tx_data_req == 0 && + rx_slot_buffer->ul_tti_req == 0) { - - if(slot_buffer->ul_tti_req != 0) - { - if(pnf_p7->_public.ul_tti_req_fn) - { - (pnf_p7->_public.ul_tti_req_fn)(NULL, &(pnf_p7->_public), slot_buffer->ul_tti_req); - } - } - else - { - // send dummy - if(pnf_p7->_public.ul_tti_req_fn && pnf_p7->_public.dummy_slot.ul_tti_req) - { - pnf_p7->_public.dummy_slot.ul_tti_req->SFN = sfn; - pnf_p7->_public.dummy_slot.ul_tti_req->Slot = slot; - (pnf_p7->_public.ul_tti_req_fn)(NULL, &(pnf_p7->_public), pnf_p7->_public.dummy_slot.ul_tti_req); - } - } - //if(subframe_buffer->dl_config_req != 0) - //deallocate_nfapi_dl_config_request(subframe_buffer->dl_config_req, pnf_p7); - //if(subframe_buffer->tx_req != 0) - //deallocate_nfapi_tx_request(subframe_buffer->tx_req, pnf_p7); - if(slot_buffer->ul_tti_req != 0) - { - deallocate_nfapi_ul_tti_request(slot_buffer->ul_tti_req, pnf_p7); - slot_buffer->ul_tti_req = 0; - - } - #if 0 - if(slot_buffer->lbt_dl_config_req != 0) - { - deallocate_nfapi_lbt_dl_config_request(slot_buffer->lbt_dl_config_req, pnf_p7); - slot_buffer->lbt_dl_config_req = 0; - } - #endif - } // sfn_slot match - - - if ( slot_buffer->dl_tti_req == 0 && - slot_buffer->tx_data_req == 0 && - slot_buffer->ul_tti_req == 0) - //slot_buffer->lbt_dl_config_req == 0 && - //slot_buffer->ue_release_req == 0) - { - memset(&(pnf_p7->slot_buffer[buffer_index]), 0, sizeof(nfapi_pnf_p7_slot_buffer_t)); - pnf_p7->slot_buffer[buffer_index].sfn = -1; - pnf_p7->slot_buffer[buffer_index].slot = -1; + memset(&(pnf_p7->slot_buffer[buffer_index_rx]), 0, sizeof(nfapi_pnf_p7_slot_buffer_t)); + pnf_p7->slot_buffer[buffer_index_rx].sfn = -1; + pnf_p7->slot_buffer[buffer_index_rx].slot = -1; } //printf("pnf_p7->_public.timing_info_mode_periodic:%d pnf_p7->timing_info_period_counter:%d pnf_p7->_public.timing_info_period:%d\n", pnf_p7->_public.timing_info_mode_periodic, pnf_p7->timing_info_period_counter, pnf_p7->_public.timing_info_period); //printf("pnf_p7->_public.timing_info_mode_aperiodic:%d pnf_p7->timing_info_aperiodic_send:%d\n", pnf_p7->_public.timing_info_mode_aperiodic, pnf_p7->timing_info_aperiodic_send); //printf("pnf_p7->timing_info_ms_counter:%d\n", pnf_p7->timing_info_ms_counter); - // send the periodic timing info if configured + //send the periodic timing info if configured if(pnf_p7->_public.timing_info_mode_periodic && (pnf_p7->timing_info_period_counter++) == pnf_p7->_public.timing_info_period) { pnf_nr_pack_and_send_timing_info(pnf_p7); @@ -1179,29 +1139,9 @@ int pnf_p7_slot_ind(pnf_p7_t* pnf_p7, uint16_t phy_id, uint16_t sfn, uint16_t sl else { pnf_p7->timing_info_ms_counter++; - } + } //gokul } - else - { - //send_dummy_subframe(pnf_p7, sfn_sf_tx); - } - - - //printf("pnf_p7->tick:%d\n", pnf_p7->tick); - // if(pnf_p7->tick == 1000) // why? - // { - // // TODO: change stats to nr_stats - // NFAPI_TRACE(NFAPI_TRACE_INFO, "[PNF P7:%d] (ONTIME/LATE) DL:(%d/%d) UL:(%d/%d) HI:(%d/%d) TX:(%d/%d)\n", pnf_p7->_public.phy_id, - // pnf_p7->stats.dl_conf_ontime, pnf_p7->stats.dl_conf_late, - // pnf_p7->stats.ul_conf_ontime, pnf_p7->stats.ul_conf_late, - // pnf_p7->stats.hi_dci0_ontime, pnf_p7->stats.hi_dci0_late, - // pnf_p7->stats.tx_ontime, pnf_p7->stats.tx_late); - // pnf_p7->tick = 0; - // memset(&pnf_p7->stats, 0, sizeof(pnf_p7->stats)); - // } - // pnf_p7->tick++; - if(pthread_mutex_unlock(&(pnf_p7->mutex)) != 0) { @@ -1654,34 +1594,18 @@ void pnf_handle_dl_tti_request(void* pRecvMsg, int recvMsgLen, pnf_p7_t* pnf_p7) NFAPI_TRACE(NFAPI_TRACE_INFO, "failed to lock mutex\n"); return; } -#if 0 - if ( - 0 && - (NFAPI_SFNSF2DEC(req->sfn_sf) % 100 ==0 || - NFAPI_SFNSF2DEC(req->sfn_sf) % 105 ==0 - ) - ) - NFAPI_TRACE(NFAPI_TRACE_INFO, "DL_CONFIG.req sfn_sf:%d pdcch:%u dci:%u pdu:%u pdsch_rnti:%u pcfich:%u\n", - NFAPI_SFNSF2DEC(req->sfn_sf), - req->dl_config_request_body.number_pdcch_ofdm_symbols, - req->dl_config_request_body.number_dci, - req->dl_config_request_body.number_pdu, - req->dl_config_request_body.number_pdsch_rnti, - req->dl_config_request_body.transmission_power_pcfich - ); -#endif - if(is_nr_p7_request_in_window(req->SFN,req->Slot, "dl_tti_request", pnf_p7)) - { - uint32_t sfn_slot_dec = NFAPI_SFNSLOT2DEC(req->SFN,req->Slot); - uint8_t buffer_index = sfn_slot_dec % pnf_p7->_public.slot_buffer_size; + if(is_nr_p7_request_in_window(req->SFN,req->Slot, "dl_tti_request", pnf_p7)) + { + uint32_t sfn_slot_dec = NFAPI_SFNSLOT2DEC(req->SFN,req->Slot); + uint8_t buffer_index = sfn_slot_dec % 20; - struct timespec t; - clock_gettime(CLOCK_MONOTONIC, &t); + struct timespec t; + clock_gettime(CLOCK_MONOTONIC, &t); - //NFAPI_TRACE(NFAPI_TRACE_INFO,"%s() %ld.%09ld POPULATE DL_TTI_REQ sfn_slot:%d buffer_index:%d\n", __FUNCTION__, t.tv_sec, t.tv_nsec, sfn_slot_dec, buffer_index); + NFAPI_TRACE(NFAPI_TRACE_INFO,"%s() POPULATE DL_TTI_REQ SFN/slot: %d.%d buffer_index:%d\n", __FUNCTION__, req->SFN, req->Slot, buffer_index); - // if there is already an dl_config_req make sure we free it. + // if there is already an dl_tti_req make sure we free it. if(pnf_p7->slot_buffer[buffer_index].dl_tti_req != 0) { NFAPI_TRACE(NFAPI_TRACE_NOTE, "%s() is_nr_p7_request_in_window()=TRUE buffer_index occupied - free it first sfn_slot:%d buffer_index:%d\n", __FUNCTION__, NFAPI_SFNSLOT2DEC(req->SFN,req->Slot), buffer_index); @@ -1691,7 +1615,7 @@ void pnf_handle_dl_tti_request(void* pRecvMsg, int recvMsgLen, pnf_p7_t* pnf_p7) deallocate_nfapi_dl_tti_request(pnf_p7->slot_buffer[buffer_index].dl_tti_req, pnf_p7); } - // saving dl_config_request in subframe buffer + // filling dl_tti_request in slot buffer pnf_p7->slot_buffer[buffer_index].sfn = req->SFN; pnf_p7->slot_buffer[buffer_index].slot = req->Slot; pnf_p7->slot_buffer[buffer_index].dl_tti_req = req; @@ -1840,7 +1764,7 @@ void pnf_handle_ul_tti_request(void* pRecvMsg, int recvMsgLen, pnf_p7_t* pnf_p7) if(is_nr_p7_request_in_window(req->SFN,req->Slot, "ul_tti_request", pnf_p7)) { uint32_t sfn_slot_dec = NFAPI_SFNSLOT2DEC(req->SFN,req->Slot); - uint8_t buffer_index = sfn_slot_dec % pnf_p7->_public.slot_buffer_size; + uint8_t buffer_index = sfn_slot_dec % 20; struct timespec t; clock_gettime(CLOCK_MONOTONIC, &t); @@ -1855,6 +1779,8 @@ void pnf_handle_ul_tti_request(void* pRecvMsg, int recvMsgLen, pnf_p7_t* pnf_p7) deallocate_nfapi_ul_tti_request(pnf_p7->slot_buffer[buffer_index].ul_tti_req, pnf_p7); } + + //filling slot buffer pnf_p7->slot_buffer[buffer_index].sfn = req->SFN; pnf_p7->slot_buffer[buffer_index].slot = req->Slot; @@ -1986,7 +1912,7 @@ void pnf_handle_ul_dci_request(void* pRecvMsg, int recvMsgLen, pnf_p7_t* pnf_p7) if(is_nr_p7_request_in_window(req->SFN,req->Slot,"ul_dci_request", pnf_p7)) { uint32_t sfn_slot_dec = NFAPI_SFNSLOT2DEC(req->SFN,req->Slot); - uint8_t buffer_index = sfn_slot_dec % pnf_p7->_public.slot_buffer_size; + uint8_t buffer_index = sfn_slot_dec % 20; if(pnf_p7->slot_buffer[buffer_index].ul_dci_req!= 0) { @@ -2125,7 +2051,7 @@ void pnf_handle_tx_data_request(void* pRecvMsg, int recvMsgLen, pnf_p7_t* pnf_p7 if(is_nr_p7_request_in_window(req->SFN, req->Slot,"tx_request", pnf_p7)) { uint32_t sfn_slot_dec = NFAPI_SFNSLOT2DEC(req->SFN,req->Slot); - uint8_t buffer_index = sfn_slot_dec % pnf_p7->_public.slot_buffer_size; + uint8_t buffer_index = sfn_slot_dec % 20; struct timespec t; clock_gettime(CLOCK_MONOTONIC, &t); @@ -2692,9 +2618,7 @@ void pnf_nr_dispatch_p7_message(void *pRecvMsg, int recvMsgLen, pnf_p7_t* pnf_p7 case NFAPI_NR_PHY_MSG_TYPE_DL_NODE_SYNC: pnf_nr_handle_dl_node_sync(pRecvMsg, recvMsgLen, pnf_p7, rx_hr_time); break; - case NFAPI_NR_PHY_MSG_TYPE_DL_TTI_REQUEST: - //printf("\nEntering pnf_handle_dl_tti_request sfn=%d,slot=%d \n",pnf_p7->sfn,pnf_p7->slot); pnf_handle_dl_tti_request(pRecvMsg, recvMsgLen, pnf_p7); break; case NFAPI_NR_PHY_MSG_TYPE_UL_TTI_REQUEST: diff --git a/nfapi/open-nFAPI/vnf/src/vnf_p7.c b/nfapi/open-nFAPI/vnf/src/vnf_p7.c index 11885d7c48..7f5d33466d 100644 --- a/nfapi/open-nFAPI/vnf/src/vnf_p7.c +++ b/nfapi/open-nFAPI/vnf/src/vnf_p7.c @@ -2011,7 +2011,9 @@ void vnf_handle_timing_info(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vnf_p7) void vnf_nr_handle_timing_info(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vnf_p7) -{ +{ + uint8_t uplink_slots[6] = {7,8,9,17,18,19}; + uint8_t is_uplink_slot = 0; if (pRecvMsg == NULL || vnf_p7 == NULL) { NFAPI_TRACE(NFAPI_TRACE_ERROR, "vnf_handle_timing_info: NULL parameters\n"); @@ -2030,16 +2032,20 @@ void vnf_nr_handle_timing_info(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vnf_p7) //int16_t vnf_pnf_sfnsf_delta = NFAPI_SFNSF2DEC(vnf_p7->p7_connections[0].sfn_sf) - NFAPI_SFNSF2DEC(ind.last_sfn_sf); int16_t vnf_pnf_sfnslot_delta = NFAPI_SFNSLOT2DEC(vnf_p7->p7_connections[0].sfn,vnf_p7->p7_connections[0].slot) - NFAPI_SFNSLOT2DEC(ind.last_sfn,ind.last_slot); //NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() PNF:SFN/SF:%d VNF:SFN/SF:%d deltaSFNSF:%d\n", __FUNCTION__, NFAPI_SFNSF2DEC(ind.last_sfn_sf), NFAPI_SFNSF2DEC(vnf_p7->p7_connections[0].sfn_sf), vnf_pnf_sfnsf_delta); - // Panos: Careful here!!! Modification of the original nfapi-code //if (vnf_pnf_sfnsf_delta>1 || vnf_pnf_sfnsf_delta < -1) //printf("VNF-PNF delta - %d", vnf_pnf_sfnslot_delta); - if (vnf_pnf_sfnslot_delta>0 || vnf_pnf_sfnslot_delta < 0) + for (int i = 0; i < 6; i++){ + if (vnf_p7->p7_connections[0].slot == uplink_slots[i]) + is_uplink_slot = 1; + } + if ((vnf_pnf_sfnslot_delta>0 || vnf_pnf_sfnslot_delta < 0) && is_uplink_slot == 0) { NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() LARGE SFN/SF DELTA between PNF and VNF delta:%d VNF:%d PNF:%d\n\n\n\n\n\n\n\n\n", __FUNCTION__, vnf_pnf_sfnslot_delta,NFAPI_SFNSLOT2DEC(vnf_p7->p7_connections[0].sfn,vnf_p7->p7_connections[0].slot),NFAPI_SFNSLOT2DEC(ind.last_sfn,ind.last_slot)) ; // Panos: Careful here!!! Modification of the original nfapi-code vnf_p7->p7_connections[0].sfn = ind.last_sfn; vnf_p7->p7_connections[0].slot = ind.last_slot; + //printf("VNF SFN/slot modified"); } } } diff --git a/nfapi/open-nFAPI/vnf/src/vnf_p7_interface.c b/nfapi/open-nFAPI/vnf/src/vnf_p7_interface.c index b84003ab6e..71a912057e 100644 --- a/nfapi/open-nFAPI/vnf/src/vnf_p7_interface.c +++ b/nfapi/open-nFAPI/vnf/src/vnf_p7_interface.c @@ -157,10 +157,6 @@ int nfapi_nr_vnf_p7_start(nfapi_vnf_p7_config_t* config) struct timespec pselect_start; struct timespec pselect_stop; - //struct timespec sf_end; - - long last_millisecond = -1; - // struct timespec sf_duration; //Change to slot_duration? // sf_duration.tv_sec = 0; @@ -200,263 +196,79 @@ int nfapi_nr_vnf_p7_start(nfapi_vnf_p7_config_t* config) setup_time = curr_time.tv_sec - ref_time.tv_sec; clock_gettime(CLOCK_MONOTONIC, &pselect_start); - //long millisecond = pselect_start.tv_nsec / 1e6; - if((last_millisecond == -1) || (millisecond == last_millisecond) || (millisecond == (last_millisecond + 1) % 1000) ) + //NFAPI_TRACE(NFAPI_TRACE_INFO, "pselect_start:%d.%d sf_start:%d.%d\n", pselect_start.tv_sec, pselect_start.tv_nsec, sf_start.tv_sec, sf_start.tv_nsec); + + 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))) { - //NFAPI_TRACE(NFAPI_TRACE_INFO, "pselect_start:%d.%d sf_start:%d.%d\n", pselect_start.tv_sec, pselect_start.tv_nsec, sf_start.tv_sec, sf_start.tv_nsec); - - - //if((pselect_start.tv_sec > sf_start.tv_sec) || - // ((pselect_start.tv_sec == sf_start.tv_sec) && (pselect_start.tv_nsec > sf_start.tv_nsec))) - 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 - pselect_timeout.tv_sec = 0; - pselect_timeout.tv_nsec = 0; - - //struct timespec overrun = 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 - //pselect_timeout = timespec_sub(sf_start, pselect_start); - pselect_timeout = timespec_sub(slot_start, pselect_start); - } - -//original_pselect_timeout = pselect_timeout; - - // detemine how long to sleep in ns before the start of the next 1ms - //pselect_timeout.tv_nsec = 1e6 - (pselect_start.tv_nsec % 1000000); - - //uint8_t underrun_possible =0; - - // if we are not sleeping until the next milisecond due to the - // insycn minor adjment flag it so we don't consider it an error - //uint8_t underrun_possible =0; - /* - { - nfapi_vnf_p7_connection_info_t* phy = vnf_p7->p7_connections; - if(phy && phy->in_sync && phy->insync_minor_adjustment != 0 && phy->insync_minor_adjustment_duration > 0 && pselect_start.tv_nsec != 0) - { - NFAPI_TRACE(NFAPI_TRACE_NOTE, "[VNF] Subframe minor adjustment %d (%d->%d)\n", phy->insync_minor_adjustment, - pselect_timeout.tv_nsec, pselect_timeout.tv_nsec - (phy->insync_minor_adjustment * 1000)) - if(phy->insync_minor_adjustment > 0) - { - // todo check we don't go below 0 - if((phy->insync_minor_adjustment * 1000) > pselect_timeout.tv_nsec) - pselect_timeout.tv_nsec = 0; - else - pselect_timeout.tv_nsec = pselect_timeout.tv_nsec - (phy->insync_minor_adjustment * 1000); - - - //underrun_possible = 1; - } - else if(phy->insync_minor_adjustment < 0) - { - // todo check we don't go below 0 - pselect_timeout.tv_nsec = pselect_timeout.tv_nsec - (phy->insync_minor_adjustment * 1000); - - - //phy->insync_minor_adjustment = 0; - phy->insync_minor_adjustment_duration--; - } - } - */ - - if(setup_time > 10 && slot_scheduled == 0){ - - // Call the scheduler - struct PHY_VARS_gNB_s *gNB = RC.gNB[0]; - pthread_mutex_lock(&gNB->UL_INFO_mutex); - gNB->UL_INFO.frame = vnf_frame; - gNB->UL_INFO.slot = vnf_slot; - - gNB->UL_INFO.module_id = gNB->Mod_id; - gNB->UL_INFO.CC_id = gNB->CC_id; - gNB->if_inst->NR_UL_indication(&gNB->UL_INFO); - pthread_mutex_unlock(&gNB->UL_INFO_mutex); - //printf("Scheduler called at SFN/slot %d.%d. \n",vnf_frame,vnf_slot); - slot_scheduled = 1; - } - -//long wraps = pselect_timeout.tv_nsec % 1e9; - - // pselect_timeout.tv_sec = 100; // 0 - // pselect_timeout.tv_nsec = 0;//500000; // ns in a 0.5 ms - selectRetval = pselect(maxSock+1, &rfds, NULL, NULL, &pselect_timeout, NULL); - // selectRetval = pselect(120, &rfds, NULL, NULL, &pselect_timeout, NULL); - - clock_gettime(CLOCK_MONOTONIC, &pselect_stop); - - nfapi_vnf_p7_connection_info_t* phy = vnf_p7->p7_connections; - -if (selectRetval==-1 && errno == 22) -{ -// NFAPI_TRACE(NFAPI_TRACE_ERROR, "INVAL: pselect_timeout:%d.%ld adj[dur:%d adj:%d], sf_dur:%d.%ld\n", -// pselect_timeout.tv_sec, pselect_timeout.tv_nsec, -// phy->insync_minor_adjustment_duration, phy->insync_minor_adjustment, -// sf_duration.tv_sec, sf_duration.tv_nsec); - -NFAPI_TRACE(NFAPI_TRACE_ERROR, "INVAL: pselect_timeout:%d.%ld adj[dur:%d adj:%d], sf_dur:%d.%ld\n", - pselect_timeout.tv_sec, pselect_timeout.tv_nsec, - phy->insync_minor_adjustment_duration, phy->insync_minor_adjustment, - slot_duration.tv_sec, slot_duration.tv_nsec); - -} - if(selectRetval == 0) - { - // calculate the start of the next slot - //sf_start = timespec_add(sf_start, sf_duration); - slot_start = timespec_add(slot_start, slot_duration); - //NFAPI_TRACE(NFAPI_TRACE_INFO, "next subframe will start at %d.%d\n", sf_start.tv_sec, sf_start.tv_nsec); - - if(phy && phy->in_sync && phy->insync_minor_adjustment != 0 && phy->insync_minor_adjustment_duration > 0) - { - long insync_minor_adjustment_ns = (phy->insync_minor_adjustment * 1000); - - //sf_start.tv_nsec -= insync_minor_adjustment_ns; - slot_start.tv_nsec -= insync_minor_adjustment_ns; - -#if 1 -/* if (sf_start.tv_nsec > 1e9) //Change to 0.5e6? - { - sf_start.tv_sec++; - sf_start.tv_nsec-=1e9; - } - else if (sf_start.tv_nsec < 0) - { - sf_start.tv_sec--; - sf_start.tv_nsec+=1e9; - }*/ - if (slot_start.tv_nsec > 1e9) - { - slot_start.tv_sec++; - slot_start.tv_nsec-=1e9; - } - else if (slot_start.tv_nsec < 0) - { - slot_start.tv_sec--; - slot_start.tv_nsec+=1e9; - } -#else - //NFAPI_TRACE(NFAPI_TRACE_NOTE, "[VNF] BEFORE adjustment - Subframe minor adjustment %dus sf_start.tv_nsec:%d\n", phy->insync_minor_adjustment, sf_start.tv_nsec); - if(phy->insync_minor_adjustment > 0) - { - // decrease the subframe duration a little - if (sf_start.tv_nsec > insync_minor_adjustment_ns) - sf_start.tv_nsec -= insync_minor_adjustment_ns; - else - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "[VNF] Adjustment would make it negative sf:%d.%ld adjust:%ld\n\n\n", sf_start.tv_sec, sf_start.tv_nsec, insync_minor_adjustment_ns); - sf_start.tv_sec--; - sf_start.tv_nsec += 1e9 - insync_minor_adjustment_ns; - } - } - else if(phy->insync_minor_adjustment < 0) - { - // todo check we don't go below 0 - // increase the subframe duration a little - sf_start.tv_nsec += insync_minor_adjustment_ns; - - if (sf_start.tv_nsec < 0) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "[VNF] OVERFLOW %d.%ld\n\n\n\n", sf_start.tv_sec, sf_start.tv_nsec); - sf_start.tv_sec++; - sf_start.tv_nsec += 1e9; - } - } -#endif - - //phy->insync_minor_adjustment = 0; - phy->insync_minor_adjustment_duration--; - -// NFAPI_TRACE(NFAPI_TRACE_NOTE, "[VNF] AFTER adjustment - Subframe minor adjustment %dus sf_start.tv_nsec:%d duration:%u\n", -// phy->insync_minor_adjustment, sf_start.tv_nsec, phy->insync_minor_adjustment_duration); - // NFAPI_TRACE(NFAPI_TRACE_NOTE, "[VNF] AFTER adjustment - Slot minor adjustment %dus slot_start.tv_nsec:%d duration:%u\n", - // phy->insync_minor_adjustment, slot_start.tv_nsec, phy->insync_minor_adjustment_duration); - - if (phy->insync_minor_adjustment_duration==0) - { - phy->insync_minor_adjustment = 0; - } - } - /* - long pselect_stop_millisecond = pselect_stop.tv_nsec / 1e6; - if(millisecond == pselect_stop_millisecond) - { - // we have woke up in the same subframe - if(underrun_possible == 0) - NFAPI_TRACE(NFAPI_TRACE_WARN, "subframe pselect underrun %ld (%d.%d)\n", millisecond, pselect_stop.tv_sec, pselect_stop.tv_nsec); - } - else if(((millisecond + 1) % 1000) != pselect_stop_millisecond) - { - // we have overrun the subframe - NFAPI_TRACE(NFAPI_TRACE_WARN, "subframe pselect overrun %ld %ld\n", millisecond, pselect_stop_millisecond); - NFAPI_TRACE(NFAPI_TRACE_WARN, "subframe underrun %ld\n", millisecond); - } - last_millisecond = millisecond; - */ - - //millisecond ++; - millisecond = millisecond + 1; - - } + // overran the end of the subframe we do not want to wait + pselect_timeout.tv_sec = 0; + pselect_timeout.tv_nsec = 0; + LOG_D(MAC, "Slot overrun detected \n"); + //NFAPI_TRACE(NFAPI_TRACE_INFO, "Slot overrun detected of %d.%d running to catchup\n", overrun.tv_sec, overrun.tv_nsec); } else { - // we have overrun the subframe advance to go and collect $200 - - if((millisecond - last_millisecond) > 3) - NFAPI_TRACE(NFAPI_TRACE_WARN, "subframe overrun %ld %ld (%ld)\n", millisecond, last_millisecond, millisecond - last_millisecond + 1); - - last_millisecond = ( last_millisecond + 1 ) % 1000; - selectRetval = 0; + // still time before the end of the subframe wait + pselect_timeout = timespec_sub(slot_start, pselect_start); } + if(setup_time > 10 && slot_scheduled == 0){ + + // Call the scheduler + struct PHY_VARS_gNB_s *gNB = RC.gNB[0]; + pthread_mutex_lock(&gNB->UL_INFO_mutex); + gNB->UL_INFO.frame = vnf_frame; + gNB->UL_INFO.slot = vnf_slot; + + gNB->UL_INFO.module_id = gNB->Mod_id; + gNB->UL_INFO.CC_id = gNB->CC_id; + gNB->if_inst->NR_UL_indication(&gNB->UL_INFO); + pthread_mutex_unlock(&gNB->UL_INFO_mutex); + slot_scheduled = 1; + } + + selectRetval = pselect(maxSock+1, &rfds, NULL, NULL, &pselect_timeout, NULL); + + clock_gettime(CLOCK_MONOTONIC, &pselect_stop); + nfapi_vnf_p7_connection_info_t* curr = vnf_p7->p7_connections; - uint8_t ul_p7_count = 0; + if(selectRetval == 0) { - //vnf_p7->sf_start_time_hr = vnf_get_current_time_hr(); - vnf_p7->slot_start_time_hr = vnf_get_current_time_hr(); -struct timespec current_time; - clock_gettime(CLOCK_MONOTONIC, ¤t_time); // pselect timed out - - // if(setup_time > 10){ - // // Call the scheduler - // struct PHY_VARS_gNB_s *gNB = RC.gNB[0]; - // pthread_mutex_lock(&gNB->UL_INFO_mutex); - // gNB->UL_INFO.frame = vnf_frame; - // gNB->UL_INFO.slot = vnf_slot; - // gNB->UL_INFO.module_id = gNB->Mod_id; - // gNB->UL_INFO.CC_id = gNB->CC_id; - // gNB->if_inst->NR_UL_indication(&gNB->UL_INFO); - // pthread_mutex_unlock(&gNB->UL_INFO_mutex); - // } + // calculate the start of the next slot + + slot_start = timespec_add(slot_start, slot_duration); + //NFAPI_TRACE(NFAPI_TRACE_INFO, "next subframe will start at %d.%d\n", sf_start.tv_sec, sf_start.tv_nsec); + if (slot_start.tv_nsec > 1e9) + { + slot_start.tv_sec++; + slot_start.tv_nsec-=1e9; + } + else if (slot_start.tv_nsec < 0) + { + slot_start.tv_sec--; + slot_start.tv_nsec+=1e9; + } + + vnf_p7->slot_start_time_hr = vnf_get_current_time_hr(); while(curr != 0) { if (curr->slot == 19) - { //curr->slot = 0; - if(curr->sfn == 1023) - curr->sfn=0; - else - curr->sfn++; - curr->slot=0; + { + curr->sfn = (curr->sfn + 1) % 1024; + curr->slot=0; } else { curr->slot++; } //printf("Frame = %d, slot = %d in VNF main loop. \n",curr->sfn,curr->slot); - vnf_frame = curr->sfn; vnf_slot = curr->slot; - - struct timespec curr_time; - clock_gettime(CLOCK_MONOTONIC, &curr_time); + vnf_frame = curr->sfn; + vnf_slot = curr->slot; //vnf_nr_sync(vnf_p7, curr); @@ -466,6 +278,7 @@ struct timespec current_time; } send_mac_slot_indications(vnf_p7); slot_scheduled = 0; + } else if(selectRetval > 0) { @@ -484,7 +297,7 @@ struct timespec current_time; } 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); + //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 { @@ -492,10 +305,7 @@ struct timespec current_time; } } } - } - - NFAPI_TRACE(NFAPI_TRACE_INFO, "Closing p7 socket\n"); close(vnf_p7->socket); diff --git a/openair1/PHY/LTE_UE_TRANSPORT/dlsch_decoding.c b/openair1/PHY/LTE_UE_TRANSPORT/dlsch_decoding.c index 39900113b7..a82356f16a 100644 --- a/openair1/PHY/LTE_UE_TRANSPORT/dlsch_decoding.c +++ b/openair1/PHY/LTE_UE_TRANSPORT/dlsch_decoding.c @@ -780,11 +780,11 @@ int dlsch_encoding_SIC(PHY_VARS_UE *ue, for (r=0; rharq_processes[harq_pid]->C; r++) { #ifdef DEBUG_DLSCH_CODING - printf("Rate Matching, Code segment %u (coded bits (G) %u,unpunctured/repeated bits per code segment %u,mod_order %d, nb_rb %d)...\n", - r, - G, - Kr*3, - mod_order,nb_rb); + // printf("Rate Matching, Code segment %u (coded bits (G) %u,unpunctured/repeated bits per code segment %u,mod_order %d, nb_rb %d)...\n", + // r, + // G, + // Kr*3, + // mod_order,nb_rb); #endif start_meas(rm_stats); #ifdef DEBUG_DLSCH_CODING diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c index 7d9d55808a..a60a68de90 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c @@ -134,6 +134,7 @@ void clear_nr_nfapi_information(gNB_MAC_INST * gNB, /* advance last round's future UL_tti_req to be ahead of current frame/slot */ future_ul_tti_req->SFN = (slotP == 0 ? frameP : frameP + 1) % 1024; + LOG_D(MAC,"Future_ul_tti SFN = %d for slot %d \n", future_ul_tti_req->SFN, (slotP + num_slots - 1) % num_slots); /* future_ul_tti_req->Slot is fixed! */ future_ul_tti_req->n_pdus = 0; future_ul_tti_req->n_ulsch = 0; @@ -374,9 +375,10 @@ void gNB_dlsch_ulsch_scheduler(module_id_t module_idP, if (NFAPI_MODE == NFAPI_MODE_VNF){ if(first_sched_entry == 1) { + printf("First sched entry at slot %d \n", slot); for (int i = 0; iUL_tti_req_ahead[CC_id][i].SFN = frame + 1; + gNB->UL_tti_req_ahead[CC_id][i].SFN = (frame + 1) % 1024; else gNB->UL_tti_req_ahead[CC_id][i].SFN = frame; } diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c index fde53c3d0c..3b6655bd99 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c @@ -46,7 +46,6 @@ void nr_fill_nfapi_pucch(module_id_t mod_id, nfapi_nr_ul_tti_request_t *future_ul_tti_req = &RC.nrmac[mod_id]->UL_tti_req_ahead[0][pucch->ul_slot]; - AssertFatal(future_ul_tti_req->SFN == pucch->frame && future_ul_tti_req->Slot == pucch->ul_slot, "future UL_tti_req's frame.slot %d.%d does not match PUCCH %d.%d\n", @@ -1140,10 +1139,6 @@ int nr_acknack_scheduling(int mod_id, __func__, pucch->csi_bits); /* if the currently allocated PUCCH of this UE is full, allocate it */ - // if (NFAPI_MODE == NFAPI_MODE_VNF){ - // pucch->sr_flag = 1; - // pucch->dai_c = 1; - // } if (pucch->dai_c == 2) { /* advance the UL slot information in PUCCH by one so we won't schedule in @@ -1174,7 +1169,7 @@ int nr_acknack_scheduling(int mod_id, /* if the UE's next PUCCH occasion is after the possible UL slots (within the * same frame) or wrapped around to the next frame, then we assume there is * no possible PUCCH allocation anymore */ - if(NFAPI_MODE == NFAPI_MONOLITHIC) + if ((pucch->frame == frame && (pucch->ul_slot >= first_ul_slot_tdd + nr_ulmix_slots)) || (pucch->frame == frame + 1)) @@ -1186,10 +1181,10 @@ int nr_acknack_scheduling(int mod_id, get_pdsch_to_harq_feedback(mod_id, UE_id, ss_type, pdsch_to_harq_feedback); /* there is a HARQ. Check whether we can use it for this ACKNACK */ - // if(NFAPI_MODE == NFAPI_MODE_VNF) - // return 0; + if (pucch->dai_c > 0) { /* this UE already has a PUCCH occasion */ + LOG_I(MAC,"pucch->frame = %d,frame=%d \n",pucch->frame,frame); DevAssert(pucch->frame == frame); // Find the right timing_indicator value. diff --git a/openair2/NR_PHY_INTERFACE/NR_IF_Module.c b/openair2/NR_PHY_INTERFACE/NR_IF_Module.c index f90361f564..5a1cb970eb 100644 --- a/openair2/NR_PHY_INTERFACE/NR_IF_Module.c +++ b/openair2/NR_PHY_INTERFACE/NR_IF_Module.c @@ -88,7 +88,7 @@ void handle_nr_uci(NR_UL_IND_t *UL_info) { if(NFAPI_MODE == NFAPI_MODE_PNF) { if (UL_info->uci_ind.num_ucis>0) { - LOG_I(PHY,"PNF Sending UL_info->num_ucis:%d PDU_type: %d, SFN/SF:%d.%d \n", UL_info->uci_ind.num_ucis, UL_info->uci_ind.uci_list[0].pdu_type ,UL_info->frame, UL_info->slot); + LOG_D(PHY,"PNF Sending UL_info->num_ucis:%d PDU_type: %d, SFN/SF:%d.%d \n", UL_info->uci_ind.num_ucis, UL_info->uci_ind.uci_list[0].pdu_type ,UL_info->frame, UL_info->slot); oai_nfapi_nr_uci_indication(&UL_info->uci_ind); UL_info->uci_ind.num_ucis = 0; } @@ -99,7 +99,7 @@ void handle_nr_uci(NR_UL_IND_t *UL_info) const sub_frame_t slot = UL_info->slot; int num_ucis = UL_info->uci_ind.num_ucis; nfapi_nr_uci_t *uci_list = UL_info->uci_ind.uci_list; - //printf("handling UCI SFN/slot: %d.%d, num_ucis: %d \n", frame,slot, num_ucis); + LOG_I(MAC,"handling UCI SFN/slot: %d.%d, num_ucis: %d \n", frame,slot, num_ucis); for (int i = 0; i < num_ucis; i++) { switch (uci_list[i].pdu_type) { case NFAPI_NR_UCI_PUSCH_PDU_TYPE: @@ -120,6 +120,7 @@ void handle_nr_uci(NR_UL_IND_t *UL_info) break; } } + LOG_D(MAC, "UCI handled \n"); } } From 62b1531c55c7dcdc3b516609bf8b4f27482fa040 Mon Sep 17 00:00:00 2001 From: francescomani Date: Wed, 4 Aug 2021 14:23:50 +0200 Subject: [PATCH 71/91] improvement in fix for commonControlResourceSet for SIB1 --- openair2/GNB_APP/gnb_config.c | 31 +---------------------------- openair2/RRC/NR/MESSAGES/asn1_msg.c | 1 - 2 files changed, 1 insertion(+), 31 deletions(-) diff --git a/openair2/GNB_APP/gnb_config.c b/openair2/GNB_APP/gnb_config.c index 94337ecb58..124e48eb9d 100644 --- a/openair2/GNB_APP/gnb_config.c +++ b/openair2/GNB_APP/gnb_config.c @@ -132,36 +132,7 @@ void prepare_scc(NR_ServingCellConfigCommon_t *scc) { scc->downlinkConfigCommon->initialDownlinkBWP->pdcch_ConfigCommon->choice.setup->controlResourceSetZero = CALLOC(1,sizeof(long)); scc->downlinkConfigCommon->initialDownlinkBWP->pdcch_ConfigCommon->choice.setup->searchSpaceZero = CALLOC(1,sizeof(long)); - NR_ControlResourceSet_t *coreset0 = CALLOC(1,sizeof(struct NR_ControlResourceSet)); - coreset0->controlResourceSetId = 0; - // frequencyDomainResources '11111111 00000000 00000000 00000000 00000000 00000'B, - if(coreset0->frequencyDomainResources.buf == NULL) coreset0->frequencyDomainResources.buf = calloc(1,6); - coreset0->frequencyDomainResources.buf[0] = 0xff; - coreset0->frequencyDomainResources.buf[1] = 0; - coreset0->frequencyDomainResources.buf[2] = 0; - coreset0->frequencyDomainResources.buf[3] = 0; - coreset0->frequencyDomainResources.buf[4] = 0; - coreset0->frequencyDomainResources.buf[5] = 0; - coreset0->frequencyDomainResources.size = 6; - coreset0->frequencyDomainResources.bits_unused = 3; - coreset0->duration = 1; - coreset0->cce_REG_MappingType.present=NR_ControlResourceSet__cce_REG_MappingType_PR_interleaved; - coreset0->cce_REG_MappingType.choice.interleaved=calloc(1,sizeof(*coreset0->cce_REG_MappingType.choice.interleaved)); - coreset0->cce_REG_MappingType.choice.interleaved->reg_BundleSize = NR_ControlResourceSet__cce_REG_MappingType__interleaved__reg_BundleSize_n6; - coreset0->cce_REG_MappingType.choice.interleaved->interleaverSize = NR_ControlResourceSet__cce_REG_MappingType__interleaved__interleaverSize_n2; - coreset0->cce_REG_MappingType.choice.interleaved->shiftIndex = scc->physCellId; - coreset0->precoderGranularity = NR_ControlResourceSet__precoderGranularity_sameAsREG_bundle; - if(coreset0->tci_StatesPDCCH_ToAddList == NULL) coreset0->tci_StatesPDCCH_ToAddList = calloc(1,sizeof(*coreset0->tci_StatesPDCCH_ToAddList)); - NR_TCI_StateId_t *tci[8]; - for (int i=0;i<8;i++) { - tci[i]=calloc(1,sizeof(*tci[i])); - *tci[i] = i; - ASN_SEQUENCE_ADD(&coreset0->tci_StatesPDCCH_ToAddList->list,tci[i]); - } - coreset0->tci_StatesPDCCH_ToReleaseList = NULL; - coreset0->tci_PresentInDCI = NULL; - coreset0->pdcch_DMRS_ScramblingID = NULL; - scc->downlinkConfigCommon->initialDownlinkBWP->pdcch_ConfigCommon->choice.setup->commonControlResourceSet = coreset0; + scc->downlinkConfigCommon->initialDownlinkBWP->pdcch_ConfigCommon->choice.setup->commonControlResourceSet = NULL; // scc->downlinkConfigCommon->initialDownlinkBWP->pdcch_ConfigCommon->choice.setup->commonSearchSpaceList = CALLOC(1,sizeof(struct NR_PDCCH_ConfigCommon__commonSearchSpaceList)); // scc->downlinkConfigCommon->initialDownlinkBWP->pdcch_ConfigCommon->choice.setup->searchSpaceSIB1 = CALLOC(1,sizeof(NR_SearchSpaceId_t)); diff --git a/openair2/RRC/NR/MESSAGES/asn1_msg.c b/openair2/RRC/NR/MESSAGES/asn1_msg.c index 4399d2c403..e36644afb0 100755 --- a/openair2/RRC/NR/MESSAGES/asn1_msg.c +++ b/openair2/RRC/NR/MESSAGES/asn1_msg.c @@ -426,7 +426,6 @@ uint8_t do_SIB1_NR(rrc_gNB_carrier_data_t *carrier, } sib1->servingCellConfigCommon->downlinkConfigCommon.initialDownlinkBWP.pdcch_ConfigCommon = configuration->scc->downlinkConfigCommon->initialDownlinkBWP->pdcch_ConfigCommon; - sib1->servingCellConfigCommon->downlinkConfigCommon.initialDownlinkBWP.pdcch_ConfigCommon->choice.setup->commonControlResourceSet = NULL; sib1->servingCellConfigCommon->downlinkConfigCommon.initialDownlinkBWP.pdcch_ConfigCommon->choice.setup->commonSearchSpaceList = CALLOC(1,sizeof(struct NR_PDCCH_ConfigCommon__commonSearchSpaceList)); asn_set_empty(&sib1->servingCellConfigCommon->downlinkConfigCommon.initialDownlinkBWP.pdcch_ConfigCommon->choice.setup->commonSearchSpaceList->list); From ebebd3c7d7b1240e3377b4e331c7017d010dffab Mon Sep 17 00:00:00 2001 From: Raphael Defosseux Date: Wed, 4 Aug 2021 16:51:53 +0200 Subject: [PATCH 72/91] doc(docker): adding tutorial on how to deploy RF sim with EPC Signed-off-by: Raphael Defosseux --- .../yaml_files/4g_rfsimulator/README.md | 480 ++++++++++++++++++ .../4g_rfsimulator/docker-compose.yml | 31 +- 2 files changed, 494 insertions(+), 17 deletions(-) create mode 100644 ci-scripts/yaml_files/4g_rfsimulator/README.md diff --git a/ci-scripts/yaml_files/4g_rfsimulator/README.md b/ci-scripts/yaml_files/4g_rfsimulator/README.md new file mode 100644 index 0000000000..49ccc6bd28 --- /dev/null +++ b/ci-scripts/yaml_files/4g_rfsimulator/README.md @@ -0,0 +1,480 @@ + + + + + +
+ + + + + + OAI Full Stack RF simulation with containers +
+ +This page is only valid for an `Ubuntu18` host. + +**TABLE OF CONTENTS** + +1. [Retrieving the images on Docker-Hub](#1-retrieving-the-images-on-docker-hub) +2. [Deploy containers](#2-deploy-containers) + 1. [Deploy and Configure Cassandra Database](#21-deploy-and-configure-cassandra-database) + 2. [Deploy OAI CN4G containers](#22-deploy-oai-cn4g-containers) + 3. [Deploy OAI eNB in RF simulator mode](#23-deploy-oai-enb-in-rf-simulator-mode) + 4. [Deploy OAI LTE UE in RF simulator mode](#24-deploy-oai-lte-ue-in-rf-simulator-mode) +3. [Check traffic](#3-check-traffic) +4. [Un-deployment](#4-un-deployment) +5. [Explanation on the configuration](#5-explanation-on-the-configuration) + 1. [UE IMSI and Keys](#51-ue-imsi-and-keys) + 2. [PLMN and TAI](#52-plmn-and-tai) + 3. [Access to Internet](#53-access-to-internet) + +# 1. Retrieving the images on Docker-Hub # + +Currently the images are hosted under the user account `rdefosseoai`. + +This may change in the future. + +Once again you may need to log on [docker-hub](https://hub.docker.com/) if your organization has reached pulling limit as `anonymous`. + +```bash +$ docker login +Login with your Docker ID to push and pull images from Docker Hub. If you don't have a Docker ID, head over to https://hub.docker.com to create one. +Username: +Password: +``` + +Now pull images. + +```bash +$ docker pull cassandra:2.1 +$ docker pull rdefosseoai/oai-hss:latest +$ docker pull rdefosseoai/oai-mme:latest +$ docker pull rdefosseoai/oai-spgwc:latest +$ docker pull rdefosseoai/oai-spgwu-tiny:latest +``` + +And **re-tag** them for tutorials' docker-compose file to work. + +```bash +$ docker image tag rdefosseoai/oai-spgwc:latest oai-spgwc:latest +$ docker image tag rdefosseoai/oai-hss:latest oai-hss:latest +$ docker image tag rdefosseoai/oai-spgwu-tiny:latest oai-spgwu-tiny:latest +$ docker image tag rdefosseoai/oai-mme:latest oai-mme:latest +``` + +```bash +$ docker logout +``` + +How to build the Traffic-Generator image is explained [here](https://github.com/OPENAIRINTERFACE/openair-epc-fed/blob/master/docs/GENERATE_TRAFFIC.md#1-build-a-traffic-generator-image). + +I will soon push also RAN images. + +# 2. Deploy containers # + +**CAUTION: this SHALL be done in multiple steps.** + +**Just `docker-compose up -d` WILL NOT WORK!** + +## 2.1. Deploy and Configure Cassandra Database ## + +It is very crutial that the Cassandra DB is fully configured before you do anything else! + +```bash +$ docker-compose up -d db_init +Creating network "rfsim4g-oai-private-net" with the default driver +Creating network "rfsim4g-oai-public-net" with the default driver +Creating rfsim4g-cassandra ... done +Creating rfsim4g-db-init ... done + +$ docker logs rfsim4g-db-init --follow +Connection error: ('Unable to connect to any servers', {'192.168.68.2': error(111, "Tried connecting to [('192.168.68.2', 9042)]. Last error: Connection refused")}) +... +Connection error: ('Unable to connect to any servers', {'192.168.68.2': error(111, "Tried connecting to [('192.168.68.2', 9042)]. Last error: Connection refused")}) +OK +``` + +**You SHALL wait until you HAVE the `OK` message in the logs!** + +```bash +$ docker rm rfsim4g-db-init +``` + +## 2.2. Deploy OAI CN4G containers ## + +```bash +$ docker-compose up -d oai_mme oai_spgwu trf_gen +rfsim4g-cassandra is up-to-date +Creating rfsim4g-trf-gen ... done +Creating rfsim4g-oai-hss ... done +Creating rfsim4g-oai-mme ... done +Creating rfsim4g-oai-spgwc ... done +Creating rfsim4g-oai-spgwu-tiny ... done +``` + +You shall wait until all containers are `healthy`. About 10 seconds! + +```bash +$ docker-compose ps -a + Name Command State Ports +------------------------------------------------------------------------------------------------------------------------- +rfsim4g-cassandra docker-entrypoint.sh cassa ... Up (healthy) 7000/tcp, 7001/tcp, 7199/tcp, 9042/tcp, 9160/tcp +rfsim4g-oai-hss /openair-hss/bin/entrypoin ... Up (healthy) 5868/tcp, 9042/tcp, 9080/tcp, 9081/tcp +rfsim4g-oai-mme /openair-mme/bin/entrypoin ... Up (healthy) 2123/udp, 3870/tcp, 5870/tcp +rfsim4g-oai-spgwc /openair-spgwc/bin/entrypo ... Up (healthy) 2123/udp, 8805/udp +rfsim4g-oai-spgwu-tiny /openair-spgwu-tiny/bin/en ... Up (healthy) 2152/udp, 8805/udp +rfsim4g-trf-gen /bin/bash -c ip route add ... Up (healthy) +``` + +## 2.3. Deploy OAI eNB in RF simulator mode ## + +```bash +$ docker-compose up -d enb +Creating rfsim4g-oai-enb ... done +``` + +Again wait for the healthy state: + +```bash +$ docker-compose ps -a + Name Command State Ports +------------------------------------------------------------------------------------------------------------------------- +rfsim4g-cassandra docker-entrypoint.sh cassa ... Up (healthy) 7000/tcp, 7001/tcp, 7199/tcp, 9042/tcp, 9160/tcp +rfsim4g-oai-enb /opt/oai-enb/bin/entrypoin ... Up (healthy) 2152/udp, 36412/udp, 36422/udp +rfsim4g-oai-hss /openair-hss/bin/entrypoin ... Up (healthy) 5868/tcp, 9042/tcp, 9080/tcp, 9081/tcp +rfsim4g-oai-mme /openair-mme/bin/entrypoin ... Up (healthy) 2123/udp, 3870/tcp, 5870/tcp +rfsim4g-oai-spgwc /openair-spgwc/bin/entrypo ... Up (healthy) 2123/udp, 8805/udp +rfsim4g-oai-spgwu-tiny /openair-spgwu-tiny/bin/en ... Up (healthy) 2152/udp, 8805/udp +rfsim4g-trf-gen /bin/bash -c ip route add ... Up (healthy) +``` + +Check if the eNB connected to MME: + +```bash +$ docker logs rfsim4g-oai-mme +... +DEBUG MME-AP src/mme_app/mme_app_statistics.c:0039 ======================================= STATISTICS ============================================ + +DEBUG MME-AP src/mme_app/mme_app_statistics.c:0042 | Current Status| Added since last display| Removed since last display | +DEBUG MME-AP src/mme_app/mme_app_statistics.c:0048 Connected eNBs | 0 | 0 | 0 | +DEBUG MME-AP src/mme_app/mme_app_statistics.c:0054 Attached UEs | 0 | 0 | 0 | +DEBUG MME-AP src/mme_app/mme_app_statistics.c:0060 Connected UEs | 0 | 0 | 0 | +DEBUG MME-AP src/mme_app/mme_app_statistics.c:0066 Default Bearers| 0 | 0 | 0 | +DEBUG MME-AP src/mme_app/mme_app_statistics.c:0072 S1-U Bearers | 0 | 0 | 0 | + +DEBUG MME-AP src/mme_app/mme_app_statistics.c:0075 ======================================= STATISTICS ============================================ + +DEBUG SCTP rc/sctp/sctp_primitives_server.c:0469 Client association changed: 0 +DEBUG SCTP enair-mme/src/sctp/sctp_common.c:0101 ---------------------- +DEBUG SCTP enair-mme/src/sctp/sctp_common.c:0102 SCTP Status: +DEBUG SCTP enair-mme/src/sctp/sctp_common.c:0103 assoc id .....: 675 +DEBUG SCTP enair-mme/src/sctp/sctp_common.c:0104 state ........: 4 +DEBUG SCTP enair-mme/src/sctp/sctp_common.c:0105 instrms ......: 2 +DEBUG SCTP enair-mme/src/sctp/sctp_common.c:0106 outstrms .....: 2 +DEBUG SCTP enair-mme/src/sctp/sctp_common.c:0108 fragmentation : 1452 +DEBUG SCTP enair-mme/src/sctp/sctp_common.c:0109 pending data .: 0 +DEBUG SCTP enair-mme/src/sctp/sctp_common.c:0110 unack data ...: 0 +DEBUG SCTP enair-mme/src/sctp/sctp_common.c:0111 rwnd .........: 106496 +DEBUG SCTP enair-mme/src/sctp/sctp_common.c:0112 peer info : +DEBUG SCTP enair-mme/src/sctp/sctp_common.c:0114 state ....: 2 +DEBUG SCTP enair-mme/src/sctp/sctp_common.c:0116 cwnd .....: 4380 +DEBUG SCTP enair-mme/src/sctp/sctp_common.c:0118 srtt .....: 0 +DEBUG SCTP enair-mme/src/sctp/sctp_common.c:0120 rto ......: 3000 +DEBUG SCTP enair-mme/src/sctp/sctp_common.c:0122 mtu ......: 1500 +DEBUG SCTP enair-mme/src/sctp/sctp_common.c:0123 ---------------------- +DEBUG SCTP rc/sctp/sctp_primitives_server.c:0479 New connection +DEBUG SCTP enair-mme/src/sctp/sctp_common.c:0205 ---------------------- +DEBUG SCTP enair-mme/src/sctp/sctp_common.c:0206 Local addresses: +DEBUG SCTP enair-mme/src/sctp/sctp_common.c:0217 - [192.168.61.3] +DEBUG SCTP enair-mme/src/sctp/sctp_common.c:0234 ---------------------- +DEBUG SCTP enair-mme/src/sctp/sctp_common.c:0151 ---------------------- +DEBUG SCTP enair-mme/src/sctp/sctp_common.c:0152 Peer addresses: +DEBUG SCTP enair-mme/src/sctp/sctp_common.c:0163 - [192.168.61.20] +DEBUG SCTP enair-mme/src/sctp/sctp_common.c:0178 ---------------------- +DEBUG SCTP rc/sctp/sctp_primitives_server.c:0554 SCTP RETURNING!! +DEBUG SCTP rc/sctp/sctp_primitives_server.c:0547 [675][44] Msg of length 51 received from port 36412, on stream 0, PPID 18 +DEBUG SCTP rc/sctp/sctp_primitives_server.c:0554 SCTP RETURNING!! +DEBUG S1AP mme/src/s1ap/s1ap_mme_handlers.c:2826 Create eNB context for assoc_id: 675 +DEBUG S1AP mme/src/s1ap/s1ap_mme_handlers.c:0361 S1-Setup-Request macroENB_ID.size 3 (should be 20) +DEBUG S1AP mme/src/s1ap/s1ap_mme_handlers.c:0321 New s1 setup request incoming from macro eNB id: 00e01 +DEBUG S1AP mme/src/s1ap/s1ap_mme_handlers.c:0423 Adding eNB to the list of served eNBs +DEBUG S1AP mme/src/s1ap/s1ap_mme_handlers.c:0438 Adding eNB id 3585 to the list of served eNBs +DEBUG SCTP rc/sctp/sctp_primitives_server.c:0283 [44][675] Sending buffer 0x7f9394009f90 of 27 bytes on stream 0 with ppid 18 +DEBUG SCTP rc/sctp/sctp_primitives_server.c:0296 Successfully sent 27 bytes on stream 0 +DEBUG MME-AP src/mme_app/mme_app_statistics.c:0039 ======================================= STATISTICS ============================================ + +DEBUG MME-AP src/mme_app/mme_app_statistics.c:0042 | Current Status| Added since last display| Removed since last display | +DEBUG MME-AP src/mme_app/mme_app_statistics.c:0048 Connected eNBs | 1 | 1 | 0 | +DEBUG MME-AP src/mme_app/mme_app_statistics.c:0054 Attached UEs | 0 | 0 | 0 | +DEBUG MME-AP src/mme_app/mme_app_statistics.c:0060 Connected UEs | 0 | 0 | 0 | +DEBUG MME-AP src/mme_app/mme_app_statistics.c:0066 Default Bearers| 0 | 0 | 0 | +DEBUG MME-AP src/mme_app/mme_app_statistics.c:0072 S1-U Bearers | 0 | 0 | 0 | + +DEBUG MME-AP src/mme_app/mme_app_statistics.c:0075 ======================================= STATISTICS ============================================ +... +``` + +## 2.4. Deploy OAI LTE UE in RF simulator mode ## + +```bash +$ docker-compose up -d oai_ue0 +Creating rfsim4g-oai-lte-ue0 ... done +``` + +Again a bit of patience: + +```bash +$ docker-compose ps -a + Name Command State Ports +------------------------------------------------------------------------------------------------------------------------- +rfsim4g-cassandra docker-entrypoint.sh cassa ... Up (healthy) 7000/tcp, 7001/tcp, 7199/tcp, 9042/tcp, 9160/tcp +rfsim4g-oai-enb /opt/oai-enb/bin/entrypoin ... Up (healthy) 2152/udp, 36412/udp, 36422/udp +rfsim4g-oai-hss /openair-hss/bin/entrypoin ... Up (healthy) 5868/tcp, 9042/tcp, 9080/tcp, 9081/tcp +rfsim4g-oai-lte-ue0 /opt/oai-lte-ue/bin/entryp ... Up (healthy) 10000/tcp +rfsim4g-oai-mme /openair-mme/bin/entrypoin ... Up (healthy) 2123/udp, 3870/tcp, 5870/tcp +rfsim4g-oai-spgwc /openair-spgwc/bin/entrypo ... Up (healthy) 2123/udp, 8805/udp +rfsim4g-oai-spgwu-tiny /openair-spgwu-tiny/bin/en ... Up (healthy) 2152/udp, 8805/udp +rfsim4g-trf-gen /bin/bash -c ip route add ... Up (healthy) +Creating rfsim4g-oai-enb ... done +``` + +Making sure the OAI UE is connected: + +```bash +$ docker logs rfsim4g-oai-enb +... +[RRC] RRCConnectionReconfiguration Encoded 1098 bits (138 bytes) +[RRC] [eNB 0] Frame 0, Logical Channel DL-DCCH, Generate LTE_RRCConnectionReconfiguration (bytes 138, UE id 617b) +[RRC] sent RRC_DCCH_DATA_REQ to TASK_PDCP_ENB +[PDCP] [FRAME 00000][eNB][MOD 00][RNTI 617b][SRB 02] Action ADD LCID 2 (SRB id 2) configured with SN size 5 bits and RLC AM +[PDCP] [FRAME 00000][eNB][MOD 00][RNTI 617b][DRB 01] Action ADD LCID 3 (DRB id 1) configured with SN size 12 bits and RLC AM +[SCTP] Successfully sent 46 bytes on stream 1 for assoc_id 676 +[RRC] [FRAME 00000][eNB][MOD 00][RNTI 617b] UE State = RRC_RECONFIGURED (default DRB, xid 0) +[PDCP] [FRAME 00000][eNB][MOD 00][RNTI 617b][SRB 02] Action MODIFY LCID 2 RB id 2 reconfigured with SN size 5 and RLC AM +[PDCP] [FRAME 00000][eNB][MOD 00][RNTI 617b][DRB 01] Action MODIFY LCID 3 RB id 1 reconfigured with SN size 1 and RLC AM +[RRC] [eNB 0] Frame 0 CC 0 : SRB2 is now active +[RRC] [eNB 0] Frame 0 : Logical Channel UL-DCCH, Received LTE_RRCConnectionReconfigurationComplete from UE rnti 617b, reconfiguring DRB 1/LCID 3 +[RRC] [eNB 0] Frame 0 : Logical Channel UL-DCCH, Received LTE_RRCConnectionReconfigurationComplete, reconfiguring DRB 1/LCID 3 +[MAC] UE 0 RNTI 617b adding LC 3 idx 2 to scheduling control (total 3) +[MAC] Added physicalConfigDedicated 0x7f98e0004950 for 0.0 +[S1AP] initial_ctxt_resp_p: e_rab ID 5, enb_addr 192.168.61.20, SIZE 4 +[SCTP] Successfully sent 40 bytes on stream 1 for assoc_id 676 +[SCTP] Successfully sent 61 bytes on stream 1 for assoc_id 676 +... +``` + +On the MME: + +```bash +$ docker logs rfsim4g-oai-mme +DEBUG MME-AP src/mme_app/mme_app_statistics.c:0039 ======================================= STATISTICS ============================================ + +DEBUG MME-AP src/mme_app/mme_app_statistics.c:0042 | Current Status| Added since last display| Removed since last display | +DEBUG MME-AP src/mme_app/mme_app_statistics.c:0048 Connected eNBs | 1 | 0 | 0 | +DEBUG MME-AP src/mme_app/mme_app_statistics.c:0054 Attached UEs | 1 | 0 | 0 | +DEBUG MME-AP src/mme_app/mme_app_statistics.c:0060 Connected UEs | 1 | 0 | 0 | +DEBUG MME-AP src/mme_app/mme_app_statistics.c:0066 Default Bearers| 0 | 0 | 0 | +DEBUG MME-AP src/mme_app/mme_app_statistics.c:0072 S1-U Bearers | 0 | 0 | 0 | + +DEBUG MME-AP src/mme_app/mme_app_statistics.c:0075 ======================================= STATISTICS ============================================ +``` + +On the LTE UE: + +```bash +$ docker exec rfsim4g-oai-lte-ue0 /bin/bash -c "ifconfig" +eth0: flags=4163 mtu 1500 + inet 192.168.61.30 netmask 255.255.255.192 broadcast 192.168.61.63 + ether 02:42:c0:a8:3d:1e txqueuelen 0 (Ethernet) + RX packets 1109931 bytes 8078031934 (8.0 GB) + RX errors 0 dropped 0 overruns 0 frame 0 + TX packets 1232068 bytes 7798928848 (7.7 GB) + TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 + +lo: flags=73 mtu 65536 + inet 127.0.0.1 netmask 255.0.0.0 + loop txqueuelen 1000 (Local Loopback) + RX packets 0 bytes 0 (0.0 B) + RX errors 0 dropped 0 overruns 0 frame 0 + TX packets 0 bytes 0 (0.0 B) + TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 + +oaitun_ue1: flags=4305 mtu 1500 + inet 12.0.0.2 netmask 255.0.0.0 destination 12.0.0.2 + unspec 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00 txqueuelen 500 (UNSPEC) + RX packets 0 bytes 0 (0.0 B) + RX errors 0 dropped 0 overruns 0 frame 0 + TX packets 0 bytes 0 (0.0 B) + TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 + +oaitun_uem1: flags=4305 mtu 1500 + inet 10.0.2.2 netmask 255.255.255.0 destination 10.0.2.2 + unspec 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00 txqueuelen 500 (UNSPEC) + RX packets 0 bytes 0 (0.0 B) + RX errors 0 dropped 0 overruns 0 frame 0 + TX packets 0 bytes 0 (0.0 B) + TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 +``` + +The tunnel `oaitun_ue1` SHALL be mounted and with an IP address in the `12.0.0.xxx` range. + +# 3. Check traffic # + +```bash +$ docker exec rfsim4g-oai-lte-ue0 /bin/bash -c "ping -c 2 www.lemonde.fr" +PING s2.shared.global.fastly.net (151.101.122.217) 56(84) bytes of data. +64 bytes from 151.101.122.217 (151.101.122.217): icmp_seq=1 ttl=54 time=12.9 ms +64 bytes from 151.101.122.217 (151.101.122.217): icmp_seq=2 ttl=54 time=12.9 ms + +--- s2.shared.global.fastly.net ping statistics --- +2 packets transmitted, 2 received, 0% packet loss, time 1001ms +rtt min/avg/max/mdev = 12.940/12.965/12.990/0.025 ms + +$ docker exec rfsim4g-oai-lte-ue0 /bin/bash -c "ping -I oaitun_ue1 -c 2 www.lemonde.fr" +PING s2.shared.global.fastly.net (151.101.122.217) from 12.0.0.2 oaitun_ue1: 56(84) bytes of data. +64 bytes from 151.101.122.217 (151.101.122.217): icmp_seq=1 ttl=53 time=23.6 ms +64 bytes from 151.101.122.217 (151.101.122.217): icmp_seq=2 ttl=53 time=29.5 ms + +--- s2.shared.global.fastly.net ping statistics --- +2 packets transmitted, 2 received, 0% packet loss, time 1001ms +rtt min/avg/max/mdev = 23.659/26.626/29.593/2.967 ms +``` + +The 1st ping command is NOT using the OAI stack. My network infrastructure has a response of `13 ms` to reach this website. + +The 2nd ping command is using the OAI stack. So the stack takes `26.6 - 12.9 = 13.7 ms`. + +# 4. Un-deployment # + +```bash +$ docker-compose down +Stopping rfsim4g-oai-lte-ue0 ... done +Stopping rfsim4g-oai-enb ... done +Stopping rfsim4g-oai-spgwu-tiny ... done +Stopping rfsim4g-oai-spgwc ... done +Stopping rfsim4g-oai-mme ... done +Stopping rfsim4g-oai-hss ... done +Stopping rfsim4g-trf-gen ... done +Stopping rfsim4g-cassandra ... done +Removing rfsim4g-oai-lte-ue0 ... done +Removing rfsim4g-oai-enb ... done +Removing rfsim4g-oai-spgwu-tiny ... done +Removing rfsim4g-oai-spgwc ... done +Removing rfsim4g-oai-mme ... done +Removing rfsim4g-oai-hss ... done +Removing rfsim4g-trf-gen ... done +Removing rfsim4g-cassandra ... done +Removing network rfsim4g-oai-private-net +Removing network rfsim4g-oai-public-net +``` + +# 5. Explanation on the configuration # + +With a single `docker-compose.yml` file, it is easier to explain how I made the full connection. + +Try to modify as little as possible. And if you don't understand a field/value, you'd better NOT modify it. + +## 5.1. UE IMSI and Keys ## + +in HSS config: + +```yaml + OP_KEY: 1006020f0a478bf6b699f15c062e42b3 + LTE_K: fec86ba6eb707ed08905757b1bb44b8f + APN1: oai.ipv4 + APN2: internet + FIRST_IMSI: 208960100000001 + NB_USERS: 10 +``` + +in UE config: + +```yaml + MCC: '208' + MNC: '96' + SHORT_IMSI: '0100000001' + LTE_KEY: 'fec86ba6eb707ed08905757b1bb44b8f' + OPC: 'c42449363bbad02b66d16bc975d77cc1' + MSISDN: '001011234561010' + HPLMN: 20896 +``` + +As you can see: `LTE_K` and `LTE_KEY` are the same value. And `OP_KEY` and `OPC` can be deduced from each other. Look in HSS logs. + +```bash +$ docker logs rfsim4g-oai-hss +... +Compute opc: + K: FEC86BA6EB707ED08905757B1BB44B8F <== `LTE_K` + In: 1006020F0A478BF6B699F15C062E42B3 <== `OP_KEY` + Rinj: D4224B3931FD5BDDD0489A9573F93E72 + Out: C42449363BBAD02B66D16BC975D77CC1 <== `OPC` +... +``` + +In HSS, I've provisioned 10 users starting at `208960100000001` (`FIRST_IMSI` and `NB_USERS`). + +My 1st UE IMSI is an aggregation of `MCC`, `MNC`, `SHORT_IMSI`. + +## 5.2. PLMN and TAI ## + +in MME config: + +```yaml + REALM: openairinterface.org +.. + MCC: '208' + MNC: '96' + MME_GID: 32768 + MME_CODE: 3 + TAC_0: 1 + TAC_1: 2 + TAC_2: 3 + MME_FQDN: mme.openairinterface.org +``` + +in SPGW-C/-U configs: + +```yaml + MCC: '208' + MNC: '96' + MNC03: '096' + TAC: 1 + GW_ID: 1 + REALM: openairinterface.org +``` + +in eNB config: + +```yaml + MCC: '208' + MNC: '96' + MNC_LENGTH: 2 + TAC: 1 +``` + +The values SHALL match, and `TAC` shall match `TAC_0` from MME. + +## 5.3. Access to Internet ## + +In my traffic test, I was able to ping outside of my local network. + +in SPGW-C config: + +```yaml + DEFAULT_DNS_IPV4_ADDRESS: 192.168.18.129 + DEFAULT_DNS_SEC_IPV4_ADDRESS: 8.8.4.4 + PUSH_PROTOCOL_OPTION: 'true' +``` + +in SPGW-U config: + +```yaml + NETWORK_UE_NAT_OPTION: 'yes' +``` + +Please put your own DNS server IP adress. + +And you may have to play with `PUSH_PROTOCOL_OPTION` and `NETWORK_UE_NAT_OPTION` depending on your network. + diff --git a/ci-scripts/yaml_files/4g_rfsimulator/docker-compose.yml b/ci-scripts/yaml_files/4g_rfsimulator/docker-compose.yml index d8be6679b1..fe8f450be3 100644 --- a/ci-scripts/yaml_files/4g_rfsimulator/docker-compose.yml +++ b/ci-scripts/yaml_files/4g_rfsimulator/docker-compose.yml @@ -32,7 +32,7 @@ services: entrypoint: /bin/bash -c "cqlsh --file /home/oai_db.cql 192.168.68.2 && echo 'OK'" oai_hss: - image: oai-hss:develop-2021-06-14 + image: oai-hss:latest container_name: rfsim4g-oai-hss privileged: true depends_on: [cassandra] @@ -59,7 +59,7 @@ services: retries: 5 oai_mme: - image: oai-mme:production + image: oai-mme:latest container_name: rfsim4g-oai-mme privileged: true depends_on: [oai_hss] @@ -116,7 +116,7 @@ services: retries: 5 oai_spgwc: - image: oai-spgwc:develop-2021-06-14 + image: oai-spgwc:latest privileged: true depends_on: [oai_mme] container_name: rfsim4g-oai-spgwc @@ -148,7 +148,7 @@ services: retries: 5 oai_spgwu: - image: oai-spgwu-tiny:develop-2021-06-14 + image: oai-spgwu-tiny:latest privileged: true container_name: rfsim4g-oai-spgwu-tiny depends_on: [oai_spgwc] @@ -177,19 +177,6 @@ services: timeout: 5s retries: 5 - flexran_rtc: - image: flexran-rtc:production - privileged: true - container_name: rfsim4g-flexran-rtc - networks: - public_net: - ipv4_address: 192.168.61.10 - healthcheck: - test: /bin/bash -c "pgrep rt_controller" - interval: 10s - timeout: 5s - retries: 5 - trf_gen: image: trf-gen:production privileged: true @@ -235,6 +222,11 @@ services: FLEXRAN_INTERFACE_NAME: eth0 FLEXRAN_IPV4_ADDRESS: 192.168.61.10 USE_ADDITIONAL_OPTIONS: --rfsim + healthcheck: + test: /bin/bash -c "pgrep lte-softmodem" + interval: 10s + timeout: 5s + retries: 5 oai_ue0: image: oai-lte-ue:develop @@ -257,6 +249,11 @@ services: MSISDN: '001011234561010' HPLMN: 20896 USE_ADDITIONAL_OPTIONS: --rfsim -C 2680000000 -r 25 --ue-rxgain 140 --ue-txgain 120 --nokrnmod 1 + healthcheck: + test: /bin/bash -c "pgrep lte-uesoftmodem" + interval: 10s + timeout: 5s + retries: 5 networks: private_net: From 3247e967ec7bf9b8de85e2b445b7270e52473e14 Mon Sep 17 00:00:00 2001 From: Raphael Defosseux Date: Wed, 4 Aug 2021 17:09:18 +0200 Subject: [PATCH 73/91] fix(docker): explicitely adding procps to target images Signed-off-by: Raphael Defosseux --- docker/Dockerfile.eNB.rhel8.2 | 1 + docker/Dockerfile.eNB.ubuntu18 | 1 + docker/Dockerfile.gNB.rhel8.2 | 1 + docker/Dockerfile.gNB.ubuntu18 | 1 + docker/Dockerfile.lteRU.rhel8.2 | 1 + docker/Dockerfile.lteRU.ubuntu18 | 1 + docker/Dockerfile.lteUE.rhel8.2 | 1 + docker/Dockerfile.lteUE.ubuntu18 | 1 + docker/Dockerfile.nrUE.rhel8.2 | 1 + docker/Dockerfile.nrUE.ubuntu18 | 1 + 10 files changed, 10 insertions(+) diff --git a/docker/Dockerfile.eNB.rhel8.2 b/docker/Dockerfile.eNB.rhel8.2 index cf012502e0..32d6796ec9 100644 --- a/docker/Dockerfile.eNB.rhel8.2 +++ b/docker/Dockerfile.eNB.rhel8.2 @@ -48,6 +48,7 @@ RUN yum update -y && \ yum install -y --enablerepo="ubi-8-codeready-builder" \ lksctp-tools \ nettle \ + procps-ng \ atlas \ net-tools \ iputils \ diff --git a/docker/Dockerfile.eNB.ubuntu18 b/docker/Dockerfile.eNB.ubuntu18 index 2954d3fb18..3ce4a98ce4 100644 --- a/docker/Dockerfile.eNB.ubuntu18 +++ b/docker/Dockerfile.eNB.ubuntu18 @@ -51,6 +51,7 @@ RUN apt-get update && \ DEBIAN_FRONTEND=noninteractive apt-get upgrade --yes && \ DEBIAN_FRONTEND=noninteractive apt-get install --yes \ software-properties-common \ + procps \ libsctp1 \ libnettle6 \ libblas3 \ diff --git a/docker/Dockerfile.gNB.rhel8.2 b/docker/Dockerfile.gNB.rhel8.2 index 248b154693..a81de04cbe 100644 --- a/docker/Dockerfile.gNB.rhel8.2 +++ b/docker/Dockerfile.gNB.rhel8.2 @@ -47,6 +47,7 @@ FROM registry.access.redhat.com/ubi8/ubi:latest as oai-gnb RUN yum repolist --disablerepo=* && \ yum update -y && \ yum install -y --enablerepo="ubi-8-codeready-builder" \ + procps-ng \ libXpm \ libX11 \ atlas \ diff --git a/docker/Dockerfile.gNB.ubuntu18 b/docker/Dockerfile.gNB.ubuntu18 index 3660baf79e..2fb569b74b 100644 --- a/docker/Dockerfile.gNB.ubuntu18 +++ b/docker/Dockerfile.gNB.ubuntu18 @@ -50,6 +50,7 @@ RUN apt-get update && \ DEBIAN_FRONTEND=noninteractive apt-get upgrade --yes && \ DEBIAN_FRONTEND=noninteractive apt-get install --yes \ software-properties-common \ + procps \ libsctp1 \ tzdata \ libnettle6 \ diff --git a/docker/Dockerfile.lteRU.rhel8.2 b/docker/Dockerfile.lteRU.rhel8.2 index 35078de007..e32325ea1b 100644 --- a/docker/Dockerfile.lteRU.rhel8.2 +++ b/docker/Dockerfile.lteRU.rhel8.2 @@ -48,6 +48,7 @@ ENV TZ=Europe/Paris RUN yum update -y && \ yum install -y --enablerepo="ubi-8-codeready-builder" \ tzdata \ + procps-ng \ atlas \ net-tools \ iputils \ diff --git a/docker/Dockerfile.lteRU.ubuntu18 b/docker/Dockerfile.lteRU.ubuntu18 index 381d63d9f3..1af5b52df4 100644 --- a/docker/Dockerfile.lteRU.ubuntu18 +++ b/docker/Dockerfile.lteRU.ubuntu18 @@ -50,6 +50,7 @@ RUN apt-get update && \ DEBIAN_FRONTEND=noninteractive apt-get upgrade --yes && \ DEBIAN_FRONTEND=noninteractive apt-get install --yes \ tzdata \ + procps \ software-properties-common \ libblas3 \ libatlas3-base \ diff --git a/docker/Dockerfile.lteUE.rhel8.2 b/docker/Dockerfile.lteUE.rhel8.2 index 731abed1a8..2d540876e3 100644 --- a/docker/Dockerfile.lteUE.rhel8.2 +++ b/docker/Dockerfile.lteUE.rhel8.2 @@ -48,6 +48,7 @@ FROM registry.access.redhat.com/ubi8/ubi:latest as oai-lte-ue RUN yum update -y && \ yum install -y --enablerepo="ubi-8-codeready-builder" \ lksctp-tools \ + procps-ng \ nettle \ atlas \ iproute \ diff --git a/docker/Dockerfile.lteUE.ubuntu18 b/docker/Dockerfile.lteUE.ubuntu18 index fcd16f0c15..c6a70a0b50 100644 --- a/docker/Dockerfile.lteUE.ubuntu18 +++ b/docker/Dockerfile.lteUE.ubuntu18 @@ -52,6 +52,7 @@ RUN apt-get update && \ DEBIAN_FRONTEND=noninteractive apt-get upgrade --yes && \ DEBIAN_FRONTEND=noninteractive apt-get install --yes \ software-properties-common \ + procps \ libsctp1 \ libnettle6 \ liblapacke \ diff --git a/docker/Dockerfile.nrUE.rhel8.2 b/docker/Dockerfile.nrUE.rhel8.2 index b71d0ed906..c8bea16801 100644 --- a/docker/Dockerfile.nrUE.rhel8.2 +++ b/docker/Dockerfile.nrUE.rhel8.2 @@ -49,6 +49,7 @@ FROM registry.access.redhat.com/ubi8/ubi:latest as oai-nr-ue RUN yum update -y && \ yum install -y --enablerepo="ubi-8-codeready-builder" \ lksctp-tools \ + procps-ng \ nettle \ net-tools \ iputils \ diff --git a/docker/Dockerfile.nrUE.ubuntu18 b/docker/Dockerfile.nrUE.ubuntu18 index c96bcf80ef..ee2160d579 100644 --- a/docker/Dockerfile.nrUE.ubuntu18 +++ b/docker/Dockerfile.nrUE.ubuntu18 @@ -54,6 +54,7 @@ RUN apt-get update && \ DEBIAN_FRONTEND=noninteractive apt-get install --yes \ software-properties-common \ libsctp1 \ + procps \ libnettle6 \ liblapacke \ libatlas3-base \ From 464520304b2243e51c4db06844e3aabb223df245 Mon Sep 17 00:00:00 2001 From: Laurent THOMAS Date: Thu, 5 Aug 2021 09:49:25 +0200 Subject: [PATCH 74/91] merge develop, make DNN, NSSAI configurable, fix infinite loop --- openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c | 7 +++++-- openair2/LAYER2/nr_rlc/nr_rlc_oai_api.c | 6 ++++-- openair3/UICC/usim_interface.c | 9 ++++++--- openair3/UICC/usim_interface.h | 3 +++ 4 files changed, 18 insertions(+), 7 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c index 8916555f18..d1056f30d2 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c @@ -2004,7 +2004,7 @@ nr_ue_get_sdu(module_id_t module_idP, int CC_id, frame_t frameP, buflen, sdu_length_total, total_rlc_pdu_header_len, buflen_remain); // ,nr_ue_mac_inst->scheduling_info.BSR_bytes[nr_ue_mac_inst->scheduling_info.LCGID[lcid]] - while(buflen_remain > 0 && lcid_buffer_occupancy_new){ + while(buflen_remain > MAX_RLC_SDU_SUBHEADER_SIZE && lcid_buffer_occupancy_new){ sdu_lengths[num_sdus] = mac_rlc_data_req(module_idP, mac->crnti, @@ -2034,7 +2034,10 @@ nr_ue_get_sdu(module_id_t module_idP, int CC_id, frame_t frameP, } /* Get updated BO after multiplexing this PDU */ - lcid_buffer_occupancy_new = mac_rlc_get_buffer_occupancy_ind(module_idP,mac->crnti,eNB_index,frameP, subframe, ENB_FLAG_NO, lcid); + // we don't recompute it if the waiting queue is much larger than our buffer + // because mac_rlc_get_buffer_occupancy_ind() cpu cost is high when waiting queu is large + if ( lcid_buffer_occupancy_new < buflen_remain+1000) + lcid_buffer_occupancy_new = mac_rlc_get_buffer_occupancy_ind(module_idP,mac->crnti,eNB_index,frameP, subframe, ENB_FLAG_NO, lcid); buflen_remain = buflen - (total_rlc_pdu_header_len + sdu_length_total + MAX_RLC_SDU_SUBHEADER_SIZE); } } diff --git a/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.c b/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.c index fb657bf5a8..e53eb94a7f 100644 --- a/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.c +++ b/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.c @@ -263,7 +263,8 @@ mac_rlc_status_resp_t mac_rlc_status_ind( * reports '> 81338368' (table 6.1.3.1-2). Passing 100000000 is thus * more than enough. */ - buf_stat = rb->buffer_status(rb, 100000000); + // Fix me: temproary reduction meanwhile cpu cost of this computation is optimized + buf_stat = rb->buffer_status(rb, 1000*1000); ret.bytes_in_buffer = buf_stat.status_size + buf_stat.retx_size + buf_stat.tx_size; @@ -326,7 +327,8 @@ rlc_buffer_occupancy_t mac_rlc_get_buffer_occupancy_ind( * more than enough. */ // Fixme : Laurent reduced size for CPU saving - buf_stat = rb->buffer_status(rb, 10000000); + // Fix me: temproary reduction meanwhile cpu cost of this computation is optimized + buf_stat = rb->buffer_status(rb, 1000*1000); ret = buf_stat.status_size + buf_stat.retx_size + buf_stat.tx_size; diff --git a/openair3/UICC/usim_interface.c b/openair3/UICC/usim_interface.c index 0973d75082..8cea3899b5 100644 --- a/openair3/UICC/usim_interface.c +++ b/openair3/UICC/usim_interface.c @@ -37,11 +37,14 @@ extern uint16_t NB_UE_INST; /*-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/ #define UICC_PARAMS_DESC {\ {"imsi", "USIM IMSI\n", 0, strptr:&(uicc->imsiStr), defstrval:"2089900007487", TYPE_STRING, 0 },\ - {"nmc_size" "number of digits in NMC", 0, iptr:&(uicc->nmc_size), defintval:2, TYPE_INT, 0 },\ + {"nmc_size" "number of digits in NMC", 0, iptr:&(uicc->nmc_size), defintval:2, TYPE_INT, 0 },\ {"key", "USIM Ki\n", 0, strptr:&(uicc->keyStr), defstrval:"fec86ba6eb707ed08905757b1bb44b8f", TYPE_STRING, 0 },\ {"opc", "USIM OPc\n", 0, strptr:&(uicc->opcStr), defstrval:"c42449363bbad02b66d16bc975d77cc1", TYPE_STRING, 0 },\ - {"amf", "USIM amf\n", 0, strptr:&(uicc->amfStr), defstrval:"8000", TYPE_STRING, 0 },\ - {"sqn", "USIM sqn\n", 0, strptr:&(uicc->sqnStr), defstrval:"000000", TYPE_STRING, 0 },\ + {"amf", "USIM amf\n", 0, strptr:&(uicc->amfStr), defstrval:"8000", TYPE_STRING, 0 },\ + {"sqn", "USIM sqn\n", 0, strptr:&(uicc->sqnStr), defstrval:"000000", TYPE_STRING, 0 },\ + {"dnn", "UE dnn (apn)\n", 0, strptr:&(uicc->dnnStr), defstrval:"oai", TYPE_STRING, 0 },\ + {"nssai_st", "UE nssai\n", 0, iptr:&(uicc->nssai_st), defintval:1, TYPE_INT, 0 }, \ + {"nssai_sd", "UE nssai\n", 0, iptr:&(uicc->nssai_sd), defintval:1, TYPE_INT, 0 }, \ }; static uicc_t** uiccArray=NULL; diff --git a/openair3/UICC/usim_interface.h b/openair3/UICC/usim_interface.h index 44c27c772e..27bab1e35e 100644 --- a/openair3/UICC/usim_interface.h +++ b/openair3/UICC/usim_interface.h @@ -49,6 +49,9 @@ typedef struct { char *opcStr; char *amfStr; char *sqnStr; + char *dnnStr; + int nssai_st; + int nssai_sd; uint8_t key[16]; uint8_t opc[16]; uint8_t amf[2]; From fadbdd3671ccc133321349e18af43405b69fb789 Mon Sep 17 00:00:00 2001 From: Laurent THOMAS Date: Thu, 5 Aug 2021 10:02:36 +0200 Subject: [PATCH 75/91] pdusession id fix: different values for UL and DL --- openair2/COMMON/gtpv1_u_messages_types.h | 1 + openair2/RRC/NR/rrc_gNB.c | 1 + openair2/RRC/NR/rrc_gNB_NGAP.c | 2 ++ openair3/ocp-gtpu/gtp_itf.cpp | 2 +- 4 files changed, 5 insertions(+), 1 deletion(-) diff --git a/openair2/COMMON/gtpv1_u_messages_types.h b/openair2/COMMON/gtpv1_u_messages_types.h index 75df3253f6..3c82076510 100644 --- a/openair2/COMMON/gtpv1_u_messages_types.h +++ b/openair2/COMMON/gtpv1_u_messages_types.h @@ -191,6 +191,7 @@ typedef struct gtpv1u_gnb_create_tunnel_req_s { int num_tunnels; teid_t upf_NGu_teid[NR_GTPV1U_MAX_BEARERS_PER_UE]; ///< Tunnel Endpoint Identifier pdusessionid_t pdusession_id[NR_GTPV1U_MAX_BEARERS_PER_UE]; + ebi_t incoming_rb_id[NR_GTPV1U_MAX_BEARERS_PER_UE]; transport_layer_addr_t upf_addr[NR_GTPV1U_MAX_BEARERS_PER_UE]; } gtpv1u_gnb_create_tunnel_req_t; diff --git a/openair2/RRC/NR/rrc_gNB.c b/openair2/RRC/NR/rrc_gNB.c index 6ef8149bb1..e31ea37336 100755 --- a/openair2/RRC/NR/rrc_gNB.c +++ b/openair2/RRC/NR/rrc_gNB.c @@ -1643,6 +1643,7 @@ rrc_gNB_process_RRCConnectionReestablishmentComplete( for ( j = 0, i = 0; i < NB_RB_MAX; i++) { if (ue_context_pP->ue_context.pduSession[i].status == PDU_SESSION_STATUS_ESTABLISHED || ue_context_pP->ue_context.pduSession[i].status == PDU_SESSION_STATUS_DONE) { create_tunnel_req.pdusession_id[j] = ue_context_pP->ue_context.pduSession[i].param.pdusession_id; + create_tunnel_req.incoming_rb_id[j] = i+1; create_tunnel_req.upf_NGu_teid[j] = ue_context_pP->ue_context.pduSession[i].param.gtp_teid; memcpy(create_tunnel_req.upf_addr[j].buffer, ue_context_pP->ue_context.pduSession[i].param.upf_addr.buffer, diff --git a/openair2/RRC/NR/rrc_gNB_NGAP.c b/openair2/RRC/NR/rrc_gNB_NGAP.c index b7f9d2c671..30c3f2f996 100644 --- a/openair2/RRC/NR/rrc_gNB_NGAP.c +++ b/openair2/RRC/NR/rrc_gNB_NGAP.c @@ -542,6 +542,7 @@ rrc_gNB_process_NGAP_INITIAL_CONTEXT_SETUP_REQ( ue_context_p->ue_context.pduSession[i].status = PDU_SESSION_STATUS_NEW; ue_context_p->ue_context.pduSession[i].param = NGAP_INITIAL_CONTEXT_SETUP_REQ (msg_p).pdusession_param[pdu_sessions_done]; create_tunnel_req.pdusession_id[pdu_sessions_done] = NGAP_INITIAL_CONTEXT_SETUP_REQ (msg_p).pdusession_param[pdu_sessions_done].pdusession_id; + create_tunnel_req.incoming_rb_id[pdu_sessions_done] = i+1; create_tunnel_req.upf_NGu_teid[pdu_sessions_done] = NGAP_INITIAL_CONTEXT_SETUP_REQ (msg_p).pdusession_param[pdu_sessions_done].gtp_teid; create_tunnel_req.upf_addr[pdu_sessions_done].length = NGAP_INITIAL_CONTEXT_SETUP_REQ (msg_p).pdusession_param[pdu_sessions_done].upf_addr.length; memcpy(create_tunnel_req.upf_addr[pdu_sessions_done].buffer, @@ -1064,6 +1065,7 @@ rrc_gNB_process_NGAP_PDUSESSION_SETUP_REQ( ue_context_p->ue_context.pduSession[i].status = PDU_SESSION_STATUS_NEW; ue_context_p->ue_context.pduSession[i].param = NGAP_PDUSESSION_SETUP_REQ(msg_p).pdusession_setup_params[pdu_sessions_done]; create_tunnel_req.pdusession_id[pdu_sessions_done] = NGAP_PDUSESSION_SETUP_REQ(msg_p).pdusession_setup_params[pdu_sessions_done].pdusession_id; + create_tunnel_req.incoming_rb_id[pdu_sessions_done]= i+1; create_tunnel_req.upf_NGu_teid[pdu_sessions_done] = NGAP_PDUSESSION_SETUP_REQ(msg_p).pdusession_setup_params[pdu_sessions_done].gtp_teid; memcpy(create_tunnel_req.upf_addr[pdu_sessions_done].buffer, NGAP_PDUSESSION_SETUP_REQ(msg_p).pdusession_setup_params[pdu_sessions_done].upf_addr.buffer, diff --git a/openair3/ocp-gtpu/gtp_itf.cpp b/openair3/ocp-gtpu/gtp_itf.cpp index e12a4d66a8..c367374436 100644 --- a/openair3/ocp-gtpu/gtp_itf.cpp +++ b/openair3/ocp-gtpu/gtp_itf.cpp @@ -528,7 +528,7 @@ int gtpv1u_create_ngu_tunnel( const instance_t instance, for (int i = 0; i < create_tunnel_req->num_tunnels; i++) { teid_t teid=newGtpuCreateTunnel(compatInst(instance), create_tunnel_req->rnti, - create_tunnel_req->pdusession_id[i], + create_tunnel_req->incoming_rb_id[i], create_tunnel_req->pdusession_id[i], create_tunnel_req->upf_NGu_teid[i], create_tunnel_req->upf_addr[i], 2152, From 4db87599bf75ffb36b4696230ffee782668eee2f Mon Sep 17 00:00:00 2001 From: Raphael Defosseux Date: Thu, 5 Aug 2021 10:40:01 +0200 Subject: [PATCH 76/91] doc(ci): how to properly capture control packets also added how to pull RAN images Signed-off-by: Raphael Defosseux --- .../yaml_files/4g_rfsimulator/README.md | 25 +++++++++++++++++-- .../4g_rfsimulator/docker-compose.yml | 5 +++- 2 files changed, 27 insertions(+), 3 deletions(-) diff --git a/ci-scripts/yaml_files/4g_rfsimulator/README.md b/ci-scripts/yaml_files/4g_rfsimulator/README.md index 49ccc6bd28..a677c642f4 100644 --- a/ci-scripts/yaml_files/4g_rfsimulator/README.md +++ b/ci-scripts/yaml_files/4g_rfsimulator/README.md @@ -52,6 +52,9 @@ $ docker pull rdefosseoai/oai-hss:latest $ docker pull rdefosseoai/oai-mme:latest $ docker pull rdefosseoai/oai-spgwc:latest $ docker pull rdefosseoai/oai-spgwu-tiny:latest + +$ docker pull rdefosseoai/oai-enb:develop +$ docker pull rdefosseoai/oai-lte-ue:develop ``` And **re-tag** them for tutorials' docker-compose file to work. @@ -61,6 +64,9 @@ $ docker image tag rdefosseoai/oai-spgwc:latest oai-spgwc:latest $ docker image tag rdefosseoai/oai-hss:latest oai-hss:latest $ docker image tag rdefosseoai/oai-spgwu-tiny:latest oai-spgwu-tiny:latest $ docker image tag rdefosseoai/oai-mme:latest oai-mme:latest + +$ docker image tag rdefosseoai/oai-enb:develop oai-enb:develop +$ docker image tag rdefosseoai/oai-lte-ue:develop oai-lte-ue:develop ``` ```bash @@ -69,8 +75,6 @@ $ docker logout How to build the Traffic-Generator image is explained [here](https://github.com/OPENAIRINTERFACE/openair-epc-fed/blob/master/docs/GENERATE_TRAFFIC.md#1-build-a-traffic-generator-image). -I will soon push also RAN images. - # 2. Deploy containers # **CAUTION: this SHALL be done in multiple steps.** @@ -101,6 +105,23 @@ OK $ docker rm rfsim4g-db-init ``` +At this point, you can prepare a capture on the newly-created public docker bridge: + +```bash +$ ifconfig rfsim4g-public + inet 192.168.61.1 netmask 255.255.255.192 broadcast 192.168.61.63 + ether 02:42:8f:dd:ba:5a txqueuelen 0 (Ethernet) + RX packets 0 bytes 0 (0.0 B) + RX errors 0 dropped 0 overruns 0 frame 0 + TX packets 0 bytes 0 (0.0 B) + TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 +$ sudo tshark -i rfsim4g-public -f 'port 3868 or port 2123 or port 36412 or port 36422 or port 46520 or port 8805' -w /tmp/my-oai-control-plane.pcap +``` + +**BE CAREFUL: please use that filter or you will also capture the data-plane with IQ samples between `eNB` and `LTE-UE`.** + +**and your capture WILL become huge (10s of Gbytes).** + ## 2.2. Deploy OAI CN4G containers ## ```bash diff --git a/ci-scripts/yaml_files/4g_rfsimulator/docker-compose.yml b/ci-scripts/yaml_files/4g_rfsimulator/docker-compose.yml index fe8f450be3..32e4bd41e8 100644 --- a/ci-scripts/yaml_files/4g_rfsimulator/docker-compose.yml +++ b/ci-scripts/yaml_files/4g_rfsimulator/docker-compose.yml @@ -261,9 +261,12 @@ networks: ipam: config: - subnet: 192.168.68.0/26 + driver_opts: + com.docker.network.bridge.name: "rfsim4g-private" public_net: name: rfsim4g-oai-public-net ipam: config: - subnet: 192.168.61.0/26 - + driver_opts: + com.docker.network.bridge.name: "rfsim4g-public" From 7e158447bb49369cafecfbb8fd7b0bef49e3f741 Mon Sep 17 00:00:00 2001 From: Raphael Defosseux Date: Thu, 5 Aug 2021 12:04:03 +0200 Subject: [PATCH 77/91] fix(ci): phy-sim build failure not correctly handled Signed-off-by: Raphael Defosseux --- ci-scripts/main.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ci-scripts/main.py b/ci-scripts/main.py index 3811162f01..f6177cde49 100644 --- a/ci-scripts/main.py +++ b/ci-scripts/main.py @@ -799,7 +799,8 @@ elif re.match('^TesteNB$', mode, re.IGNORECASE) or re.match('^TestUE$', mode, re CiTestObj.Perform_X2_Handover(HTML,RAN,EPC) elif action == 'Build_PhySim': HTML=ldpc.Build_PhySim(HTML,CONST) - if ldpc.exitStatus==1:sys.exit() + if ldpc.exitStatus==1: + RAN.prematureExit = False elif action == 'Run_PhySim': HTML=ldpc.Run_PhySim(HTML,CONST,id) elif action == 'Build_Image': From 74c5816c72d5f975e02d48a660151e44df572278 Mon Sep 17 00:00:00 2001 From: Rahul Gottipati Date: Thu, 5 Aug 2021 17:30:12 +0530 Subject: [PATCH 78/91] VNF clock dependency removed --- executables/nr-gnb.c | 6 +- nfapi/oai_integration/nfapi_pnf.c | 62 +++++++------------ nfapi/oai_integration/nfapi_pnf.h | 2 +- nfapi/oai_integration/nfapi_vnf.c | 44 ++++++++++++- .../nfapi/public_inc/nfapi_nr_interface_scf.h | 1 + nfapi/open-nFAPI/nfapi/src/nfapi_p7.c | 45 +++++++++++++- nfapi/open-nFAPI/pnf/src/pnf_p7.c | 33 +++++----- nfapi/open-nFAPI/pnf/src/pnf_p7_interface.c | 12 ++++ nfapi/open-nFAPI/vnf/inc/vnf_p7.h | 1 - .../vnf/public_inc/nfapi_vnf_interface.h | 2 +- nfapi/open-nFAPI/vnf/src/vnf_p7.c | 31 +++++++++- nfapi/open-nFAPI/vnf/src/vnf_p7_interface.c | 22 +++---- openair1/PHY/NR_TRANSPORT/nr_dlsch_coding.c | 2 +- openair1/SCHED_NR/fapi_nr_l1.c | 2 +- openair1/SCHED_NR/phy_procedures_nr_gNB.c | 2 +- openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c | 2 +- .../LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c | 5 -- .../LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c | 3 - openair2/NR_PHY_INTERFACE/NR_IF_Module.c | 2 +- 19 files changed, 186 insertions(+), 93 deletions(-) diff --git a/executables/nr-gnb.c b/executables/nr-gnb.c index dbf5fb8fb2..de24bb9136 100644 --- a/executables/nr-gnb.c +++ b/executables/nr-gnb.c @@ -142,16 +142,16 @@ void rx_func(void *param) { int slot_tx = info->slot_tx; sl_ahead = sf_ahead*gNB->frame_parms.slots_per_subframe; nfapi_nr_config_request_scf_t *cfg = &gNB->gNB_config; - + LOG_I(PHY,"slot rx %d \n", slot_rx); start_meas(&softmodem_stats_rxtx_sf); // ******************************************************************* if (NFAPI_MODE == NFAPI_MODE_PNF) { // I am a PNF and I need to let nFAPI know that we have a (sub)frame tick - //LOG_D(PHY, "oai_slot_ind(frame:%u, slot:%d) ********\n", frame_rx, slot_rx); + //LOG_D(PHY, "oai_nfapi_slot_ind(frame:%u, slot:%d) ********\n", frame_rx, slot_rx); start_meas(&nfapi_meas); - oai_slot_ind(frame_rx, slot_rx); + handle_nr_slot_ind(frame_rx, slot_rx); stop_meas(&nfapi_meas); /*if (gNB->UL_INFO.rx_ind.rx_indication_body.number_of_pdus|| diff --git a/nfapi/oai_integration/nfapi_pnf.c b/nfapi/oai_integration/nfapi_pnf.c index da8912e6a9..520a5dc578 100644 --- a/nfapi/oai_integration/nfapi_pnf.c +++ b/nfapi/oai_integration/nfapi_pnf.c @@ -2304,50 +2304,24 @@ void oai_subframe_ind(uint16_t sfn, uint16_t sf) { } } +void handle_nr_slot_ind(uint16_t sfn, uint16_t slot) { -long shift_ns,prev_ts_nsec,shift_us; -void oai_slot_ind(uint16_t sfn, uint16_t slot) { - - //slow down PNF - - LOG_D(PHY,"%s(sfn:%d, slot:%d)\n", __FUNCTION__, sfn, slot); - struct timespec ts; - clock_gettime(CLOCK_MONOTONIC, &ts); - - // if (!(sfn == 0 && slot == 0) && ts.tv_nsec > prev_ts_nsec){ - // shift_ns = ts.tv_nsec - prev_ts_nsec; - // shift_us = shift_ns/1000; - // printf("previous: %d, current: %d, shift: %d", prev_ts_nsec, ts.tv_nsec, shift_us); - // if(500-shift_us > 0) - // usleep(500-shift_us); - // // usleep(50); - // } - prev_ts_nsec = ts.tv_nsec; - - -//NFAPI_TRACE(NFAPI_TRACE_INFO, "[PNF] %s %d.%d (sfn:%u slot:%u) SFN/SLOT(TX):%u\n", __FUNCTION__, ts.tv_sec, ts.tv_nsec, sfn, slot, NFAPI_SFNSLOT2DEC(sfn, slot)); - //TODO FIXME - HACK - DJP - using a global to bodge it in - if (p7_config_g != NULL && sync_var==0) { - // DONE: changed for NR x x x x x x x x x x x x x x - - - - - - : x (Frame), - (Slot) (max_numer =2) - uint16_t sfn_slot_tx = sfn<<6 | slot; - // if ((sfn % 100 == 0) && slot==0) { // DOUBT: Why 100? - // struct timespec ts; - // clock_gettime(CLOCK_MONOTONIC, &ts); - // NFAPI_TRACE(NFAPI_TRACE_INFO, "[PNF] %s %d.%d (sfn:%u slot:%u) SFN/SLOT(TX):%u\n", __FUNCTION__, ts.tv_sec, ts.tv_nsec, sfn, slot, NFAPI_SFNSLOT2DEC(sfn, slot)); - // } - - //TODO: send p7_config instead of p7_config_g + //send VNF slot indication, which is aligned with TX thread, so that it can call the scheduler + nfapi_nr_slot_indication_scf_t *ind; + ind = (nfapi_nr_slot_indication_scf_t *) malloc(sizeof(nfapi_nr_slot_indication_scf_t)); + uint8_t slot_ahead = 6; + uint32_t sfn_slot_tx = sfnslot_add_slot(sfn, slot, slot_ahead); + uint16_t sfn_tx = NFAPI_SFNSLOT2SFN(sfn_slot_tx); + uint8_t slot_tx = NFAPI_SFNSLOT2SLOT(sfn_slot_tx); + + ind->sfn = sfn_tx; + ind->slot = slot_tx; + oai_nfapi_nr_slot_indication(ind); + + //copy data from appropriate p7 slot buffers into channel structures for PHY processing int slot_ret = nfapi_pnf_p7_slot_ind(p7_config_g, p7_config_g->phy_id, sfn, slot); - // if (subframe_ret) { - if (slot_ret) { - NFAPI_TRACE(NFAPI_TRACE_INFO, "[PNF] %s(frame:%u slot:%u) SFN/SLOT(TX):%u - PROBLEM with pnf_p7_slot_ind()\n", __FUNCTION__, sfn, slot, sfn_slot_tx, NFAPI_SFNSLOT2DEC(sfn, slot)); - // printing anything causes error: probably because there isn't enough time to accomodate a print statement - } else { - //NFAPI_TRACE(NFAPI_TRACE_INFO, "***NFAPI subframe handler finished *** \n"); - } - } else { - } + return; } int oai_nfapi_rach_ind(nfapi_rach_indication_t *rach_ind) { @@ -2401,6 +2375,12 @@ int oai_nfapi_sr_indication(nfapi_sr_indication_t *ind) { //NR UPLINK INDICATION +int oai_nfapi_nr_slot_indication(nfapi_nr_slot_indication_scf_t *ind) { + ind->header.phy_id = 1; + ind->header.message_id = NFAPI_NR_PHY_MSG_TYPE_SLOT_INDICATION; + return nfapi_pnf_p7_nr_slot_ind(p7_config_g, ind); +} + int oai_nfapi_nr_rx_data_indication(nfapi_nr_rx_data_indication_t *ind) { ind->header.phy_id = 1; // DJP HACK TODO FIXME - need to pass this around!!!! ind->header.message_id = NFAPI_NR_PHY_MSG_TYPE_RX_DATA_INDICATION; diff --git a/nfapi/oai_integration/nfapi_pnf.h b/nfapi/oai_integration/nfapi_pnf.h index 61d4847eba..463bd42692 100644 --- a/nfapi/oai_integration/nfapi_pnf.h +++ b/nfapi/oai_integration/nfapi_pnf.h @@ -27,5 +27,5 @@ void configure_nfapi_pnf(char *vnf_ip_addr, int vnf_p5_port, char *pnf_ip_addr, 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 oai_subframe_ind(uint16_t sfn, uint16_t sf); -void oai_slot_ind(uint16_t sfn, uint16_t slot); +void handle_nr_slot_ind(uint16_t sfn, uint16_t slot); #endif diff --git a/nfapi/oai_integration/nfapi_vnf.c b/nfapi/oai_integration/nfapi_vnf.c index 1bc2f70d93..8c8a19e883 100644 --- a/nfapi/oai_integration/nfapi_vnf.c +++ b/nfapi/oai_integration/nfapi_vnf.c @@ -33,10 +33,10 @@ #include "nfapi_nr_interface_scf.h" #include "nfapi_vnf_interface.h" +#include "nfapi_vnf.h" #include "nfapi.h" #include "vendor_ext.h" -#include "nfapi_vnf.h" #include "PHY/defs_eNB.h" #include "PHY/LTE_TRANSPORT/transport_proto.h" #include "openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h" @@ -1014,8 +1014,47 @@ int phy_cqi_indication(struct nfapi_vnf_p7_config *config, nfapi_cqi_indication_ return 1; } +// void add_slot(uint16_t *frameP, uint16_t *slotP, int offset) +// { +// uint16_t num_slots = 20; // set based on numerlogy (fixing for 1) + +// *frameP = (*frameP + ((*slotP + offset) / num_slots))%1024; + +// *slotP = ((*slotP + offset) % num_slots); +// } + +// uint32_t sfnslot_add_slot(uint16_t sfn, uint16_t slot, int offset) +// { +// uint32_t new_sfnslot; +// // uint16_t sfn = NFAPI_SFNSLOT2SFN(sfnslot); +// // uint16_t slot = NFAPI_SFNSLOT2SLOT(sfnslot); + +// //printf("%s() sfn:%u sf:%u\n", __FUNCTION__, sfn, sf); +// add_slot(&sfn, &slot, offset); + +// new_sfnslot = sfn<<6|slot; + +// //printf("%s() sfn:%u sf:%u offset:%d sfnsf:%d(DEC:%d) new:%d(DEC:%d)\n", __FUNCTION__, sfn, sf, offset, sfnsf, NFAPI_SFNSF2DEC(sfnsf), new_sfnsf, NFAPI_SFNSF2DEC(new_sfnsf)); + +// return new_sfnslot; +// } + //NR phy indication +int phy_nr_slot_indication(nfapi_nr_slot_indication_scf_t *ind) { + + uint8_t vnf_slot_ahead = 2; + uint32_t vnf_sfn_slot = sfnslot_add_slot(ind->sfn, ind->slot, vnf_slot_ahead); + uint16_t vnf_sfn = NFAPI_SFNSLOT2SFN(vnf_sfn_slot); + uint8_t vnf_slot = NFAPI_SFNSLOT2SLOT(vnf_sfn_slot); //offsetting the vnf from pnf by vnf_slot_head slots + struct PHY_VARS_gNB_s *gNB = RC.gNB[0]; + pthread_mutex_lock(&gNB->UL_INFO_mutex); + gNB->UL_INFO.frame = vnf_sfn; + gNB->UL_INFO.slot = vnf_slot; + pthread_mutex_unlock(&gNB->UL_INFO_mutex); + LOG_D(MAC, "VNF SFN/Slot %d.%d \n", gNB->UL_INFO.frame, gNB->UL_INFO.slot); +} + int phy_nr_crc_indication(nfapi_nr_crc_indication_t *ind) { struct PHY_VARS_gNB_s *gNB = RC.gNB[0]; pthread_mutex_lock(&gNB->UL_INFO_mutex); @@ -1282,6 +1321,7 @@ void *vnf_nr_p7_thread_start(void *ptr) { p7_vnf->config->nb_harq_indication = &phy_nb_harq_indication; p7_vnf->config->nrach_indication = &phy_nrach_indication; p7_vnf->config->nr_crc_indication = &phy_nr_crc_indication; + p7_vnf->config->nr_slot_indication = &phy_nr_slot_indication; p7_vnf->config->nr_rx_data_indication = &phy_nr_rx_data_indication; p7_vnf->config->nr_uci_indication = &phy_nr_uci_indication; p7_vnf->config->nr_rach_indication = &phy_nr_rach_indication; @@ -1739,7 +1779,7 @@ int oai_nfapi_dl_tti_req(nfapi_nr_dl_tti_request_t *dl_config_req) //LOG_I(PHY, "sfn:%d,slot:%d\n",dl_config_req->SFN,dl_config_req->Slot); //printf("\nEntering oai_nfapi_nr_dl_config_req sfn:%d,slot:%d\n",dl_config_req->SFN,dl_config_req->Slot); nfapi_vnf_p7_config_t *p7_config = vnf.p7_vnfs[0].config; - dl_config_req->header.message_id= NFAPI_NR_PHY_MSG_TYPE_DL_TTI_REQUEST; + 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 = nfapi_vnf_p7_nr_dl_config_req(p7_config, dl_config_req); 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 faa30582dc..9c3dd6fd8f 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 @@ -673,6 +673,7 @@ typedef struct { #define NFAPI_NR_SLOT_INDICATION_PERIOD_NUMEROLOGY_3 125 //us typedef struct { + nfapi_p7_message_header_t header; uint16_t sfn; //0->1023 uint16_t slot;//0->319 diff --git a/nfapi/open-nFAPI/nfapi/src/nfapi_p7.c b/nfapi/open-nFAPI/nfapi/src/nfapi_p7.c index e18aa7fda2..c25e6bc11c 100755 --- a/nfapi/open-nFAPI/nfapi/src/nfapi_p7.c +++ b/nfapi/open-nFAPI/nfapi/src/nfapi_p7.c @@ -3355,6 +3355,20 @@ static uint8_t pack_nr_timing_info(void *msg, uint8_t **ppWritePackedMsg, uint8_ //NR UPLINK indication function packing +//SLOT INDICATION + +static uint8_t pack_nr_slot_indication(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) +{ + nfapi_nr_slot_indication_scf_t *pNfapiMsg = (nfapi_nr_slot_indication_scf_t*)msg; + + if (!(push16((uint16_t)pNfapiMsg->sfn , ppWritePackedMsg, end) && + push16((uint16_t)pNfapiMsg->slot , ppWritePackedMsg, end) + )) + return 0; + +return 1; +} + //RX DATA INDICATION static uint8_t pack_nr_rx_data_indication_body(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) @@ -3696,18 +3710,19 @@ int nfapi_nr_p7_message_pack(void *pMessageBuf, void *pPackedBuf, uint32_t packe // look for the specific message uint8_t result = 0; switch (pMessageHeader->message_id) - { + { case NFAPI_NR_PHY_MSG_TYPE_DL_TTI_REQUEST: result = pack_dl_tti_request(pMessageHeader, &pWritePackedMessage, end, config); - //printf("result of pack dl_tti_req is %d. \n",result); break; case NFAPI_NR_PHY_MSG_TYPE_UL_TTI_REQUEST: result = pack_ul_tti_request(pMessageHeader, &pWritePackedMessage, end, config); break; + case NFAPI_NR_PHY_MSG_TYPE_TX_DATA_REQUEST: result = pack_tx_data_request(pMessageHeader, &pWritePackedMessage, end, config); break; + case NFAPI_NR_PHY_MSG_TYPE_UL_DCI_REQUEST: result = pack_ul_dci_request(pMessageHeader, &pWritePackedMessage, end, config); break; @@ -3720,6 +3735,9 @@ int nfapi_nr_p7_message_pack(void *pMessageBuf, void *pPackedBuf, uint32_t packe result =pack_ue_release_response(pMessageHeader, &pWritePackedMessage, end, config); break; + case NFAPI_NR_PHY_MSG_TYPE_SLOT_INDICATION: + result = pack_nr_slot_indication(pMessageHeader, &pWritePackedMessage, end, config); + case NFAPI_NR_PHY_MSG_TYPE_RX_DATA_INDICATION: result = pack_nr_rx_data_indication(pMessageHeader, &pWritePackedMessage, end, config); break; @@ -6350,6 +6368,21 @@ static uint8_t unpack_tx_request(uint8_t **ppReadPackedMsg, uint8_t *end, void * //UNPACK NR UPLINK INDICATION FUNCTIONS +//SLOT INDICATION + +static uint8_t unpack_nr_slot_indication(uint8_t **ppReadPackedMsg, uint8_t *end, nfapi_nr_rx_data_indication_t *msg, nfapi_p7_codec_config_t* config) +{ + nfapi_nr_slot_indication_scf_t *pNfapiMsg = (nfapi_nr_slot_indication_scf_t*)msg; + + printf("\n"); + if (!(pull16(ppReadPackedMsg, &pNfapiMsg->sfn , end) && + pull16(ppReadPackedMsg, &pNfapiMsg->slot , end) + )) + return 0; + +return 1; +} + //RX DATA INDICATION static uint8_t unpack_nr_rx_data_indication_body(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end) @@ -8707,6 +8740,14 @@ int nfapi_nr_p7_message_unpack(void *pMessageBuf, uint32_t messageBufLen, void * else return -1; break; + case NFAPI_NR_PHY_MSG_TYPE_SLOT_INDICATION: + if (check_nr_unpack_length(NFAPI_NR_PHY_MSG_TYPE_SLOT_INDICATION, unpackedBufLen)){ + nfapi_nr_slot_indication_scf_t* msg = (nfapi_nr_slot_indication_scf_t*) pMessageHeader; + result = unpack_nr_slot_indication(&pReadPackedMessage, end, msg, config); + } + else + return -1; + break; case NFAPI_NR_PHY_MSG_TYPE_RX_DATA_INDICATION: if (check_nr_unpack_length(NFAPI_NR_PHY_MSG_TYPE_RX_DATA_INDICATION, unpackedBufLen)){ diff --git a/nfapi/open-nFAPI/pnf/src/pnf_p7.c b/nfapi/open-nFAPI/pnf/src/pnf_p7.c index 0b75d3c7ec..c04285c62e 100644 --- a/nfapi/open-nFAPI/pnf/src/pnf_p7.c +++ b/nfapi/open-nFAPI/pnf/src/pnf_p7.c @@ -940,11 +940,11 @@ int pnf_p7_slot_ind(pnf_p7_t* pnf_p7, uint16_t phy_id, uint16_t sfn, uint16_t sl //We align the pnf_p7 sfn/slot with tx sfn/slot, and vnf is synced with pnf_p7 sfn/slot. This is so that the scheduler runs slot_ahead from rx thread. - pnf_p7->sfn = sfn_tx; + pnf_p7->sfn = sfn_tx; //gokul pnf_p7->slot = slot_tx; - uint32_t slot_dec = NFAPI_SFNSLOT2DEC(sfn, slot); - uint8_t buffer_index_rx = slot_dec % 20; + uint32_t rx_slot_dec = NFAPI_SFNSLOT2DEC(sfn, slot); + uint8_t buffer_index_rx = rx_slot_dec % 20; uint32_t tx_slot_dec = NFAPI_SFNSLOT2DEC(sfn_tx,slot_tx); uint8_t buffer_index_tx = tx_slot_dec % 20; @@ -978,14 +978,14 @@ int pnf_p7_slot_ind(pnf_p7_t* pnf_p7, uint16_t phy_id, uint16_t sfn, uint16_t sl nfapi_pnf_p7_slot_buffer_t* tx_slot_buffer = &(pnf_p7->slot_buffer[buffer_index_tx]); - if (0) NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() shift:%d slot_buffer->sfn_sf:%d tx_slot_buffer->sfn_slot:%d sfn_sf:%d subframe_buffer[buffer_index:%u dl_config_req:%p tx_req:%p] " - "TX:sfn_sf:%d:tx_buffer_index:%d[dl_config_req:%p tx_req:%p]\n", - __FUNCTION__, - pnf_p7->slot_shift, - NFAPI_SFNSLOT2DEC(rx_slot_buffer->sfn, rx_slot_buffer->slot), - NFAPI_SFNSLOT2DEC(tx_slot_buffer->sfn, tx_slot_buffer->slot), - slot_dec, buffer_index_rx, rx_slot_buffer->dl_tti_req, rx_slot_buffer->tx_data_req, - tx_slot_dec, buffer_index_tx, tx_slot_buffer->dl_tti_req, tx_slot_buffer->tx_data_req); + // if (0) NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() shift:%d slot_buffer->sfn_sf:%d tx_slot_buffer->sfn_slot:%d sfn_sf:%d subframe_buffer[buffer_index:%u dl_config_req:%p tx_req:%p] " + // "TX:sfn_sf:%d:tx_buffer_index:%d[dl_config_req:%p tx_req:%p]\n", + // __FUNCTION__, + // pnf_p7->slot_shift, + // NFAPI_SFNSLOT2DEC(rx_slot_buffer->sfn, rx_slot_buffer->slot), + // NFAPI_SFNSLOT2DEC(tx_slot_buffer->sfn, tx_slot_buffer->slot), + // slot_dec, buffer_index_rx, rx_slot_buffer->dl_tti_req, rx_slot_buffer->tx_data_req, + // tx_slot_dec, buffer_index_tx, tx_slot_buffer->dl_tti_req, tx_slot_buffer->tx_data_req); //TODO: Change later if required // todo : how to handle the messages we don't have, send dummies for @@ -1004,7 +1004,8 @@ int pnf_p7_slot_ind(pnf_p7_t* pnf_p7, uint16_t phy_id, uint16_t sfn, uint16_t sl if(pnf_p7->_public.tx_data_req_fn) { - //NFAPI_TRACE(NFAPI_TRACE_INFO, "Calling tx_data_req_fn in SFN/slot %d.%d \n",sfn,slot); + //NFAPI_TRACE(NFAPI_TRACE_INFO, "Calling tx_data_req_fn in SFN/slot %d.%d \n",sfn,slot); + LOG_D(PHY, "Process tx_data SFN/slot %d.%d buffer index: %d \n",sfn_tx,slot_tx,buffer_index_tx); (pnf_p7->_public.tx_data_req_fn)(&(pnf_p7->_public), tx_slot_buffer->tx_data_req); } } @@ -1045,6 +1046,7 @@ int pnf_p7_slot_ind(pnf_p7_t* pnf_p7, uint16_t phy_id, uint16_t sfn, uint16_t sl if(pnf_p7->_public.ul_dci_req_fn) { //NFAPI_TRACE(NFAPI_TRACE_INFO, "Calling UL_dci_req_fn in SFN/slot %d.%d \n",sfn,slot); + LOG_D(PHY, "Process ul_dci SFN/slot %d.%d buffer index: %d \n",sfn_tx,slot_tx,buffer_index_tx); (pnf_p7->_public.ul_dci_req_fn)(NULL, &(pnf_p7->_public), tx_slot_buffer->ul_dci_req); } } @@ -1098,6 +1100,7 @@ int pnf_p7_slot_ind(pnf_p7_t* pnf_p7, uint16_t phy_id, uint16_t sfn, uint16_t sl { pnf_p7->_public.dummy_slot.ul_tti_req->SFN = sfn; pnf_p7->_public.dummy_slot.ul_tti_req->Slot = slot; + LOG_D(PHY, "Process ul_tti SFN/slot %d.%d buffer index: %d \n",sfn,slot,buffer_index_rx); (pnf_p7->_public.ul_tti_req_fn)(NULL, &(pnf_p7->_public), pnf_p7->_public.dummy_slot.ul_tti_req); } } @@ -1603,7 +1606,7 @@ void pnf_handle_dl_tti_request(void* pRecvMsg, int recvMsgLen, pnf_p7_t* pnf_p7) struct timespec t; clock_gettime(CLOCK_MONOTONIC, &t); - NFAPI_TRACE(NFAPI_TRACE_INFO,"%s() POPULATE DL_TTI_REQ SFN/slot: %d.%d buffer_index:%d\n", __FUNCTION__, req->SFN, req->Slot, buffer_index); + NFAPI_TRACE(NFAPI_TRACE_INFO,"%s() %ld.%09ld POPULATE DL_TTI_REQ current tx sfn/slot:%d.%d p7 msg sfn/slot: %d.%d buffer_index:%d\n", __FUNCTION__, t.tv_sec, t.tv_nsec, pnf_p7->sfn,pnf_p7->slot, req->SFN, req->Slot, buffer_index); // if there is already an dl_tti_req make sure we free it. if(pnf_p7->slot_buffer[buffer_index].dl_tti_req != 0) @@ -1764,12 +1767,12 @@ void pnf_handle_ul_tti_request(void* pRecvMsg, int recvMsgLen, pnf_p7_t* pnf_p7) if(is_nr_p7_request_in_window(req->SFN,req->Slot, "ul_tti_request", pnf_p7)) { uint32_t sfn_slot_dec = NFAPI_SFNSLOT2DEC(req->SFN,req->Slot); - uint8_t buffer_index = sfn_slot_dec % 20; + uint8_t buffer_index = (sfn_slot_dec % 20); struct timespec t; clock_gettime(CLOCK_MONOTONIC, &t); - //NFAPI_TRACE(NFAPI_TRACE_INFO,"%s() %ld.%09ld POPULATE UL_TTI_REQ sfn_slot:%d buffer_index:%d\n", __FUNCTION__, t.tv_sec, t.tv_nsec, sfn_slot_dec, buffer_index); + NFAPI_TRACE(NFAPI_TRACE_INFO,"%s() %ld.%09ld POPULATE UL_TTI_REQ current tx sfn/slot:%d.%d p7 msg sfn/slot: %d.%d buffer_index:%d\n", __FUNCTION__, t.tv_sec, t.tv_nsec, pnf_p7->sfn,pnf_p7->slot, req->SFN, req->Slot, buffer_index); if(pnf_p7->slot_buffer[buffer_index].ul_tti_req != 0) { diff --git a/nfapi/open-nFAPI/pnf/src/pnf_p7_interface.c b/nfapi/open-nFAPI/pnf/src/pnf_p7_interface.c index 88aa1391cb..a5cd9bcd16 100644 --- a/nfapi/open-nFAPI/pnf/src/pnf_p7_interface.c +++ b/nfapi/open-nFAPI/pnf/src/pnf_p7_interface.c @@ -258,6 +258,18 @@ int nfapi_pnf_ue_release_resp(nfapi_pnf_p7_config_t* config, nfapi_ue_release_re //NR UPLINK INDICATION +int nfapi_pnf_p7_nr_slot_ind(nfapi_pnf_p7_config_t* config, nfapi_nr_slot_indication_scf_t* ind) +{ + 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); + return pnf_nr_p7_pack_and_send_p7_message(_this, (nfapi_p7_message_header_t*)ind, sizeof(nfapi_nr_rx_data_indication_t)); +} + int nfapi_pnf_p7_nr_rx_data_ind(nfapi_pnf_p7_config_t* config, nfapi_nr_rx_data_indication_t* ind) { if(config == NULL || ind == NULL) diff --git a/nfapi/open-nFAPI/vnf/inc/vnf_p7.h b/nfapi/open-nFAPI/vnf/inc/vnf_p7.h index ad1c5e7944..4fcc99f79b 100644 --- a/nfapi/open-nFAPI/vnf/inc/vnf_p7.h +++ b/nfapi/open-nFAPI/vnf/inc/vnf_p7.h @@ -25,7 +25,6 @@ #define TIME2TIMEHR(_time) (((uint32_t)(_time.tv_sec) & 0xFFF) << 20 | ((uint32_t)(_time.tv_usec) & 0xFFFFF)) - typedef struct { uint8_t* buffer; uint16_t length; 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 14c53b870b..31328393c9 100644 --- a/nfapi/open-nFAPI/vnf/public_inc/nfapi_vnf_interface.h +++ b/nfapi/open-nFAPI/vnf/public_inc/nfapi_vnf_interface.h @@ -854,7 +854,7 @@ typedef struct nfapi_vnf_p7_config int (*nrach_indication)(struct nfapi_vnf_p7_config* config, nfapi_nrach_indication_t* ind); //The NR indication functions below copy uplink information received at the VNF into the UL info struct - + int (*nr_slot_indication)(nfapi_nr_slot_indication_scf_t* ind); int (*nr_crc_indication)(nfapi_nr_crc_indication_t* ind); int (*nr_rx_data_indication)(nfapi_nr_rx_data_indication_t* ind); int (*nr_uci_indication)(nfapi_nr_uci_indication_t* ind); diff --git a/nfapi/open-nFAPI/vnf/src/vnf_p7.c b/nfapi/open-nFAPI/vnf/src/vnf_p7.c index 7f5d33466d..4b68f016a8 100644 --- a/nfapi/open-nFAPI/vnf/src/vnf_p7.c +++ b/nfapi/open-nFAPI/vnf/src/vnf_p7.c @@ -23,7 +23,6 @@ #include #include #include - #include "vnf_p7.h" #define SYNC_CYCLE_COUNT 2 @@ -1455,7 +1454,31 @@ void vnf_handle_ul_node_sync(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vnf_p7) } //NR HANDLES FOR UPLINK MESSAGES +void vnf_handle_nr_slot_indication(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vnf_p7) +{ + // ensure it's valid + if (pRecvMsg == NULL || vnf_p7 == NULL) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__); + } + else + { + nfapi_nr_slot_indication_scf_t ind; + + if(nfapi_nr_p7_message_unpack(pRecvMsg, recvMsgLen, &ind, sizeof(ind), &vnf_p7->_public.codec_config) < 0) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: Failed to unpack message\n", __FUNCTION__); + } + else + { + if(vnf_p7->_public.nr_slot_indication) + { + (vnf_p7->_public.nr_slot_indication)(&ind); //gokul + } + } + } +} void vnf_handle_nr_rx_data_indication(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vnf_p7) { // ensure it's valid @@ -2179,7 +2202,11 @@ void vnf_nr_dispatch_p7_message(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vnf_p7 case NFAPI_TIMING_INFO: vnf_nr_handle_timing_info(pRecvMsg, recvMsgLen, vnf_p7); break; - + + case NFAPI_NR_PHY_MSG_TYPE_SLOT_INDICATION: + vnf_handle_nr_slot_indication(pRecvMsg, recvMsgLen, vnf_p7); + break; + case NFAPI_NR_PHY_MSG_TYPE_RX_DATA_INDICATION: vnf_handle_nr_rx_data_indication(pRecvMsg, recvMsgLen, vnf_p7); break; diff --git a/nfapi/open-nFAPI/vnf/src/vnf_p7_interface.c b/nfapi/open-nFAPI/vnf/src/vnf_p7_interface.c index 71a912057e..5c0ff7b068 100644 --- a/nfapi/open-nFAPI/vnf/src/vnf_p7_interface.c +++ b/nfapi/open-nFAPI/vnf/src/vnf_p7_interface.c @@ -25,6 +25,7 @@ #include #include "vnf_p7.h" +#include "nfapi_vnf.h" #include "common/ran_context.h" @@ -96,8 +97,10 @@ 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) -{ - uint16_t vnf_frame; uint8_t vnf_slot; uint16_t slot_scheduled; +{ + struct PHY_VARS_gNB_s *gNB = RC.gNB[0]; + uint8_t temp_slot; + uint16_t vnf_frame; uint8_t vnf_slot; if(config == 0) return -1; @@ -150,8 +153,8 @@ int nfapi_nr_vnf_p7_start(nfapi_vnf_p7_config_t* config) //struct timespec original_pselect_timeout; struct timespec pselect_timeout; - pselect_timeout.tv_sec = 0; - pselect_timeout.tv_nsec = 500000; // ns in a 0.5 ms + pselect_timeout.tv_sec = 100; + pselect_timeout.tv_nsec = 0; // ns in a 0.5 ms //pselect_timeout.tv_nsec = 500000; struct timespec pselect_start; @@ -213,19 +216,15 @@ int nfapi_nr_vnf_p7_start(nfapi_vnf_p7_config_t* config) pselect_timeout = timespec_sub(slot_start, pselect_start); } - if(setup_time > 10 && slot_scheduled == 0){ + if(setup_time > 10 && temp_slot != gNB->UL_INFO.slot){ - // Call the scheduler - struct PHY_VARS_gNB_s *gNB = RC.gNB[0]; + //Call the scheduler pthread_mutex_lock(&gNB->UL_INFO_mutex); - gNB->UL_INFO.frame = vnf_frame; - gNB->UL_INFO.slot = vnf_slot; - gNB->UL_INFO.module_id = gNB->Mod_id; gNB->UL_INFO.CC_id = gNB->CC_id; gNB->if_inst->NR_UL_indication(&gNB->UL_INFO); pthread_mutex_unlock(&gNB->UL_INFO_mutex); - slot_scheduled = 1; + temp_slot = gNB->UL_INFO.slot; } selectRetval = pselect(maxSock+1, &rfds, NULL, NULL, &pselect_timeout, NULL); @@ -277,7 +276,6 @@ int nfapi_nr_vnf_p7_start(nfapi_vnf_p7_config_t* config) curr = curr->next; } send_mac_slot_indications(vnf_p7); - slot_scheduled = 0; } else if(selectRetval > 0) diff --git a/openair1/PHY/NR_TRANSPORT/nr_dlsch_coding.c b/openair1/PHY/NR_TRANSPORT/nr_dlsch_coding.c index 2ae2549df3..e01adc1bf2 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_dlsch_coding.c +++ b/openair1/PHY/NR_TRANSPORT/nr_dlsch_coding.c @@ -292,7 +292,7 @@ int nr_dlsch_encoding(PHY_VARS_gNB *gNB, } G = nr_get_G(nb_rb, nb_symb_sch, nb_re_dmrs, length_dmrs,mod_order,rel15->nrOfLayers); - LOG_D(NR_PHY,"dlsch coding A %d G %d (nb_rb %d, nb_symb_sch %d, nb_re_dmrs %d, length_dmrs %d, mod_order %d)\n", A,G, nb_rb,nb_symb_sch,nb_re_dmrs,length_dmrs,mod_order); + LOG_I(NR_PHY,"dlsch coding A %d G %d (nb_rb %d, nb_symb_sch %d, nb_re_dmrs %d, length_dmrs %d, mod_order %d)\n", A,G, nb_rb,nb_symb_sch,nb_re_dmrs,length_dmrs,mod_order); if (A > 3824) { // Add 24-bit crc (polynomial A) to payload diff --git a/openair1/SCHED_NR/fapi_nr_l1.c b/openair1/SCHED_NR/fapi_nr_l1.c index 42441e9f53..23e18f5787 100644 --- a/openair1/SCHED_NR/fapi_nr_l1.c +++ b/openair1/SCHED_NR/fapi_nr_l1.c @@ -268,7 +268,7 @@ void nr_schedule_response(NR_Sched_Rsp_t *Sched_INFO){ //printf("Inside NR schedule response SFN/slot %d.%d. \n",frame,slot); if(NFAPI_MODE != NFAPI_MONOLITHIC && number_ul_tti_pdu>0) { - //printf("SFN/slot %d.%d Sending ul tti req \n",frame,slot); + LOG_I(MAC,"SFN/slot %d.%d Sending ul tti req \n",frame,slot); oai_nfapi_ul_tti_req(UL_tti_req); } diff --git a/openair1/SCHED_NR/phy_procedures_nr_gNB.c b/openair1/SCHED_NR/phy_procedures_nr_gNB.c index 9f40821d04..c1dd64af5d 100644 --- a/openair1/SCHED_NR/phy_procedures_nr_gNB.c +++ b/openair1/SCHED_NR/phy_procedures_nr_gNB.c @@ -164,7 +164,7 @@ void phy_procedures_gNB_TX(PHY_VARS_gNB *gNB, gNB->Mod_id,frame,slot,pdcch_pdu_id,ul_pdcch_pdu_id); if (pdcch_pdu_id >= 0 || ul_pdcch_pdu_id >= 0) { - LOG_D(PHY, "[gNB %d] Frame %d slot %d Calling nr_generate_dci_top (number of UL/DL DCI %d/%d)\n", + LOG_I(PHY, "[gNB %d] Frame %d slot %d Calling nr_generate_dci_top (number of UL/DL DCI %d/%d)\n", gNB->Mod_id, frame, slot, gNB->ul_pdcch_pdu[ul_pdcch_pdu_id].pdcch_pdu.pdcch_pdu.pdcch_pdu_rel15.numDlDci, gNB->pdcch_pdu[pdcch_pdu_id].pdcch_pdu.pdcch_pdu_rel15.numDlDci); diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c index b678988be1..5e474f1bd2 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c @@ -406,7 +406,7 @@ void gNB_dlsch_ulsch_scheduler(module_id_t module_idP, { printf("First sched entry at slot %d \n", slot); for (int i = 0; iUL_tti_req_ahead[CC_id][i].SFN = (frame + 1) % 1024; else gNB->UL_tti_req_ahead[CC_id][i].SFN = frame; diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c index c77bd93203..9da818c2ab 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c @@ -835,8 +835,6 @@ void nr_schedule_ue_spec(module_id_t module_id, int8_t current_harq_pid = sched_pdsch->dl_harq_pid; if (current_harq_pid < 0) { /* PP has not selected a specific HARQ Process, get a new one */ - // if (NFAPI_MODE == NFAPI_MODE_VNF) - // sched_ctrl->available_dl_harq.head = 0; current_harq_pid = sched_ctrl->available_dl_harq.head; AssertFatal(current_harq_pid >= 0, "no free HARQ process available for UE %d\n", @@ -853,9 +851,6 @@ void nr_schedule_ue_spec(module_id_t module_id, remove_nr_list(&sched_ctrl->retrans_dl_harq, current_harq_pid); } NR_UE_harq_t *harq = &sched_ctrl->harq_processes[current_harq_pid]; - // if (NFAPI_MODE == NFAPI_MODE_VNF) { - // harq->is_waiting = false; - // } DevAssert(!harq->is_waiting); add_tail_nr_list(&sched_ctrl->feedback_dl_harq, current_harq_pid); NR_sched_pucch_t *pucch = &sched_ctrl->sched_pucch[sched_pdsch->pucch_allocation]; diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c index 1eb7fa7f7d..139b22788d 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c @@ -502,9 +502,6 @@ void nr_csi_meas_reporting(int Mod_idP, // find free PUCCH that is in order with possibly existing PUCCH // schedulings (other CSI, SR) NR_sched_pucch_t *curr_pucch = &sched_ctrl->sched_pucch[1]; - // if(NFAPI_MODE == NFAPI_MODE_VNF){ - // curr_pucch->csi_bits = 0; curr_pucch->sr_flag = 0; curr_pucch->dai_c = 0; - // } AssertFatal(curr_pucch->csi_bits == 0 && !curr_pucch->sr_flag && curr_pucch->dai_c == 0, diff --git a/openair2/NR_PHY_INTERFACE/NR_IF_Module.c b/openair2/NR_PHY_INTERFACE/NR_IF_Module.c index 5a1cb970eb..26978ebc30 100644 --- a/openair2/NR_PHY_INTERFACE/NR_IF_Module.c +++ b/openair2/NR_PHY_INTERFACE/NR_IF_Module.c @@ -99,7 +99,7 @@ void handle_nr_uci(NR_UL_IND_t *UL_info) const sub_frame_t slot = UL_info->slot; int num_ucis = UL_info->uci_ind.num_ucis; nfapi_nr_uci_t *uci_list = UL_info->uci_ind.uci_list; - LOG_I(MAC,"handling UCI SFN/slot: %d.%d, num_ucis: %d \n", frame,slot, num_ucis); + LOG_D(MAC,"handling UCI SFN/slot: %d.%d, num_ucis: %d \n", frame,slot, num_ucis); for (int i = 0; i < num_ucis; i++) { switch (uci_list[i].pdu_type) { case NFAPI_NR_UCI_PUSCH_PDU_TYPE: From b7857a505e64ebbe8d55d13b9ddc5bb53b510532 Mon Sep 17 00:00:00 2001 From: Laurent THOMAS Date: Thu, 5 Aug 2021 17:31:31 +0200 Subject: [PATCH 79/91] try to fix CUDA, and fix infinite loop in nr UE uplink data collect --- cmake_targets/CMakeLists.txt | 11 +- openair1/PHY/types.h | 2 +- openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c | 105 ++++++++------------ openair2/LAYER2/nr_rlc/nr_rlc_oai_api.c | 6 +- openair2/NETWORK_DRIVER/MESH/local.h | 4 - openair2/NETWORK_DRIVER/UE_IP/local.h | 4 - openair3/NAS/NR_UE/nr_nas_msg_sim.c | 31 +++--- openair3/NAS/NR_UE/nr_nas_msg_sim.h | 3 - openair3/UICC/usim_interface.c | 2 +- openair3/UICC/usim_interface.h | 2 +- 10 files changed, 71 insertions(+), 99 deletions(-) diff --git a/cmake_targets/CMakeLists.txt b/cmake_targets/CMakeLists.txt index 16fe7b1eab..aae52c6d23 100644 --- a/cmake_targets/CMakeLists.txt +++ b/cmake_targets/CMakeLists.txt @@ -255,6 +255,7 @@ macro(add_list_string_option name val helpstr) endif() endmacro(add_list_string_option) +# this function should produce the same value as the macro MAKE_VERSION defined in the C code (file types.h) function(make_version VERSION_VALUE) math(EXPR RESULT "0") foreach (ARG ${ARGN}) @@ -311,13 +312,13 @@ endif() 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") set(commonOpts "-pipe -Wno-packed-bitfield-compat -fPIC -Wall -fno-strict-aliasing -rdynamic") -set(MKVER "'MAKE_VERSION(a,b,c)=((a)*256+(b)*16+c)'") set(CMAKE_C_FLAGS - "${CMAKE_C_FLAGS} ${C_FLAGS_PROCESSOR} ${commonOpts} -std=gnu99 -funroll-loops -D${MKVER}") + "${CMAKE_C_FLAGS} ${C_FLAGS_PROCESSOR} ${commonOpts} -std=gnu99 -funroll-loops") set(CMAKE_CXX_FLAGS - "${CMAKE_CXX_FLAGS} ${C_FLAGS_PROCESSOR} ${commonOpts} -std=c++11 -D${MKVER}") + "${CMAKE_CXX_FLAGS} ${C_FLAGS_PROCESSOR} ${commonOpts} -std=c++11") +# cuda compiler bug (limitation) on complex macro definition if (CUDA_FOUND) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DCUDA_FLAG") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DCUDA_FLAG") @@ -336,7 +337,7 @@ set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -ggdb3 -Wl,-rpath -Wl,${C # set a flag for changes in the source code # these changes are related to hardcoded path to include .h files set(debugOpt "-ggdb3 -DMALLOC_CHECK_=3 -fno-delete-null-pointer-checks") -set(CMAKE_C_FLAGS_DEBUG "${debugOpt} -Og") +set(CMAKE_C_FLAGS_DEBUG "${debugOpt} -O0") set(CMAKE_C_FLAGS_RELWITHDEBINFO "${debugOpt} -O2") set(CMAKE_C_FLAGS_RELEASE "-O3") @@ -3491,7 +3492,7 @@ endfunction(make_driver name dir src) # nashmesh module ################ list(APPEND nasmesh_src device.c common.c ioctl.c classifier.c tool.c mesh.c) -set(module_cc_opt "${module_cc_opt} -DNAS_NETLINK -DPDCP_USE_NETLINK -D${MKVER}") +set(module_cc_opt "${module_cc_opt} -DNAS_NETLINK -DPDCP_USE_NETLINK") # legacy Makefile was using NAS_NETLINK flag, but other drivers the hereafter flag # so, this cmake use OAI_NW_DRIVER_USE_NETLINK everywhere if (OAI_NW_DRIVER_USE_NETLINK) diff --git a/openair1/PHY/types.h b/openair1/PHY/types.h index c0a9af388c..8d8d9db2de 100644 --- a/openair1/PHY/types.h +++ b/openair1/PHY/types.h @@ -23,6 +23,6 @@ #define __openair_TYPES_H__ #include - +#define MAKE_VERSION(a,b,c) ((a)*256+(b)*16+c) #endif /*__openair_TYPES_H__ */ diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c index d1056f30d2..67c4a81e80 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c @@ -1970,93 +1970,66 @@ uint8_t nr_ue_get_sdu(module_id_t module_idP, int CC_id, frame_t frameP, sub_frame_t subframe, uint8_t eNB_index, uint8_t *ulsch_buffer, uint16_t buflen, uint8_t *access_mode) { - uint8_t total_rlc_pdu_header_len = 0; - int16_t buflen_remain = 0; uint8_t lcid = 0; uint16_t sdu_lengths[MAX_LCID] = { 0 }; uint8_t sdu_lcids[MAX_LCID] = { 0 }; uint16_t payload_offset = 0, num_sdus = 0; uint8_t ulsch_sdus[MAX_ULSCH_PAYLOAD_BYTES]; - uint16_t sdu_length_total = 0; //unsigned short post_padding = 0; NR_UE_MAC_INST_t *mac = get_mac_inst(module_idP); - rlc_buffer_occupancy_t lcid_buffer_occupancy_new = 0; LOG_D(NR_MAC, "[UE %d] MAC PROCESS UL TRANSPORT BLOCK at frame%d subframe %d TBS=%d\n", module_idP, frameP, subframe, buflen); AssertFatal(CC_id == 0, "Transmission on secondary CCs is not supported yet\n"); - + // Check for DCCH first // TO DO: Multiplex in the order defined by the logical channel prioritization + int buflen_remain = buflen; + char * current_ulsch_ptr = (char*)ulsch_sdus; for (lcid = UL_SCH_LCID_SRB1; lcid < MAX_LCID; lcid++) { - lcid_buffer_occupancy_new = mac_rlc_get_buffer_occupancy_ind(module_idP, mac->crnti, eNB_index, frameP, subframe, ENB_FLAG_NO, lcid); - - if(lcid_buffer_occupancy_new) { - buflen_remain = - buflen - (total_rlc_pdu_header_len + sdu_length_total + MAX_RLC_SDU_SUBHEADER_SIZE); - LOG_D(NR_MAC, - "[UE %d] Frame %d : UL-DXCH -> ULSCH, RLC %d has %d bytes to " - "send (Transport Block size %d SDU Length Total %d , mac header len %d, buflen_remain %d )\n", //BSR byte before Tx=%d - module_idP, frameP, lcid, lcid_buffer_occupancy_new, - buflen, sdu_length_total, - total_rlc_pdu_header_len, buflen_remain); // ,nr_ue_mac_inst->scheduling_info.BSR_bytes[nr_ue_mac_inst->scheduling_info.LCGID[lcid]] - - while(buflen_remain > MAX_RLC_SDU_SUBHEADER_SIZE && lcid_buffer_occupancy_new){ - - sdu_lengths[num_sdus] = mac_rlc_data_req(module_idP, - mac->crnti, - eNB_index, - frameP, - ENB_FLAG_NO, - MBMS_FLAG_NO, - lcid, - buflen_remain-MAX_RLC_SDU_SUBHEADER_SIZE, - //Fixme: Laurent I removed MAX_RLC_SDU_SUBHEADER_SIZE because else we get out the buffer silently - // the interface with nr_generate_ulsch_pdu() looks over complex and not CPU optimized - (char *)&ulsch_sdus[sdu_length_total],0, - 0); - - AssertFatal(buflen_remain >= sdu_lengths[num_sdus], - "LCID=%d RLC has segmented %d bytes but MAC has max=%d\n", - lcid, sdu_lengths[num_sdus], buflen_remain); - - if (sdu_lengths[num_sdus]) { - sdu_length_total += sdu_lengths[num_sdus]; - sdu_lcids[num_sdus] = lcid; - - total_rlc_pdu_header_len += MAX_RLC_SDU_SUBHEADER_SIZE; //rlc_pdu_header_len_last; - - //Update number of SDU - num_sdus++; - } - - /* Get updated BO after multiplexing this PDU */ - // we don't recompute it if the waiting queue is much larger than our buffer - // because mac_rlc_get_buffer_occupancy_ind() cpu cost is high when waiting queu is large - if ( lcid_buffer_occupancy_new < buflen_remain+1000) - lcid_buffer_occupancy_new = mac_rlc_get_buffer_occupancy_ind(module_idP,mac->crnti,eNB_index,frameP, subframe, ENB_FLAG_NO, lcid); - buflen_remain = buflen - (total_rlc_pdu_header_len + sdu_length_total + MAX_RLC_SDU_SUBHEADER_SIZE); - } + while ( (sdu_lengths[num_sdus] = mac_rlc_data_req(module_idP, + mac->crnti, + eNB_index, + frameP, + ENB_FLAG_NO, + MBMS_FLAG_NO, + lcid, + buflen_remain-MAX_RLC_SDU_SUBHEADER_SIZE*2, + //Fixme: Laurent I removed MAX_RLC_SDU_SUBHEADER_SIZE*2 because else we get out the buffer silently + // the interface with nr_generate_ulsch_pdu() looks over complex and not CPU optimized + current_ulsch_ptr , 0, + 0)) > 0 ) { + + AssertFatal(buflen_remain >= sdu_lengths[num_sdus], + "LCID=%d RLC has segmented %d bytes but MAC has max=%d\n", + lcid, sdu_lengths[num_sdus], buflen_remain); + AssertFatal(current_ulsch_ptr < (char*)ulsch_sdus+MAX_ULSCH_PAYLOAD_BYTES, ""); + + current_ulsch_ptr += sdu_lengths[num_sdus]; + buflen_remain -= sdu_lengths[num_sdus]; + buflen_remain -= MAX_RLC_SDU_SUBHEADER_SIZE; + sdu_lcids[num_sdus] = lcid; + num_sdus++; } } - + // Generate ULSCH PDU if (num_sdus>0) { - payload_offset = nr_generate_ulsch_pdu(ulsch_sdus, - ulsch_buffer, // mac header - num_sdus, // num sdus - sdu_lengths, // sdu length - sdu_lcids, // sdu lcid - 0, // power_headroom - mac->crnti, // crnti - 0, // truncated_bsr - 0, // short_bsr - 0, // long_bsr - 0, // post_padding - buflen); // TBS in bytes + payload_offset = nr_generate_ulsch_pdu(ulsch_sdus, + ulsch_buffer, // mac header + num_sdus, // num sdus + sdu_lengths, // sdu length + sdu_lcids, // sdu lcid + 0, // power_headroom + mac->crnti, // crnti + 0, // truncated_bsr + 0, // short_bsr + 0, // long_bsr + 0, // post_padding + buflen); // TBS in bytes } else { return 0; } diff --git a/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.c b/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.c index e53eb94a7f..e196b56f1c 100644 --- a/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.c +++ b/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.c @@ -216,8 +216,10 @@ tbs_size_t mac_rlc_data_req( maxsize = tb_sizeP; ret = rb->generate_pdu(rb, buffer_pP, maxsize); } else { - LOG_E(RLC, "%s:%d:%s: fatal: data req for unknown RB, channel_idP: %d\n", __FILE__, __LINE__, __FUNCTION__, channel_idP); - exit(1); + // Laurent: the query loop was checking all possible RB, but by mac_rlc_get_buffer_occupancy_ind + // so it is more straitforward to try to get data + //LOG_E(RLC, "%s:%d:%s: fatal: data req for unknown RB, channel_idP: %d\n", __FILE__, __LINE__, __FUNCTION__, channel_idP); + //exit(1); ret = 0; } diff --git a/openair2/NETWORK_DRIVER/MESH/local.h b/openair2/NETWORK_DRIVER/MESH/local.h index 58ae78e7a5..4918e19628 100644 --- a/openair2/NETWORK_DRIVER/MESH/local.h +++ b/openair2/NETWORK_DRIVER/MESH/local.h @@ -64,10 +64,6 @@ #include "rrc_nas_primitives.h" #include "COMMON/platform_types.h" -#ifndef MAKE_VERSION - #define MAKE_VERSION(a,b,c) ((a)*256+(b)*16+(c)) -#endif - struct rb_entity { nasRadioBearerId_t rab_id; nasSapId_t sapi; diff --git a/openair2/NETWORK_DRIVER/UE_IP/local.h b/openair2/NETWORK_DRIVER/UE_IP/local.h index 5532de9573..46e44f0040 100644 --- a/openair2/NETWORK_DRIVER/UE_IP/local.h +++ b/openair2/NETWORK_DRIVER/UE_IP/local.h @@ -55,10 +55,6 @@ #include "platform_types.h" #include "sap.h" -#ifndef MAKE_VERSION - #define MAKE_VERSION(a,b,c) ((a)*256+(b)*16+(c)) -#endif - typedef struct ue_ip_priv_s { int irq; int rx_flags; diff --git a/openair3/NAS/NR_UE/nr_nas_msg_sim.c b/openair3/NAS/NR_UE/nr_nas_msg_sim.c index 7308f677a1..c6992642e9 100644 --- a/openair3/NAS/NR_UE/nr_nas_msg_sim.c +++ b/openair3/NAS/NR_UE/nr_nas_msg_sim.c @@ -465,7 +465,7 @@ static void generateAuthenticationResp(as_nas_info_t *initialNasMsg, uint8_t *bu initialNasMsg->length = mm_msg_encode(mm_msg, (uint8_t*)(initialNasMsg->data), size); } -void generateSecurityModeComplete(as_nas_info_t *initialNasMsg) +static void generateSecurityModeComplete(as_nas_info_t *initialNasMsg) { int size = sizeof(mm_msg_header_t); fgs_nas_message_t nas_msg; @@ -532,7 +532,7 @@ void generateSecurityModeComplete(as_nas_info_t *initialNasMsg) } } -void generateRegistrationComplete(as_nas_info_t *initialNasMsg, SORTransparentContainer *sortransparentcontainer) { +static void generateRegistrationComplete(as_nas_info_t *initialNasMsg, SORTransparentContainer *sortransparentcontainer) { //wait send RRCReconfigurationComplete and InitialContextSetupResponse sleep(1); int length = 0; @@ -625,12 +625,11 @@ void decodeDownlinkNASTransport(as_nas_info_t *initialNasMsg, uint8_t * pdu_buff } } -void generatePduSessionEstablishRequest(as_nas_info_t *initialNasMsg){ +static void generatePduSessionEstablishRequest(uicc_t * uicc, as_nas_info_t *initialNasMsg){ //wait send RegistrationComplete usleep(100*150); int size = 0; - fgs_nas_message_t nas_msg; - memset(&nas_msg, 0, sizeof(fgs_nas_message_t)); + fgs_nas_message_t nas_msg={0}; // setup pdu session establishment request uint16_t req_length = 7; @@ -649,8 +648,6 @@ void generatePduSessionEstablishRequest(as_nas_info_t *initialNasMsg){ MM_msg *mm_msg; nas_stream_cipher_t stream_cipher; uint8_t mac[4]; - uint8_t nssai[]={1,0,0,1}; //Corresponding to SST:1, SD:1 - uint8_t dnn[4]={0x4,0x6f,0x61,0x69}; //Corresponding to dnn:"oai" nas_msg.header.protocol_discriminator = FGS_MOBILITY_MANAGEMENT_MESSAGE; nas_msg.header.security_header_type = INTEGRITY_PROTECTED_AND_CIPHERED_WITH_NEW_SECU_CTX; size += 7; @@ -680,11 +677,21 @@ void generatePduSessionEstablishRequest(as_nas_info_t *initialNasMsg){ mm_msg->uplink_nas_transport.requesttype = 1; size += 3; mm_msg->uplink_nas_transport.snssai.length = 4; - mm_msg->uplink_nas_transport.snssai.value = nssai; - size += (1+1+4); - mm_msg->uplink_nas_transport.dnn.length = 4; - mm_msg->uplink_nas_transport.dnn.value = dnn; + //Fixme: it seems there are a lot of memory errors in this: this value was on the stack, + // but pushed in a itti message to another thread + // this kind of error seems in many places in 5G NAS + mm_msg->uplink_nas_transport.snssai.value=calloc(1,4); + mm_msg->uplink_nas_transport.snssai.value[0] = uicc->nssai_sst; + mm_msg->uplink_nas_transport.snssai.value[1] = (uicc->nssai_sd>>16)&0xFF; + mm_msg->uplink_nas_transport.snssai.value[2] = (uicc->nssai_sd>>8)&0xFF; + mm_msg->uplink_nas_transport.snssai.value[3] = (uicc->nssai_sd)&0xFF; size += (1+1+4); + int dnnSize=strlen(uicc->dnnStr); + mm_msg->uplink_nas_transport.dnn.value=calloc(1,dnnSize+1); + mm_msg->uplink_nas_transport.dnn.length = dnnSize + 1; + mm_msg->uplink_nas_transport.dnn.value[0] = dnnSize + 1; + memcpy(mm_msg->uplink_nas_transport.dnn.value+1,uicc->dnnStr, dnnSize); + size += (1+1+dnnSize+1); // encode the message initialNasMsg->data = (Byte_t *)malloc(size * sizeof(Byte_t)); @@ -819,7 +826,7 @@ void *nas_nrue_task(void *args_p) as_nas_info_t pduEstablishMsg; memset(&pduEstablishMsg, 0, sizeof(as_nas_info_t)); - generatePduSessionEstablishRequest(&pduEstablishMsg); + generatePduSessionEstablishRequest(uicc, &pduEstablishMsg); if(pduEstablishMsg.length > 0){ MessageDef *message_p; message_p = itti_alloc_new_message(TASK_NAS_NRUE, 0, NAS_UPLINK_DATA_REQ); diff --git a/openair3/NAS/NR_UE/nr_nas_msg_sim.h b/openair3/NAS/NR_UE/nr_nas_msg_sim.h index 348c27ecc8..753ebf1762 100644 --- a/openair3/NAS/NR_UE/nr_nas_msg_sim.h +++ b/openair3/NAS/NR_UE/nr_nas_msg_sim.h @@ -117,9 +117,6 @@ typedef union { } fgs_nas_message_t; void generateRegistrationRequest(as_nas_info_t *initialNasMsg, int Mod_id); -void generateSecurityModeComplete(as_nas_info_t *initialNasMsg); -void generateRegistrationComplete(as_nas_info_t *initialNasMsg, SORTransparentContainer *sortransparentcontainer); -void generatePduSessionEstablishRequest(as_nas_info_t *initialNasMsg); void *nas_nrue_task(void *args_p); #endif /* __NR_NAS_MSG_SIM_H__*/ diff --git a/openair3/UICC/usim_interface.c b/openair3/UICC/usim_interface.c index 8cea3899b5..5d04f88285 100644 --- a/openair3/UICC/usim_interface.c +++ b/openair3/UICC/usim_interface.c @@ -43,7 +43,7 @@ extern uint16_t NB_UE_INST; {"amf", "USIM amf\n", 0, strptr:&(uicc->amfStr), defstrval:"8000", TYPE_STRING, 0 },\ {"sqn", "USIM sqn\n", 0, strptr:&(uicc->sqnStr), defstrval:"000000", TYPE_STRING, 0 },\ {"dnn", "UE dnn (apn)\n", 0, strptr:&(uicc->dnnStr), defstrval:"oai", TYPE_STRING, 0 },\ - {"nssai_st", "UE nssai\n", 0, iptr:&(uicc->nssai_st), defintval:1, TYPE_INT, 0 }, \ + {"nssai_sst", "UE nssai\n", 0, iptr:&(uicc->nssai_sst), defintval:1, TYPE_INT, 0 }, \ {"nssai_sd", "UE nssai\n", 0, iptr:&(uicc->nssai_sd), defintval:1, TYPE_INT, 0 }, \ }; diff --git a/openair3/UICC/usim_interface.h b/openair3/UICC/usim_interface.h index 27bab1e35e..eb32a6bfc1 100644 --- a/openair3/UICC/usim_interface.h +++ b/openair3/UICC/usim_interface.h @@ -50,7 +50,7 @@ typedef struct { char *amfStr; char *sqnStr; char *dnnStr; - int nssai_st; + int nssai_sst; int nssai_sd; uint8_t key[16]; uint8_t opc[16]; From 557b5445d385f5eef6d14e71d08173d0efdfaa91 Mon Sep 17 00:00:00 2001 From: Mahesh Date: Sun, 8 Aug 2021 12:23:15 +0530 Subject: [PATCH 80/91] PNF config file pusch_proc_threads update --- targets/PROJECTS/GENERIC-LTE-EPC/CONF/oaiL1.nfapi.usrpx300.conf | 1 + 1 file changed, 1 insertion(+) diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/oaiL1.nfapi.usrpx300.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/oaiL1.nfapi.usrpx300.conf index 5cfd4dc768..51079cf604 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/oaiL1.nfapi.usrpx300.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/oaiL1.nfapi.usrpx300.conf @@ -28,6 +28,7 @@ L1s = ( remote_n_portc = 50001; // vnf p5 port local_n_portd = 50010; // pnf p7 port remote_n_portd = 50011; // vnf p7 port + pusch_proc_threads = 8; } ); From 78f3bca19a5585e990496aa4fc514edd3d413766 Mon Sep 17 00:00:00 2001 From: Rahul Gottipati Date: Mon, 9 Aug 2021 16:36:27 +0530 Subject: [PATCH 81/91] CSI-RS handling in nFAPI --- executables/nr-gnb.c | 7 +- nfapi/oai_integration/nfapi_pnf.c | 43 +++--- .../nfapi/public_inc/nfapi_nr_interface_scf | Bin 3986416 -> 0 bytes nfapi/open-nFAPI/nfapi/src/nfapi_p7.c | 8 +- nfapi/open-nFAPI/pnf/src/pnf_p7.c | 2 +- openair1/SCHED_NR/fapi_nr_l1.c | 128 ++++++++---------- openair1/SCHED_NR/phy_procedures_nr_gNB.c | 2 +- openair2/NR_PHY_INTERFACE/NR_IF_Module.c | 17 ++- .../CONF/oaiL1.nfapi.usrpx300.conf | 2 + 9 files changed, 97 insertions(+), 112 deletions(-) delete mode 100644 nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface_scf diff --git a/executables/nr-gnb.c b/executables/nr-gnb.c index de24bb9136..7a8ff0dabe 100644 --- a/executables/nr-gnb.c +++ b/executables/nr-gnb.c @@ -142,7 +142,7 @@ void rx_func(void *param) { int slot_tx = info->slot_tx; sl_ahead = sf_ahead*gNB->frame_parms.slots_per_subframe; nfapi_nr_config_request_scf_t *cfg = &gNB->gNB_config; - LOG_I(PHY,"slot rx %d \n", slot_rx); + LOG_D(PHY,"slot rx %d \n", slot_rx); start_meas(&softmodem_stats_rxtx_sf); // ******************************************************************* @@ -253,7 +253,7 @@ void rx_func(void *param) { stop_meas( &softmodem_stats_rxtx_sf ); LOG_D(PHY,"%s() Exit proc[rx:%d%d tx:%d%d]\n", __FUNCTION__, frame_rx, slot_rx, frame_tx, slot_tx); - + // Call the scheduler start_meas(&gNB->ul_indication_stats); @@ -265,8 +265,7 @@ void rx_func(void *param) { gNB->if_inst->NR_UL_indication(&gNB->UL_INFO); pthread_mutex_unlock(&gNB->UL_INFO_mutex); stop_meas(&gNB->ul_indication_stats); - - + notifiedFIFO_elt_t *res; if (tx_slot_type == NR_DOWNLINK_SLOT || tx_slot_type == NR_MIXED_SLOT) { diff --git a/nfapi/oai_integration/nfapi_pnf.c b/nfapi/oai_integration/nfapi_pnf.c index 520a5dc578..5957f173f3 100644 --- a/nfapi/oai_integration/nfapi_pnf.c +++ b/nfapi/oai_integration/nfapi_pnf.c @@ -1216,13 +1216,12 @@ int pnf_phy_dl_tti_req(gNB_L1_rxtx_proc_t *proc, nfapi_pnf_p7_config_t *pnf_p7, int sfn = req->SFN; int slot = req->Slot; - //int slot_tx = slot + 6; // ref for PNF is slot_rx, so increment by slot ahead struct PHY_VARS_gNB_s *gNB = RC.gNB[0]; if (proc==NULL) proc = &gNB->proc.L1_proc; nfapi_nr_dl_tti_request_pdu_t *dl_tti_pdu_list = req->dl_tti_request_body.dl_tti_pdu_list; - if (req->dl_tti_request_body.nPDUs) + //if (req->dl_tti_request_body.nPDUs) // NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() TX:%d/%d RX:%d/%d; sfn:%d, slot:%d, nGroup:%u, nPDUs: %u, nUE: %u, PduIdx: %u,\n", // __FUNCTION__, proc->frame_tx, proc->slot_tx, proc->frame_rx, proc->slot_rx, // TODO: change subframes to slot // req->SFN, @@ -1233,27 +1232,20 @@ int pnf_phy_dl_tti_req(gNB_L1_rxtx_proc_t *proc, nfapi_pnf_p7_config_t *pnf_p7, // req->dl_tti_request_body.PduIdx); for (int i=0; idl_tti_request_body.nPDUs; i++) { - // TODO: enable after adding gNB PDCCH: // NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() sfn/sf:%d PDU[%d] size:%d pdcch_vars->num_dci:%d\n", __FUNCTION__, NFAPI_SFNSF2DEC(req->sfn_sf), i, dl_config_pdu_list[i].pdu_size,pdcch_vars->num_dci); if (dl_tti_pdu_list[i].PDUType == NFAPI_NR_DL_TTI_PDCCH_PDU_TYPE) { nfapi_nr_dl_tti_request_pdu_t *dl_tti_pdu=&dl_tti_pdu_list[i]; - memcpy(dl_tti_pdu,&dl_tti_pdu_list[i],sizeof(nfapi_nr_dl_tti_request_pdu_t)); - //if(!&dl_tti_pdu->pdcch_pdu) handle_nfapi_nr_pdcch_pdu(gNB, sfn, slot, &dl_tti_pdu->pdcch_pdu); - //dl_tti_pdu_list[i].pdcch_pdu.pdcch_pdu_rel15.numDlDci++; // ? - // NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() pdcch_vars->num_dci:%d\n", __FUNCTION__, pdcch_vars->num_dci); - } else if (dl_tti_pdu_list[i].PDUType == NFAPI_NR_DL_TTI_SSB_PDU_TYPE) { - //NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() PDU:%d BCH: pdu_index:%u pdu_length:%d sdu_length:%d BCH_SDU:%x,%x,%x\n", __FUNCTION__, i, pdu_index, bch_pdu->bch_pdu_rel8.length, tx_request_pdu[sfn][sf][pdu_index]->segments[0].segment_length, sdu[0], sdu[1], sdu[2]); - handle_nr_nfapi_ssb_pdu(gNB, sfn, slot, &dl_tti_pdu_list[i]); - gNB->pbch_configured=1; - //} else { - // NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s() BCH NULL TX PDU SFN/SF:%d PDU_INDEX:%d\n", __FUNCTION__, NFAPI_SFNSF2DEC(req->sfn_sf), pdu_index); - //} - } else if (dl_tti_pdu_list[i].PDUType == NFAPI_NR_DL_TTI_PDSCH_PDU_TYPE) { + } + else if (dl_tti_pdu_list[i].PDUType == NFAPI_NR_DL_TTI_SSB_PDU_TYPE) { + //NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() PDU:%d BCH: pdu_index:%u pdu_length:%d sdu_length:%d BCH_SDU:%x,%x,%x\n", __FUNCTION__, i, pdu_index, bch_pdu->bch_pdu_rel8.length, tx_request_pdu[sfn][sf][pdu_index]->segments[0].segment_length, sdu[0], sdu[1], sdu[2]); + handle_nr_nfapi_ssb_pdu(gNB, sfn, slot, &dl_tti_pdu_list[i]); + gNB->pbch_configured=1; + } + else if (dl_tti_pdu_list[i].PDUType == NFAPI_NR_DL_TTI_PDSCH_PDU_TYPE) { nfapi_nr_dl_tti_pdsch_pdu *pdsch_pdu = &dl_tti_pdu_list[i].pdsch_pdu; - nfapi_nr_dl_tti_pdsch_pdu_rel15_t *rel15_pdu = &pdsch_pdu->pdsch_pdu_rel15; - //nfapi_nr_tx_data_request_t *tx_data = tx_data_request[sfn][slot][rel15_pdu->pduIndex]; + nfapi_nr_dl_tti_pdsch_pdu_rel15_t *rel15_pdu = &pdsch_pdu->pdsch_pdu_rel15; nfapi_nr_pdu_t *tx_data = tx_data_request[sfn][slot][rel15_pdu->pduIndex]; if (tx_data != NULL) { @@ -1267,14 +1259,21 @@ int pnf_phy_dl_tti_req(gNB_L1_rxtx_proc_t *proc, nfapi_pnf_p7_config_t *pnf_p7, LOG_E(PHY,"pnf_phy_dl_config_req illegal harq_pid %d\n", harq_pid); return(-1); } - //uint8_t *dlsch_sdu = (uint8_t *)tx_data->TLVs[0].value.direct; + uint8_t *dlsch_sdu = nr_tx_pdus[UE_id][harq_pid]; - memcpy(dlsch_sdu, tx_data->TLVs[0].value.direct,tx_data->PDU_length);//TODO: Check if required + memcpy(dlsch_sdu, tx_data->TLVs[0].value.direct,tx_data->PDU_length); //NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() DLSCH:pdu_index:%d handle_nfapi_dlsch_pdu(eNB, proc_rxtx, dlsch_pdu, transport_blocks:%d sdu:%p) eNB->pdcch_vars[proc->subframe_tx & 1].num_pdcch_symbols:%d\n", __FUNCTION__, rel8_pdu->pdu_index, rel8_pdu->transport_blocks, dlsch_sdu, eNB->pdcch_vars[proc->subframe_tx & 1].num_pdcch_symbols); handle_nr_nfapi_pdsch_pdu(gNB, sfn, slot,pdsch_pdu, dlsch_sdu); - } else { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s() DLSCH NULL TX PDU SFN/SF:%d PDU_INDEX:%d\n", __FUNCTION__, NFAPI_SFNSLOT2DEC(sfn,slot), rel15_pdu->pduIndex); } - } else { + } + else { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s() DLSCH NULL TX PDU SFN/SF:%d PDU_INDEX:%d\n", __FUNCTION__, NFAPI_SFNSLOT2DEC(sfn,slot), rel15_pdu->pduIndex); + } + } + else if (dl_tti_pdu_list[i].PDUType == NFAPI_NR_DL_TTI_CSI_RS_PDU_TYPE) { + nfapi_nr_dl_tti_csi_rs_pdu *csi_rs_pdu = &dl_tti_pdu_list[i].csi_rs_pdu; + handle_nfapi_nr_csirs_pdu(gNB, sfn, slot, csi_rs_pdu); + } + else { NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s() UNKNOWN:%d\n", __FUNCTION__, dl_tti_pdu_list[i].PDUType); } } diff --git a/nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface_scf b/nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface_scf deleted file mode 100644 index 6ee4ec840431454c5429456810abaa7a2f29fb59..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3986416 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 z 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°XK?cs+^}VF8F+= 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�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
=(V8T~( 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
~j43GSco4W5em#vL_`zqm_oUE=(0 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

^SLPfJk$!O%IyUB$-;YTl z&PfS&S?Qp*#e892m>Qe(r|Chl1ekEhifP)3x(s&yn=CBp6kN5-RXDO|B zx0jFyCsV9+2<*b+JUoxs>fmQTYW>3hhjV}6@rYK(xS+%4DzAR2;Rape=2Lt(Unm)% z;fCLF&R6CT_EY`sy2l#Lkv`&_lwg;Y-BMQRdC8#b4~&yOP5{C=WM#M1p?ZGy&5P%r z#vY0K&=}`Ba4skLNSuT`wbsZbH*5N;N!U&10LMCEURBYt3Qul3FQI;&OtI2e`5(ru zj=;WqHsyEelVnge)y!>DtK;=E$S1q)dm^am5Oeulytf9n8|3Sq51yE-;YvrH+f7Do z*&GA^_9?yI^++KrSmF9rj0<^c`HGoGHGRWL=*wf`M>7i07jPe%nuDTm85wO#!E?_2 z49;hZd<6HmD(JvVt6MMA{8vqaugrp?y4*mIznLS0Ri%eHCneZrrLVeM=X>A3-a#7Q zm`lDA`93Ddb8g&r=LM;M0&<)~R(vJud*DXA-?6pES4!e@Niyep5z;Rp-}&*e@k^!l zoRbpl()hCLzcT3;u-;ej(EUwVh%CYN-@Mv-d>GYWz$>*_V4J!XUxniP=Fy8No*7HN z1HQ7cNxY^|T$_`)~t zK-__GXiCQ;&jLJMQatwe17x}Z+4hooH~85n3(90k4{=UPu**u{7~u>3V*C47qV)%3 zDXQV@zCYV9iYXnQc>Wbgdkn=Zs6!TdBcShP=SpfOVMh<-WTpJ#IWfo$BoQK9;Xc_<}zS9{lOu zMpQ}4sATWIY#XRYreYl`qU{HzW~P3ed)l6_3_wiDApHX7-J37}?S%9UbAnCPs$cjh z9iBgX5ackFfCC+5LknDyDZ7=gx$>gaz<5%j>g@hJYd1gP3wdANj7+rtYb>fDUu8bF z8wgPJ>G2g(wh_1Fpfi79`Nl|pgZ#JS4+}dRQPDN8v&WU$MyMX8#`&S6{$3%yYCK6k zWRD9iSiS*O*Wrp^dwgj`MQbRvoyAGEo&P+}N2{U(H|~6Wu$HI#mnD~{vV23tA7Fgz zv;E5r>~(Vl_06RF+y43|MelF2d?SP}tP@P??lpbRC*puFyhj#SCAcsiKe&JPIXH(d zg${A)Hn5$yM_-3&vGgT$6&y+Ax18HeW-e~?of=j#F4(Q*X?cvc zUwidA_FnrS6dG#yy~ zEhhd8aeb%UGst3Q3+fOgI+R6#pPWaZlR*BFOtIqYK_d_73vuVWN$pWIHkJZGzFCyM zJJ*jmA~iJP1{{8FhSgW5`1Wn^;~66=`h2VdzR-rn^%7iIe^~qFh(j!{a=q<1WXd@J zBOg6)2Ks`ZJ+kG4Be0Jyxvz+gL*bSf7xJiSbD#c$#&oi6pal>8oeT@LtOQMYLg z_IR+S*mxWwc8kxChoHEQ`Uzcf9Lz6dx&hhFCAiSv3V$!UD8ax%l~5GxPwg^nf)27_ z53Ym>E{w;%iJh*HZseSlV3(D?k>_xKgK;Qw?U7bmex|z2&pf;Jemwojd)7&xB_PK+ z1bpjp_RAFRvvd2OkOG{O66~_lH;>YH<8SEmI8P=3;T*EU^%B0&k2`j0bWnPV(>TE{ zE8HA(KpWqlf4Sm9>4^j&oI_T)0g_ik{N3Ee-zxq9H>bVTE-Ty^d2SFm7vJ&mAJXeq z2>kt4xalPBz&QW-*cx4=bbfoQy$F|^KSW9X0R8yx1?c%5reut<&mUx_4OA7v7xIU+ zF&)ar6Kv|dygTgUx=fv~ZAOUyf)10K44){WdNRdI-w^SK3J9!s#k4ij8_A&JXd-i( zppSo+`tOpRAIy-Na863F%Zjf;`WqN^%-X5_q^txWoI_T)1w>!)hdK4o>>I5>BvSyF zSNvo=hWlhA53WFJ8%s_-vGF*A^0S_|4!#V&zap7pr9+hH0ORKGFgt!R8B}Y3@Kbhs z^=RHu>7`49>!aescb&_glU}|wxS160y|*J=Q%0HiI#&ATq5}{kAwC@Wbmiqz)5JLJ zQ7hb>UOMit@9nr;dWCJ7xNe0TBmMw+$%Q73Hb{`DB~h$!{X}2rZ`W@`$xb69XrBFg zDmSkCI$<4v@09$XCmK=F{B(=m5nuKfV#?imAS_{pQ%e(g2KUI*<|!>gD4 zP6dR=n&)S4*5)lrH|Oih20&6NA$clk%rh|Jr2zebNH%X_h;!_!g4!7&`D{^Q`%idcD~QmWwm0Rq|N`}ZKL zVN1l`an~;*L$SUv&-zWiCWF0pYJsf|xXChOzmR(AcIz;I(h?RoQ_yZv;=hph<%Oc( zOUqg0#C6So^BBHfG7f=J)wvJBbjwhpf_ziRx+lbkrY$oTNGlAmwiS(U$#SE<3dOhg z#K%p1OYHe_{WnPb_cFw6kk?EvHb*S(1nXdbfN|)qzDjTDCNp-TJ(>>eIZ@)jkWaQ6 z+rl)?r*{w*f{AY{s8x# z&R;dWItvllZrhK!{s8N6Fm8g~{_eNz9E&SAbr#Q9zN(6G!Es;sqPl5yQnlyHQi<2q zX&4v$;Z}}64z z|A#%v@8I`&*)~wmA@L02q_hv+?}k8;M6uE#MCq_rQX z+b_8BAxz~v_iXgV<)E>B%WQG!(@VF#l%I7A9N8e5o>VA3mAhf3uS)cV_;4mT>T4vm~B@~jYDlYaVMv%nE$F|z6mpcjMY;@+?)6;8LDojLzL(M>jbC!H#CiJ5qm%5 z`a>S^2bj0C`5HzeWAWB-HeMK8p*7##IG({py9{~pE~yrKM&i1a4l$wwFzx$UWD|>0 zEa(q~O=>Z-|e_Fz+6|bk{=moSe#n{!8=)KfCpCgE5lK zA}6j}>031XV} z;Ai8WTW8Wi+94JnLgaVXD0fnaxu&cZi@#AB`%ygv_}qzC&~yvGvv8941K4ri zL+KEUOs&T9O>?LNiz^dc$fIiA_e47uH`^gD+pdWG9_tP0z>_)unw}esRIv9mh=r!I zNB4)>6CeAYJsv2q$Avbm4qi%!dF`Gv=@7Qpfg9IV(%)bn+o@a&Qyx`tr9EGs4zV>@ z2Uvel4{h23?};wOVX=57y{6+{_hh#_X-wD-US-dhZ3A`hy?A}H5!zmOVGvsNB0WBd z@4e;e;3571I_!Gp*LiR)x)j;_1J`Z^#BMO(lzV<=%Fj|8+v~vPy9kd%*CE__^{Pi` zuCSdt&E9T2+~7cLHyDRb{xBMN zJns~Xo7u!(UueVj;{f3c7k#kllmZr4vFFP+iPz=(vE3jq**?EvQ}(3nN@9Fv^hgO{ zf}iz>HJ{7kdY={>hx{^L--K!A&Zcj|?GZysxlzo|ir46V_QxgkvmoVXdye|n8OWka zmc8A$eio(jo$EM$mMgdplSbL?9**6zvh3}~>&Ma$y1pk|=*#L?)CS|0MF*Pwjpp4+ z7A-!o&7#vVF63v`ej0XxJ?^nP?*1n0zkbSY_jBwP zyv+i+5T$UZa&W_< zxKzG#@?iEoTKo+Ua%Z;yWw&u0y9L^d+09Sc?Ou-Ef;+|ZRY-pWyM;OW7CY3J_1|nt zhY(MPG%+1ADZVo}e6tRV=}@fddEZmlG%kJqOil86E>?#irNajt9g3c@=gW&{0Wyz; ziN!qsgB{RIQbmhrEMKV`)&b^2<2if-4*2qj1gN;)WK5O&*>f^~6VoAw=m7qE|9chg zW^wK6nhxxF#Uwt!cwBu?lQ~*^2)c~xIg~$q$kDgBqkX^N`GZ2`eWzXIeXI`BD(nxS zL!TKJr)fG!54nqzAxeh{938?AbTDy6J3NH%wP<_I{uZcTU<-#`+RX>p=nwkEM;yLs zf_%eNJge~Pun>Ybl)_xGe&MJ5L2)r3GLS(Pndl4aeS=m-KhyM8UFw@l`NPK?eRDe4 z_Y0OQ)blBQD{}PBnk1%gfYP_lCDhkT>HD7l%x#*!F_-#=DSan$^o!I#5ES_0) z3u^;)vY5VpYF;>W$fcVP)@p4!rR#NctO$Ln|(!KSU^h z*v8RU5%h;5N{2%n9SWz5>7e|ekH^mp67LtRT_U8vL0ljHh#q&86Yj?Od`jQ#9DSpT znE&Rq#5#bll&$rR&^jWkLA?H-zOHeYW4F}X?Cl0PY(Mr>{rG2&4w-^Fq*8o;=kQer z*{?_ObnxuJ`hq{a_Ta+R+Bg(+=?^O94?8$IWOTOo2VQ*eQT^gI7x97BLMG3zL+LN0!oLS932Xq+3Ub^g}O?ftAO>h4e9UR!Jd;F(_<3~o8=ODDb8VqxdEGS~{7<^eqta30tF1o_{@VPUf|@V(xy1lww+TZ| zqjmc-h&g)B=v{YwizvI@aKOwrP0((BD&P6Ib!z80S?XWOT(N$kQt@|%i~DaBmH4K2 z2euomM{T}s?I=xO>7+Y-iz$6?6K!F;~&nd(om$FmlQ`B{|mv;3jr;}FZoNBP;nEqeS_ zTOe&y(@y0bweCD02zdJ%iLZ zw5qKhC*>yY;$(=L2i(N5TZzN?!1{xa^0OB?ewMn#{`)<_W-P9U^0R6jzIhv*^$XS? z3aNbZxfT=7v&W?+V(~0S#k2P>;kX$f@eI}<8s61wsMarnF5_7$rEhhPzWEOOF>AL> z${$|h_(Q=v&emaAT$$oqgTq(dDCQ5!y*R$4BYhWN-{DnFUnR-@#`;k)U-y2@-brDgS+$FcHRy@sQ2`gdaf8z%k>I?VY}*C96B-T0PH>F^Lo2g#uhtp9o&>3QEP z9Dm4LB9=!f6yLr)zT3s@mU2;Fw{O4X@3&b`RF>P@jhF98zhE7}ZjZfo>GE}z@`p|7 zhu_!wg;ea$A2KL?`*HLw*@n z`su_UVEydYySt7z9lyukAJ{ffm&xzX-h{Sy`U^)RyUA!%Qj_@oZaAMUCGD~Q-iQwT zRcZ28%^#FD$;|^;eIr!<+n=MaPf*_|wSLx`qi>$W&r7p>1E`~E^Ue93xDyuqTyuns zL*Tz_Dqp)u(^vW?x&Fr5ExnIE9;b73$X;ddXT1IvKr3;e1H_%iE}n~L`Nl}x0UZ`s z(sfXi9FJLC9~FP!n6=+@-zg~gdEP973-`0yZ~otK({&x>XFPp9Yq7qN_Z?``=O~M7 zSJ&bhdtQ)=JGs-}H08fVg3rB5J278axA)z75`9hrGYBRzUhs7AlJO1ZS>?}%zhmEz zUEN9t55>339Xelmx8wfC{XAKu1nU3?TYOlyD$CE`TI{(MnfL?f+h_l@K`gFaUDJV$ zXF)2SE#kzpoMHCkG4I+rNA>ZdZR*_HOUEHHKJnVn`!v4vKG;?^V1429WDjvZPnK85 z8DCb197>1993AABZSBVO2bJ=No6GH}%f6qC9nSJpww*%7hwjHGqhI4pu2|`tdl-NJ zB#iTOipCvbQDc`m)0b^m)KB+^JCx_qJj+<}+S=-CY(Q!<`Tg%&sD4e^zaG*2OiAK* z!Fh(uxDESRIfQ#;^)-KRFP>nhrZ4MfVam^za{MfJu)PjEzQF~0zgThh@tYG+;~vuZ zvIn!P<8?w9-~K7=Iz`hr>{4GpiR;jhE6uEQ8GBv3y2h8)H$v(A7f0X1SH=8SS%=4k zR77mj#~V=AYApUM#BkL^*lsYsRUe;&@)G>cf`2(4hvGz79r7t1&Tw=nc){M!jPDTF z0@OIPVfu)^ymJ!m)9l8cQ%L*_;?9*_r^PfsizVS_EGE=bAI5P9P2;2y-(O++-h-?T zVmjp3(c?pK#g{A_dYIx2fSFGGxPkXk1gKJAQ`#kH$j*{x)buI~>W`ZU-4 z*S|D5|219zG;UuF9T;@Cbc^N>3i*9q)A`H}#FrN)rF?V%<}DC#wwOj^^f}Cx_VXd; zQt@iIFOHMoXE)vSTSNAo+&dH74RzQ5mtti%X^kGw3Y*^2HQ9?>;f9Exf%uP}sQ%`q z!i{BMKLgtxO1okyi<{9%?EXa|6(`Sf;$+4fVsSl8bbxv6+KTnxX8GFHt@Mo%|A%qt z?Nvk3bH!z3w26MS!d-t0k^BMX7t=SsJUWh<#6K&(CEfJ+aAUV#V_C?6gXd}4Hc*dH z`R|Nxt2gGIlW3pDmmN2YD1SK5@dr6u%pXdK|Hjt|I+gh!%dN1;S=?dy7E^pLaQONJ z$N6H)AJTU|0AV<(qUp;vDr%48Bs_mMan7&1*yDC}D_rkh9M@sJBqeRh_jWk!aVuOO z!G-6ePIqo{CEL!fZiSoCNY5YI&Ne@PCW@O!@)8)|e!ch7eUD4%g0Am1gVX~dT+ghZ7C)Z)4z3rD!>z#!C4E*7$Nfml%?=0NR-S{Sd ztLHnRuYNF+TH(teDv(h(A;uZ>I($BrGg7_e#O)2QoZVI{20P$?iuBIrBzzpQS-RUc> z$L(Pr&|`cU%x5TBcZ}U4w=7SF8zKneFH=XG#!v0|L|YP zOXAm-54+PLO5y`Nr||OP%0m#Yj5ej9%W+dZh;@K*=*SpwU(7e?(jQ_}UQ)F0K?Gbz zM&Ock(VY(An9lc&r&qkK@eL=*mmS}HRDXMe)8F!674wHE(HHXH^7Y4d)cC4N@&)PW z5{Y3Q0JnW;L3<5XcKLiscmlQ$+%UcNkwfS|_6Mn}JG+&zXm8B_G0p7*)r8&1{dLxbLX zVwJ`>=n^+d;r5S&p4V{0E^!qyAA-1k(;FSN=@>{HFS#F!&0`B|v&HEnkX}F5ZxFexZ1APMW)G6VstCZrFxZ@kDiu(m%|8ZN(yER<@ukLXD zKHQHHQEAx1SyA+2D8WgB{!8(lvG3c?rF>oLAm60xu;b3dX#D~EuivHJd;}Nz#djx` zmCjqjF8QXB=T^XOPam%MoyJ#ni5sN&_I&$@zZBPHekK$Dh4EM#K4iIuEC1`x&%6W| z)>FTjFk-!itGLAVRMY+8^~rzs(QtzF8#Bm+Qp^v^8uCixjr8>LMz_yFtiQ^8$ z-wCVx&Sa0LKId${$+inf*dJhi(f0Pnx$JSJidZ}=K8E=M?o-n%pk*GcSXfH#d1aQ5 zcNE5j?~m#}zV|lvc$U|eFLz#;qG12M3<19J4vUJ`v)kC>nj4`#DaSEih-dwe{3o#uc8}xb04PgmQGYH?k z?&73c9e+NyA!3L~u~CiVwm4dYmk-`4w7iPp(+u zh9Ac|coAH7mlY^J5Phe*(;@m2<_q~*jh+v;VcDjR5sPO9GLAb{5MYC&&L-0z@C(Kv!MTW#`-o#fZx5|y_bfoOo_ZZdbn1zezmfjqG0<# zzFv3sJuv+?l)~4<;(DwMjspNVY*NpE44_ciBZeEOjqL{U_te&Drg2CSTrbHdxZn@X zPG2()DAGmwMU1ah7V7{v(0ko~u!zQl?T{dDaT$HwTl+G z{CU%qR9jr`_!dK%KlBS2-#Vacu%)=U7;b7^jC(l(Y?JllMHbipzF2(l5*?r)SLZxu z9<=}b5LbsHqC;7Pi*6B`irmsx2U8o^QM^dE+vsY)jnLw+GS*%E4c5Yb-vC{s{-lzj z2v^?(E4SgJ%l5xPV=^#0O zP8YpXbBU4lp?Lm~y`c2Ilk5^VQUm(~Z?W+>s9^iFL%6;Eor0zrSTTQd$96+4%_T_u7uGc%J@g!+T}DQmlI-&S zP=x9ixAuzm)o>Mu&xu+2L(a=MPJ%x?+ILkC;7XU=T(LMQk@XTV*b`Fp8;!5uC0`GD zUJmm0ltm@KYPhn?=QV&xhURCF*G$ zA7CDP-{H4!iGx!A0)o#KD?~@oq0anr(=;7oE_DbHyFt!A@!i3LHC)-{^Dxq{`16H; zTcP9mO_T)j&HPWr{8#CM<2u;w@zY3?$1Acv2a)^uJilzTpiLC-5;iK z{2{Bqtv^tz>6^hvalQz7N%fYwbM+&5t7y7dob)u%^WUs_vj%87gq`~XOC?^JAMT{klZFA95Q}J8`e4c96|NqA&PaeRc8O8m^M$=Z{(B zTUnjzZCA8PXDo%2#pZ7j zN{3H5Iute(U9 z9k~5CL%}+r8@$q6lUi3`-+9rawzzDQcs+0k<06Tbk1{Pg*P~}8~Z+e#Lpm~ti7ksF^zA~CEo%ve*@fiuWD(EJ2}(D;!c>-;WmyA zLHqmjtOW6TDtYb-^zFpKRjZ2Wn?>}6IJv0eKy-TqM<~^~zTA8#O7)ArJIwte@0i&5 zmQVBryDdBY1q`2tQglQtPReK{PFpXzdPmPc44@7wR(VNw2aF5%ogUi1)^x|vGeT?~ zCYQ>i&dq*WgfI79MTx$U_f6wG-9;8%2gHy%8Eg1vaj7+YMnNxbeQ>($^7 z`@8ir_2a@5Vt$rK^t}w>4n(U2$rh_|K0fJ&&CGg_#SPVVrY}2g zM#y*p^Q;Lk&705S<_kWD7u$;GComr0(yrn?EUwq#_e8SoB=TGv+;6#Z=^xi<@k}QB zP3JQ^tn3zOi^l_q5hv3Io8~Q9YsC6-DtS%};_tb}845#3D!9d&-Pm^00o>nUoL~3$ zTX$$WC@yvIQhcRdqfP4?C4zR#r~1X%KHr$;o2K{2?69(19_bgL?<40rj%S)lYF#mX zW%ArMjK>}1JN9b&`d#WPufukO=Yl-Vn%C8E<;&fz?_?0WL0y0lw1rSGO|RzP?+ zl%U{qLFvTLu0v?eT3`90#y9MeZ|o!8&o*$LgZ9;T<`4emw;0y9!(?3=60^38?la9> zGG7w&hY+RjPL960f}g)AA^C3=#P`Fy?lsM0Qv}yx@(5qRJuz>^YV=|#{&Z*h8XBRB zO6(5f<_%q{t!0mA>=Mg&f>eJy?@3+3;!1tQ_OSld<(zF>vEv) z#g=A$vjzF45xy|ak9~UG(=1=lZZUloN{2rV-2!3FQ2c_p>8o`eUYu;!AuChNZlUoQ z7sj`R9Uq)vAd4yyLB5eE^te9qocVjo(gnZ&S0()o#e(vsmfS=?aH4*NHmX|Fz zkVTd7`(iqTi4I`5`5$jz%HkFa>JTLT0`&dqM0=E78cTXVF}}(+tRv{KYQ_$ftr?5@ zv>0xXjPnrB?%uce5hE)4K03kAp#&+uP41mHnZ+%6MU1aZJ~xw!0Qc5gK83~g?iGuZ zc`fjG0sfFXGe5@SW(wlUujz5;4Ciw*IXBtrz+KlUK^Z!X6_=sE+tD@Hk|Owd$N=fb zFi^}{{q{W6k7cwe#hmwJF5lu#I^Q6NukUxU^)oNI&j5VWIlqIKVm~kB@-3nGj^XeP zJDeZ0>l#@oK!V-Mp}!#KdwtUHv-Mvt-%t;X3kw8QOsfRQrv>MmKFWU^o-%*#D_wB@ z=BIF*b8sd5c>q@jkAii$9O*Fb^A#7-i=kvaZrk4s=WCVNG>i-D8uxIX(=8cbi_7Jk zs_6dEZ{x3~^~qHGJc^4eQ@D?DaI>GZjM+1oT8v;5h*)w)I&_1x70&U06(&)Vw1wVR?~zVO`22+s36Ucu+N zaw&ZWaP&=^Eyh=>r|Ub7^Sr0;FDjK7dGfd4{#SbFxIThNQ4L~?BPp1s^ zG6ve>8hDgert5rHa`@)HD~20At>Z?oe%GW!(Ob5-Tpdz~|AG$t{xaVuQ&-#KmcDg* zBjunTCvzU0snW+_J56wY9C{HyuiP48e7m~BOl`gyZs&Nu$<-lC!TLg+T+8{qUa=tG z2o-nU=IG%2!B$@`-;|D+FT}|s_g|=mUJNCDq1f}vxp(0C5Ul_9xTWtm22fN$H8BbZJ~_H<#a=5POswD`-O zq)_wN5p6FActi2OF1B7>v;vP8u&}eO#<}keps149S!|var1(DHZ~H73H+P@yc)>P_ z*HcMB)Pwbl2g~d%5v|EJe3;9mg@>OWn)>wRkIuuZL zi?-j^-iV4m|0akVBe>Atp4oQ-mgfvbIUr`YP-E<8u#Q;$!1M(MP*lnL%yztBo5brL z@;fVVU!=p%#oO4E)Ky|}Cyn5O4z)gdov%tlx#dL@fzM#XpS#9gExM?fJ#!XKveLOx=;j(8~T>m;Tz6#L+^nGpqGv`^{ zG(jB#6yNuEFFelTdVdn*o6-d90Q&y4?}aTaZmKG#um5|Tm%zI6ktgQPD9uaAe)c+S z-D;fAAv!>Rt32m((@LU$gP0D|W%#)a7~h)jU;aAFC-{RHu6iZLh5W4I?7Be~H?&C% zH%4$FK=!C{c~2HMxLFKWCOX`N0Bco_DlBebtr)KK1#VXx0X~t^vmc9_8x_M1lh2LA z2N~u)e(rM?H)o3=E)~ySALNU%xM9J#Bj17NStz}ho=ZKjm&GmED#q7G^pz3dOCQ{r z$>L^h6T{6|px-|}+HC0aT0fRnJDwM^RN{3x1@{Yx4_*8IozI>W*&)VPzFx;|ooU7` z*eQma*Fn!89=*5gVwP`Kp)*`|-KdC)>&No5P4j@v^pI9Z&#xOSC+i`K6^Z4w-~N;3)UCrEpoWOsb3Tc;)aP15YP7IeRP=Rs|dzl ziTE!p5IlQdOIY486!m*CyG57k`j&052F*9|NEmk6-||U3L(A6E*cU6RI+wAe z{V2vagTx2$-%}@#WEoM>{lcGZ`Eu8zd}KWe)_?yyQe?XS772>w>%}O7Y3si)Pi%dA zsh`bo7uQqD>T$ABg`?nZh7uC|o(6RY<^}QW>QyUW(D+Kvy5p;Us;@_VeDtdSX}GG( z=XAs5c@2mUY2&AzFo=LE@=~$+W{?`+TCA^ski|`DAciXwyFp&vx?uTa7B?t(f2ff3 z3&8#HzCC}jxSq*kaYv=}ee>FJomt$xSz^@T|fJiFEl*uH73YcPQ`f?`0wY3u3oO;X|IKTF}_M2j9U!> zy|?mnnmIc#L0SRqo#RQNRV%g{LTfebG83!^eUFG z>hO2O*m-v@;S1~4({6j}NftNrkeI&3WPS|KRg7F--L%e?JyS5>q5NTe$C)O(l?d{U zk-Qql`Ra|@e5Z{=QpDXj6eE0LoNvdX8iKB;^ z);0V+#r!Nt#tX39nj6e^OPeA%URd|SzO?@a{C?rSQ!q3(Y{IqY%k9S{#BPwUcOAU(R~9!nEM_;E*bVfp z`^wSzn%!bvcjHi)^f%Dqhx^XKZ5Kl+EEMA#ruxP4P5&-6fTBufFR}QbQhZkrF!Rm- zT#ToKZd zZ2!BmDeuc_F2>hS@%{as%FEb`N9_4>^-a4B=lRet#%H&?mBmfX6YCd264zmT>vMMG zRu(t*gxI_#^-J6i{CD8pX~$Sx-+f|s^QPhZ-H?#{bnAzYYX0kYnV(6E_5OB#Oyk)s z-@s9^c~+SCLk$FYyY#)uw(3*1`kLARH>I9F4;Z@l(f?S!>I-6gi@Rfe;e!n2hW`F0 zi|Z47oR_;95Lhz&zl&E{~b+4`n#KFT&2}r3#oYtd~@H zWA7T4Z*YMvU$#lSE-QMRyludv(~Z-H6gf}vu3b2{O6 zunzOrh!HT{8%kzB+q{HpH-*GAFxa!b&2}rfAQpdpKJ33~2=~uXBU@c?j|{Ww<;H%jR{hQrs>M~rW38(oLDIJka6+#-r^ z4hI)KMCWMT-ZWk)m@mZ1v<`obXZ=CS6x4yjef{}!m08>pzis?wo5bsxBXGV0&%;c3 z{9E*RF`fq~cev|sA!0YsVK|4cPf!Oh(E<9!jI>Sd;%|cb7Z$_~m(%ALr#H1hF^|lg z<|U^C>kk=}-R3oV?rn-{d{cQy%pVkzSHq1rU%#JC>pQ6f#rz?Q;DSGlt@FES-jdl@ zjBk)Up9=ZpXX|FJj=y>8Ur-R&PreUGMp&Dc{k?^PjBiE-aTSvH!F(t@@VBp6+%)^& zVd9RP9`d{3d ziw`C~L$SU{04e=wt~owT665P5xUkN(v}MM>>~*~>#o|MR^kaDNw?U-coh)w2r(%4A zRDa9p*xjT_+YnRhOrpFsbYN96n))u zWBn^Ov$%G3jj!pvtMT{-4^+(Aaq>s@cc!qHt~V^kw}8Se^VKor9mWzB#4V<9f66~M(}*fbfoWoV^M_-9fIR9z`Pa~YV&OjS z;*Nywu)uRE*P_1<_T2^37ek3m7vn2GgL%RFLt}La%6~E6*mie({Z!sJuj|x216fol z{#=Z2h{CP@>f5idxCP&f`LCb!3s~J)UFYgPa8l{C4HtdzN`*;#BQ+uFywTOX`GKZ z#AW%Y6z-t6A2h9V6|NQ2!ACtm`E>b#^V#c`2tGgQr=H*W_xB~Hyf1gZvw1AbCp(Da z4ooyxrqn?F4fkX9OLzU)NAib;2>0#}*PG@S!OyUNvwXBViGEtO^fm1e{{9l^7kzU_ zqx%8I5}YZfgFG0=NyyhzHka*(USuP3;+hrTFnP`f`r8AaY&T)%ZWNmb6j#7@gV^46 zQV?#tn6S}4%cAjR`&;x%tOG1kf0Dl5rjqYHfV`xAnZLWB7ekTl@B7Ek zXZ-3G= z36+e;aDRSm%P*f{kNfhRjmK;|i9A0ExEnaQ1rBjpe@LbD-OJHI7Sute_=Z}Ub;z3K zOb3>)O!3{v;TyS0%x=;(c>V_ZR=dT_H{~lazG)QS{T#lzqWTiPFyE}+a`^A8zvKz> z^-_Fe9KPA){ylp=t*(u4T3vgU$^Cg4kCoLqcWL{zSC9Sk8u3$Ee^7`HkWjz>Q8-t_ z(_S;a7PDJArNaS^4#lE6bjJA?u*7-zg?W&{SNK@Yp?#GWUnmx4F7{P_O^HS5{GqwHNYw8?lxU8SWsPS0l=-~fW%+F-4O7qet?Rn(J55*Z zHCymGJU`I^*8Ap+9g?l#X|KU;Vt$rQ*{vQ&hrm*2c4PfFNa5D!;HHfhi)Ud@HA7aFAkoOH-HRoLoPkT+9?@R~n{Lb&}QQ4H%=R4%f+C^%vub=gq zw(54%ahn|)5mtvhN{4|Q9Wqup(}BfJC;2)&57YUkC-<}TG8c;3Ekf~qg2UIRI^)ao zk;#3his-<{`%ji-k4FXh=2Lv1m;?^WdV;P{5| zb*;#U__g@<#__t+zd`&p|8@N8djr3wyoHY!k$P|#-mhKV%Fl|a`1=$`huA7HyJZm_ zu0sS?)fu@`%H_rMEvER+qZWSL&C>>^TaC7I1#j}(Uwwr>8)cs@AD3(u71!s2qKlZ)^Zpx|s|9+ZeP#Gj+ zpLom2Hnu!?F}4~@nM93!N@YkIvG)7f|bD)w!#cpsjacZxbYEUaP&&u`Z3AmZkA_v!xfbW_E3J#V{> z#{-Rbv?o2KcAI+w%fNG3dY-~E_B@usr?Iq8$FkuuEE}g`Nq(YupgNTfAGV9Gu;EGH zUUO+Xm2ne!30JfOyD^I8bQWies@T`}yEXfg92?3bP+m7|`0u;Z7Hrtg|H#)UuU#ka z;wtib*IScUw1bz=W7+&T@Sg{ViSh>8Z#*81?Ca3Uo2?>m;zw)pit=Q2-?{qbk++A4 z`=hs8lUF=1$nC(^9|rIHOvQ7oZj1MyiS~8s?C@q4JJkPSY6s|XDt{3##xGp{*A`rH zCUaleFI?kyjiTHRY+d=1{E~|Mn0(t>v#)3em(C8hxs`cc`=6;D%Jid(i+|UMjVFJr z5)Y0$YLhn!35W7S>nifP%=1H4zeT;xe#=(zTVsv#x^?#5qKdqc8tq%ueJ^QZ-zPF; zcPfj&)Mj6gPTn?Ee2_g^Awid$7)ug(rzRgpLKN^Rp`#|3yE zlX=(vPiJ(Zmi`RHt;s8%m(e|^7OnD}TEXJ;WTM}EIy-D##SY#Y<2UX_zp?l|XU{{& zi~7Xgv}OlUUcXM>ZK}v?PuJ$RfDX596KSR>3XSXor9<|8}a9e=~p8CT~n9?`c)!P0TfIZ&l+g*PJXio7oKc2VLH;~}BL?O6pkd7kO|SyelvxgFSIhW)L| z@4Ti?wsv2P3h(rw^ot2{sU|6O)m@kJGunr zW!K++TQ~VIaeq_9)DERnD&*DK_qHnXx?VTMt!m$_x7oh-D)x1bHpQ(fZ(1ks?N#JW z)o5QAe_py1u>SAW_^~B&-G4rl=dfx0%zGMMCv^A0>wbZ=uypms(%%ouXaLJ%Z!8mM zV43w}Nz|0js7_`0RkSadLp!wd%E2w+eKQ}j_;^qhlsfysK}UblI>sA{5|F3x7mf2g8=b4@U{Lv>vKJwP|?J?4y_1H^+G zExrdsjNc}m9hOwFL+l+>d8_)(rCZ;5~ zpFBFPGaddJvUWdh#d$E`qxHUA6?rR;7d9CA&91|JuL^Fg#`hp={Jwa$uHo9wxmFNI zOHZxMZw{Tj?^lsGV=*2?c~X!On0?u}x=$cgk$0S5)F!V}C+`PU-nO& z9e;bl%O8vT&FW+a@wmJ$9?so*$QW_IS=|WN&F#SKyYt7-4l~0M_Z#76`F(gSKLlGp zK0`dutZszs=k{gehvORuJYt3;?l-~>a62%0k3MK3i~{9;Mz}#PFLd|XH#Z*gi5x1; zPAku9;_ZUHU*le<{qxErHonD3-mtD+9Mkr+=Qoa0xz`BSv9h^c?34N63h_+8#rq$` z^E3zE561fWPlpyO?yIOcUf4kLig_mmH$JdfXbu0)tMP!!JDaO>w`y#`h+9d7QE5LWfLtv&(ShzmB!pH_q(~!!+&v`8(H~cf|P3 z@pjCf>j+=kbac6}@ZO{yYm>K0mnZw#2W>Cnn$;*ct6!3n#icB`1Th&W>12sg;v8@rA(`1vU;O-TKWaHBfhc~4E5F9iw* z8{sB({ZO`DY}6*hosInvYZvw7j$90dO9tCW-VARSY+SPJxo!hxFxjz$TakA-F3V@( zrdBIN+=d$aA@6S3&$Ily(}VY(F5)J=rt2D2=Y@X$-3Qj*;;|~u%kx;?Z$NxDo!H zZDxni)K4Kg%74lEwT&N=d!QY61-MslIf$hnsh^R&ah<#uJifNK2 z4~kFUBknh=8_ApJ@!$l2JAXL)X)_#gzY%V9d2`P%3!i%jc`-kzT3btbAHRs6LAAI+Bd`P z%hvlku37hsh-+3ik~gEvlf6^lvGG~iuc1bHef+*+)-LAEKKiFJPzx0!c|&{P`Z{aJ zi`w4?1s<92DR;kyD1zr@jEAjZ$DWa8Y?d3|@N9pwE_zp4jqWTTP1IbEEcbjICph!9P0Sj#(NUN3O_ zvUms|S((=}9co)ANO#5lg0;88h4nX5oJIL}(?$8kx{)2CPvU!e8SeYLzh2Q_G@M|q zKNk61C!xG7|9=1Y+Iz+QW_2TZ>p3p7?^V%fEAm;bxNiRap$-6WS0En|aeS+5vqPTG z-`ITf+b`M;5pm7xMs~>YcwpncMb|!dh=`MX%v$`4=lQvPS)QDh-FcJwEeCH>W3j;U z+0yHNbc?)Zbt5|@b>q}W{x|+zGaPZh5w7P!l$YhR30;4gN$oAUv}Jic1S^NM4*tOX z^ZpX$F{>NN8{&Rr?f9PmPI$}=N8E3On}V4jleZ20d#(2+G4VXJI^l|WGNT)>AJ+Ac zOGO;ltlHu?`cQM69oAvTw?$mDI>=jfT_XcK$PSNw_4ZRDPU7s^@_M$uIjheyqL>oh!tz2XqF&N4J}LponW$H?l*X_s6V%yW_ouv(0eC{YJPU zejSI6&;H!+u8?@1S=|UX$@4lh{+>6+D#od`;<|V|u=l;*e)?5snBj=~jpWUPMOlBr z){Wj8I~kZ2VB*-`Qpf{a^2VaUB?zL}tzNn{J-N+7JZeO-8 zH>Q0T*6gHyMz{rC{Kmbf_mKjHgN<-g{Cl^|zMXaUO&;7bzr}R3Ra?q;pO5OMRoKW6Rt#`7!ZvD&WIa7B6i`{Hwc%)VXp_Wi`NeXHi*1h+4{ zQSOunJGT;f12@$;f74x;o^zc7b6H+*3;!-nk6a_}H>(@@Ew5|GJ8t>RLJ=ptv#H<2Q%d#d zD=05pUq5HoPxTbP(VH!|x2m`)-TjDnrKVNPhpL{W+emiMZ7Tg4)~$0Lc6yszNM3D+ zmR;v{@pxeCFo(I5&~M89jO6tkiuP>{aBprqtLD5eO5<=hzn@@wDv&2TcylfDTi|4z zZ?bvIYInY`$ZJ+7JBaPLz`w`Z4FKBspM`mB`LAhdZSm{kerE%Re$!Gnm!q23NM7+s zFUMu$lF*1_&Jy>V)s1k2I^1`jTXeV?j=0|lH_CC@g)G}=|6U-TXI3}DP3mxGwqH8h z3`g8=gzI@7*OghW+;PkPPf+~2-j$1AG0tK>%RCb^TD?MSH?}A0C-JtYvvUG6=_$hXG-a^RM`oaDykdEY7qJC>OgwD!o5kG#7r2 zyVPc1FVE}D#>q)vg0;CFB-@1`j+XFXf6)PUT+#if{Q%bme`>B5TV@AeckD0NfbZ-h zCSSoY^*^`8?;45m8{xR@I)nR^qFay2{!Z42+n|%T>HWE1i@44jziZT}lXvzPdrcE@ z<2B;id!T)p9o8*h+Ev8$Sp5EwXx|XWWq$kas@Gl>af=pl#q%6IpRsj~e(qf>#;M}* zVx97XD6e-V=ACWfgtce+ccIGpifnYWzAn z8>fCdWzq^W9C5!9Zjj@${5y1;MGRi*XN2qMhIU|a_T-90#XKPAw{|_NqFwNQh>iQE z?^{V)J~N{j*&z-yHfCGaj@S2G`y=&3Udet)3-A98>u{%@|Hv@HO}5Yu4IKAikoTq;p9~<}Obc=2+;0Z}?(tJs zK^jI+3C)gs!rd}?gSzi}&Z+Xe~F4dLGw}*f?tB&VN+2W06O!8^v$z;^y(${FT2wCZ1vC zbeJK$(FrMCd%Jhm>WcOjy|uRcX_MRztnaj~zVi)3!3=g7$(y;dIX{e>GKmdOq<%)Y zX`Q^!PMY+I6et`_xMJRE;(lZO#Vfs*vf*mkuP_$lrEH_FLb$q3r9X50`xk6MBUd;a zu1eyO-s9!gVMN^Eo;dzxxVN99y+F8`fi1($@pjDOVPN{>r6Ov8aWEZQO1LOXbPUT3&l4!xiY;YM4SC%t^U!>*I{yX%>n$El+Inz()0_^kWt{VUej zlM`yQuQm|llZ{h%`}*JKi@auaieIr^I5{rMzx{vs@i!62U1NV7(DlciF1a4&7bror zh4BzSqj?^1;*bkq-i^2!Tg&>*sP6l*&sX^#YuMuVV@3P9E<<_Q!0fQL=Y9+FvZ;~f zANfr@A;sGp8}Ibn$Nw|gA=yIv#tz1Qp5=!bOZNR(H`&h9emj9RyRu*7leM+C;3>`btvvSXTep{iTBsP=A;Q}mv#$o3c8%L?!OSob`l;`UrY~Ayr!11SwXEr@zZ9P>y&wB)Z zzwkKNF?QQ)ARbVHd<*lWb0M}j)^8p)cy2e5H+Zk&uOWM*cmpHcj}`1|G9h2uXz*}6#t&6s?rm~h4OLW6MJ$J+6y*Ifqh!I1kI z;f8I^k)S zDEp;bnT{vRj;BhI+kwTyE_?mB$@=;57?hXw^T)Mba6Iu*+4y>G@}^*7%_jckJCI)vcO%i?)=Y0+}OO@+M6?r`GJkAAG-6bXGB~r zQyZ?P8%HIl?eU?A>!|Vj$69O5R~-TH^A7JuMcn!t-;*BK*jWyzCbhxM7 z^Vm-!Ze*fq{uNIt)q}e46nCxiono!V??5}beOWv-+AF)v5i}OM#Xq1 zbZ2dL@ag3JYv;$IRhR#A_S*7fgyXX7PLBn4IHnv`(~9xhrQOma_Zt~lSJIy z$lBy>(8;^wnCTaYxWxsvwc`xOW$o?LHES#KS@Q1M>=1qn^A5vZ{bH^nuh+j(o4j$p zZp7B@U)*Lu#dU_%OSR=+*A}QJiwDmO>vgy%O`h2pgxe z@#OKlO*pK~2vBKQT${Y1F3s)uKP$saL|n7F(Rk9W``+U2Rlc_vzROhJs^iH9FWQ0K zZ-0E1?{C`8zb9N(r6jj6n-6W>u)1QtSqRsd*TJIXw_=s=Ml}wv4Y!f6SF`;4uTMKx zti#xwO!InG`#Sl2h>h3ZsPbK|;`-X;4c>-!VDs23w|(#+D5QQyahB2fZTQkkzj=q$ zmLH;nP)`;JCocMTCn;g!U?X|M*JIr84ae->@I6>X?q`VmWpkVzdWCBbIaFhLlOqt9 zwTp{B`L3c}G+a^Jx^jZsm$i-ed*5HNer6`WksVwop}Z_V9P-&)ATJ*2I#llZrnt_P z;_|Zj=FeNh#|?#_{f64wMP8TJ=T!OLSGvY|K-$wBzdsHBz2f>%{6*9JD`<$-D37zY zP`zkbx9_VSw2_TQev5Nl7H2z8nE%Q~Agb;%!p)}f`rGz!)-G$`A6oU~jcg=bF&-R) z(Y`Dmz8(MQog##%#&z1r3(fhV>BC`%Q~U<^m5X0do+ST%H*0UVK0jfhxW8#iZSkwk zLi@7$#nso=_YiT->SSN>xWJ*!?RfN&zcDjQ{fux^JkD4@^wIh|Ywm}{cnIj?;onCu zeNPm&SYte7M&k7vHbC8KdiX05*Q^e9sM^mLyl7w6&u?4hdsMkEYs(Mu=bG>D`{J-w ztIXsR_Z#^wqstEqQrjFWo@Z7!!VS%CzCPdno!=|&-?54-#)GRXwpVsNYth!boh9Pr z=hSH5Uz+>lcTfJJqCXDRxNh&A(`*OlU;dmZuUXy5zEN(6-2mXzNguOrS?Xtmo7Can zFyMl;6et{Qgq!1W#^zbubzQPJgQu7hW` z!+AIBH?P020N2UTV)?c$>xc4VF`uz`*rVqi-)+FWe&rY>)Oo@`y};Q8b?FSmOcNtFuOSKQ^f1m$J(*tdS$jSVBD zenz-?-j25hw0MVq^^*dHgN<;tgD`$sUcY{C-)Wl)*L5n|mrX3@9XF?Et+-p6F`hAYa` zz~g~6wCA5#{+hVotZwAD^t|Tr!?Tn69%Y6j?l;11)a8c*F1uz6@jSD-5w0JQn0*;w z_^-EqH^UM46RzmD)EM+j7dYXuzix!6EB|F{Y;T$u`!{CTc8No7qzsj5VgB`U+#><^ zxI3>tmvHkf#I=Voud{Zs{*P}CE4PAqjqEEPS>Sn{tv_5h?$!T_`_1Y`xb<9KmM3>S z;?!E^Syie19GAsf??-RWR6S@T8;#_Ra$Ghsp8QLvlQ#lUb(axtLWjH3@x*miPu|Ez z!WG*^U;*X_X5TyNdMp$n>@{AG4MGNEwq^a$$188y6XMqee`-;0%kFb@>At5nq2KUL z77wl@%FE^#-@4yCn#rpFc}CT?4inj;xxeW8+lWne-<6MF7u^ShTz=3y(O+vB1>W_2Swr1*G}EpWB{?yVxpo7umG^EZC}u7KNT`<*{ElTX}l zB(HV=%Ec~RtUK`IMdEp8bt7Dd2glV10zmGNch{TYi2IFjz5F{O%npz3*9P(=KeC1I z*NE{v$p-3Q?t7k1l*g=YB(F9W$0eNr;KllPYhL#h`CUWNzN`U1k3D;Q!`vtJ z1Kg_X5AJ_8_ZLeqshkfLnrfS0xOtobyf*2&vxZ9v3kMt7A<5T0S-*M9@pCK2lku-> zlh@AQ`^OCX%JwJJa^0z_eYNA!zR)de_w4KZ0gAF;;J>xW8_>14Cocb}Vt!FZQl(;K z-;~b2cT}-&u10wsr#0u_LkHbb-BwlPq)i}i)pP7R``%y0zJ)e5Uia6v#n~AI=o$xAL_rYEgq6OdB45=tcv>)&4f3yuZQOcc715d`)9&9O8C|IJVRKQ z&qi-Q+AE-%R*mfI*X5nP=Uv#_6i7J02sfhZH`Cv~Tuc8}HGZAPV}95YhUXm^P-|VUt-PL3*QH-wfPYo4k3QygMD%=hYhIt$Ips0LB^XHv?p)y5VDq;VKI^@|h-+2{J5Um8yH>P|^hj%V5cw0j?>-DZ zu(Cf+uBoj*PSrPGFI=(Rs?j2^S=}few2Pbji+!uagY*2_@>!C%H+Fq9Uz@yD{pR8A zjrr|}Dt^mblvj*j?Mz(PV{ta@;Mo=9N%!p9;=!S_?^7RCwzuFlrnpt@0Iv%u{Bz zo4ol)FwT5{`|N9P^&$Ie9?SMEv)hKsh0XGIn)Tj)Hf-mAL~Fbs+_M(j8=DUef2VRj zlz*Z&J9uwLJDdc#U(f9a|6>dCTDL>>IOF-3#o0xXbMAwp?3cN*w)Uo7f%3u)(Asr( zKDChK)edUe^^4T1=KQcv6~841)n;FRs9D|#kN$Ec$?LK%Z&myHb@m-p#lE4NYqM{T z_s0i-ec!%$)^d{9YhB(lKT{yI$h6Q74xJr3SFwZd^4i9~X}Dp9=2?Zivz0H1Dbud90@_uzZ%Aj~ zL#x;~^+;{@jp_2kJ~w>Xe7(@qvV7+3+k9Pm@zu^{qNeeQ*4l+Q{*8lm$iDrntivSC z?|T(RDb@3Q-oo%5M;*jM1B6;Ys+WZ!+$M>JHh2KM7 zp1q3X4O;IvMNvw1pU!VftN6`7$(r9p@CIEzyZDf#amfb?~23u$c|H~*Z zdp_&kgLgkyWKO(c?Rir%pGCLBJi7}3etr1m758m7&aj3n%Hx=T^0N8y=r8xWN!)K% zH?nUYMr1UOy5-2;ABs5n>9zHnj^nUBZ3lquZ(2D<#EmVi%??@w^EZ3`VnFucp(3tX z-OvsT&<-r=@Av4cllL|Q6800W7!Qehw8M^Y{Q6TXzt~dKd|-|`uy6fbf;MQ(+JnYN(a9syuJ7)J~x{kgVvYXt`2-nMTS$}-Q`Uv!*az7(n zXB6{xCx9DUx5aQdRAW1MIc{eFY=8Kw-8U6(klTT^N^*(w+H9M)FQ9ML>o@H_NQ_sEuDNs1r2sfmQGoPbF z|4oG(*TvZrBi?3@&q)1@f-n6CoA8JV#Z^Ho9B6l z&4*6h>b$qiaK!yaxLF>*EY6OcwD*zXd1iGZT;J>1Z@L)nub-?Vi$x!3**GdtEwfK#l4^=9EY>is^(+8-PKe<+|{NcbMO6~7BPc44x0=4+Q0c!D^2CBtx45`I; zU9J{CbA?*`;FW6eizC$H=bluHAAUwHzWoKY_$kHs4KJyczc52Bep6a4zE83I#og8R zzur!2@jZ&iKM}WD`9u4w#n0`d7T3(YMlk^_0w0(u|Rx5w-UbXnKN7drHA6JX- zd{QmG<7u_{_Gi`NN4`{xAO1=WKHW&>>eaQ>ew_y#SSs^pVm;LxOUGGQ22a7#e+HI? z)3MB)hGqOzEa`d#U0(%4H&r3MckY2(JiJrwJ|V1Jgb+p}k#yj!FuuyGz}u=2EkCpd9wxuGtF`$&=9r$4GvX{pS(&fe$xoW_(8S!fnjR#n;uq+ADyNaKQdh{zWWrl z`6qI!TKw!Jwf0FqpcX&>h+2HtX=?57|3t0)(ba14olR=-J)fwxfBjmu@;Cmf7QgVB zT71_UwfMnr)Z+VgRlB~?w7Xh-Pbanb+0JV5wWHLIZv*?QmEY%4i(h}3TKwn{YVi}t zs`YR1IJNToPgINF7*vbj;8csB8=w~7HBc>n{1vtROMZr0{OC+I_;mfNzAaw23bn(s z=)lswJ(kg*4=AmFjavM~mTK^+eFYNOPGVEBblrz#dxX6T3@pRX9aP#LKMU*bv$4$ZGSC<6#XeXDc}e{s zjeo*})W}cxnZauD8*fxQzO`SbMt<_I_bT*HXe5^2_2^goaIEM4z|_=C^24jeRJ7B9E%Y&pfUc-|>W6{9uDx{M3_b@wKPb;`^Ub zi=TW}Exy)C?f570yjuC4@2bVmtXGR4?4mY*ruI>bukEWAzdP3=qZZ%wvs(P{FKY4g`>UCMvFDBthkx{3HG|bIH*3#FGkHtT<6C?_n%)NzGr_0vbNXR5_9y)K2Ws)P`_$&2{H|)_ zKQ>+M`mkH^`;#5dtCc^xh1&S3_bB%7!D{gv4^fNnK1?lskEq?4gwfOD}72~g08=t{JYUS5LYVnhosl`t{t`=W=LM^_( zK`nmrNwxUCAJxXc_ZhYF*FUEgzcHm2-~FOm{P0<7{hK;R4L;3tY5sV*#rKcV`=gr9 zv^GDb`KHzP%MpGNCfa822dicNPVawn9cyj=PWI6(&aX*+kIDP-$o^y>tM5;v^?`bm z_nV3MlO*ML!xv1=>|e|K+35Xs9{9qf6@0S)T8r|NJp(51m%DMh{+b`waR|Tg9KL6< z_4fVYy^D2PVl2K_kje~f?*K< zPxrS(Z^h@FeYay77>@7Zj^BiJ??fzJxA6TpV`-0LnY#l zx{F%;$Zl%!v%9OsckZbcKjc!2AKXhVerj*E_*!SR_yxCGd~a8^_|cQp;^$6Qi|^{8 z7C-D$i=R0~4L*%;-P_>(_kp%pMjcqDw!_l9BbNE?v2=96vbYtN{%x^Lx5rW(-#SiH zBR}ger}jr{Opx#@k7Ja;@d~5#Sg%ZR4Sj(ZMa4)e(_qh_`d7Z z;ujR-d&j7iKk_fN^E=1BYVqq8zhA{ZSFQX_3)SKWw^KX+^&F@+K0Q~emEY}AE5GXy zwfLdK)#9h>)#7{4Qj1^TS1rCLpcX%Rj#~V}4r=iu=c&cdT&Na5*k3Ka|4y~|iAiel z>+eyE-*~TD{OtW|@ne^(!KeAP|7V;RH}Nw13)WL>v1}+}nO}!x=zmzoe#Fwpw>$aq z;`};rhZ^~5ejN#`#do}^7C-!{TKvEgwfMfAT72*OYVjMFsl|6Us>RRjs`mPLdUv(> z#l6(xd%LK`uXn4(ckizj->3Nb&B9Y^=3jLG9^Id2_5Mt{|IO27@hwXl?^@jT`1M6L-b=lyp*Ol&{q&Ux> z_k8L2%;d+be&03^+u8SRy~6kFTix?`+4pV3{QI^+*v{_HY+QwMP)Yvv9H%z_M7?V8 zgC9Oo)jm?S8DN->(%1N{;L*0`mI|0>?dmR zwQg$qcZ&bSQEKt?$Ed~69j_MOb)s7Q@JVX%(^sm+4-8j}pB$wY-+QfE{QPxl@k2MO z#ka@Q;wLAl#dn3&-d~-Is+GU6L@j>oJ+=6e57pv3d#YIM&XSBu}M*#6FQ)ynTUUoC#>Lbdo> zP%VCPfLeU-Ahr1Qm#D?}O;DTPB4;Wd-wsi0pW<6;@#F8R#czCH4L=M2-B^zc+lY7T>#CEq?w>wfLzY z)#5u(Qk#F=qZHpi-$SkZfm77t`%hDgZ{J!?{80XhZijitw*!_9J7O8}?NiD_pn{LsN_@v}qK;s>u%i|@KoEq+Sz z`e)!JwelBURg3T5Uh(*Io?7`sZ>Yu3_EVexL+7f+w_l(Zzu_Xa_=N##@#BNk;y0$% zwy)@=YUOucp%ysTMy!OD%q8fm;0Z8*1^JdZ?XW_}^43zwd3e`0;nt;^*I0 zi|@Hcaelj2Eq-paT71{_YVku+HTX1ttUr3+(mXN8OV6=b4<3i5`*7WzpZ&}6`sp$4ezx7Vv!;16_DX^OAi2-e}LYz!wL;!UELKDqm5OFT?rP0pDG~mwa80&oRSVypa5! zGbvuy+9m;CQIgMXkuP}*&Q}_*#QE6&K)=_4&$$A>cSHNl{O6u&O+UhO^g;dp1im+z zJ>Nll(ta~OuOwfT^Zf;U3z^wpZ{Gs{bCmR(l?<0>W8EM>VWS} z;7jF@kM^6{vq_RKcNY4u74W?UeD?R`_?)w>#Y=P#ydOL}3iY!A-%{X9b3WQ{re9E! zFLgHR*BbcV0Y1n3sGn87h$Nq@FY;{xeD4BZNRqF?BA@qVj2G7ov}YUO%L8BXW7LoK zo7por$D02(;PpfOj%(Mk^-ADt_(YDcNs=$j`Ht$@vGpq8OMNQGr@gju{n~N^Ig) zFX@ou%bW0#|Gby(U$Up?0lfbuJOk_YSFud;vObOV94|vNv98U+GQmsFY^-N_$?VU5 zWKYlen9l;&A5h|*8rN)xcZBc5KZ^R%emo2R_d+51&wh)w@gU(v&qaGqO=-4nz!!Q< zj?X2@S0KKeW;+7-!qepV>LvMt=W+cCnynuAB9F`Q`6c;s#OJ899SMBV>2iD_Nj~rS zTt82p?I_@jJt4;zmE=nipTEv_H1O3o$nnJk9ZT`8k7NDcVta61!1W8)+5QcD={|d4 zyX5Uff36oQVtYtf)X)7Rwm--9$Tw!u94)q$rsdB4SBa1IoAEhUTWf#0Hu$_#VG{C< zS~gF67Wj&nAs_8GGf z?KtqC?dMNn6Doy*lfLkFP%m{+HaPxJ-1rRXB+Sap?(iJTHDS5zRXNH zKA%Ot(8Z{qJ%;)PV7=!|;ET*gKH6`lUqq5G&-FV8`1$}}bdDTf+#;WSFzT1M9rZgG z`1%50(_G}E{bu?#O7dj}qyNqWzJ9>x%gFH+B>6m-Am91G2SZ6Mut1K_ew(%UBzq+} z-vz*T4)6tEm*aC;0b0F{y0KUXq za(sDNg1V8w`A@rE+{;Nj}#Q zva+BFj;~#7C&#q@3M$1@P7X2l;5fnSM=@e0i?lq=MZx4EUNP`Lqev;*;d} z4@G-Ua%^P_17G1oIsKfHd>P{NY-PI=_=?Nq_&gT*Txne2%{HR{?n`ZD8xDMdM&zUY zX8sFWK81fAtKU*6Ge2soNzQ(*9UzGD* zHD$II0X~nUeg%tsIVg{^EOLBHU~a`73L)Gx>RuADJjyB74zOZqQjF+NE@@0DCX$JVw{pkG>2zXnPD zQk?IqMYFZhpkKYD|NN5vb6v&t^K5O4fPRiojRF1QlJS|6)Gx#N?vHP68x8t7Kb4EmdP)5}Be;GY=V)U=zf@m2|79ih zOLD&ZQ(N1v1O2j+`h_I*bBsj&!d>QQQP3}Xo}7L~N&TXn@BZA@w(CK^$Y*l?OGxTh z;Cxs1oul0V`g!}v>6el0AA+OMo(~kZwv7S(a+3OGCH2d3zN-e$(QX9&5|a9PS6OTC z8~VQp*UzzyZ7k>)T`uRpyrh09&NqDI9PK91&nMYGgeCQJUBmVBY-5XpevOj)g)GiD zDSyT}Uu66oZ5-$qK1VJ-W0Lx5*P?z8`nR#&0Qz}8m-AmjQok_gyJpH9?Pky~B6&SE zEva9g^b2oeyAkxuOX}yIXstbv|NNuTo};JF(Z+**MalRKd}3{V!Z{1)fALRn{&y*? zhujSMHLXDZ(SEb}UszH<&vmHZ^)u#Zw}5_r$?=P3@p?GPpX7X(fqvsbKW|=6znDe+ zh%d^o_YVQSTYxVi$(OXqNAaRvi1viL&ZD=2JvGVkgh$ez1+L%apkEC1D@f{>meeme z2KCzk^t%o83rOl0v)CT&UmRY#UX}S2+rtC7wzk_rzv4=a7us*u9Ip-sh{U2S_M7>yQBuDs=NsAgHSI3YFE6Q|%c6eXZ!o|3S73Y&1N{=9Uv>@p zkM^7CXOCO6C-v{ao6(-5M!u#^0{t8Tx%jM?)Gx>R!l2(&(9iXioPPC^`gzB5{l>qh z-3|JMB=rkf)Gz-X`p>zN`iE_853u-bLj7pJng61a`nhgF{jQ$znl>5q%Sh^%kkl{E z`4aJMZ4ZKejgtB$Eb136pgn!7(4M=W*~yj!zWmo{Pug#0&#Xm0-|N^v#5x{W8mA3u zGgrG8?3v~BTiS2N=lIfE`y=`DG4$VVS9P*I0{YeeS5802x7OxkB)|Vwu9g7( zTzq~@`_1(8TGWs5Jh$=o*JZ9Y75ID?VSb_gW_+oLHG2|XlJgDkHdnh3_==KzS&Mx6 zo$&tTaE9yGZL!u7UM}N%1ofl+X8JX*wWeQc0P-alAm7#N7Hclx%T7l=+Hc0^e8L(Z z+0$`5@{Q;|SGynV*$|ZTUs5t&f)kK$c;C6&1Hc#PFUOaY*bG}i_=4y`tUv7|`e)g~A;w8`d zhOe2cO#{B@U^za&B%eRdu~7tPb20Y0DP^G9Jx{la|xbIh7~+H=6yFhtItNlCuo-RM7fR5bcL@TD%7 zwdr-ftyJfVOfUnrPb7?+7?ZvFUM=bJX?KmFv?TYzj%=nBp1Nd@b)Q|R?@#Vj> z=D!ViQ&7LrQ!?7Cz!$wzj;|=m7bd>x87&Qbv8&|x9N)|7m*;%f&&X&qfzLNZjxU{* zurrtL6CIlKN$cZ&^m04Sb2=a(rG%K2HMm8?z>(&0+Q&A;%Yx}d zxPBs^>jBO;Wxlou_*|pq_?#y86#3%BH+{ag82H@R$?S7wz?YZgi%9Zih;Q9| zZ3*zzkCC%y)}lQfZTb4(o;<&FTcEuQd`+B>_UqfR7b@cWATk#9BfR9pXwTu@7ic-) zON>SRXula>qa>dr$^F-Nf%YEo6(sozl6+ClH+=8{?S0_$&XCj3`x%bwdAL zKYfArA@FH4k&pJ9*|WYN$Cu~x&D~-A@)7X)Z;;~)N%G|$LI3Rme2u`@Aj#*MCa0hG zQRExDW`XuGv*(R+`XwawOL4w2>lSFA0AE0oFD1$6dJOg36YTjZ@WnH7`eh~g;+)R~ ze4hcIZ-E?NUXo9nhWd2^zU9DYze$cSBN;DY&bJrveGYsXwT7oU)S=$=NKo)=lD^MFT?r%1^TT7zFbz0&n?O4nU4B(2EJ9mmyy)Z zE6JDSd|iNVHSjrameVgF$>(?i_1g#dz5u?kBwtLDFUtAGOn+Vb68N%`d}&F(0_VGa z#_QS|;PWn#vuBe)O}A=e`B`Xuny1>-ouAdmy}A1N!fpHg9PE z1-_^xU(sTFCqD0!$ma&CZ-B2+k}oK!UyAeX3w+-KpC=|~&xjnYT)EAV{>d@)Hr z$8>A{Yj9w^WaeSK3?2D~Rsg>GTTwsSZx$~Zi~5BRlY zeltF8k~RGZFZ?vxb5h-Ywmk5KC(H3UE%L?pL;a%vL;XhCz<fn! z!1pWg`BHNJi%RmPINy!HR|LMKBws?3&-DW8cN6ff2R{D`a{6T@`Qn^!9Ps@Hd<~L( zc}YI)Mbz(R;QJl;0x!zxSCr%nbH4Gw_XqH$B>5a$$>p;==eq^?{s(-)m*n(wOY-?& zLVL!5?@!=MOY(Uw@)gd+{ynkfL8bnA@?8ho+Q35z;a5;U+HaO$Vv>BGmr=j5j~r;* z68N%`d`XLZ8^(KlymZC*H?$vNJQ#XUZanCg9Dh1qLH$Ndc|-dN_?jfgpN$sBpQK-u z^9`N;hW0b?xjvB7uOP`+;C#bpyrKO9d^t%z`_IMip5x5M`5T7cv0>pL#g)&rmKcGQpdo3+1?Bwy-PwC9*E3$@>X zFDc0vwaAy;9`#EtMEyn%Ua0*K`275SQ`&E)UsjSYo<{vfja;bx34ETr(VkZM@{)Yo zOwKocq4pQ>#U%N{7V`_qA11yj3pEYy_pYBTr(aBxFHd~a7ix9D*CfeTl(eUR7TPm1 zW1-dx_!9TX>F55%T7F4%!1#1zd3>&0sBHm!{(F&+_M63L+M+!P&oi6HOPfVn8{mt# z!~4N#zZqXnk}pYo9T#a^0$(5@r(amso^!Z~D-@YVDCv#jdZWHGoLZ4clJJ&t^|-%P)#B%g<#S6j1K z+Y|VllFzFpB>4(FUWT{HYMp@3^@N;$DM>!Z>*&9D$E>y&@Z}`=vKILQ7h`;;KSclS z2dT3&@Ohp@{b;|L|B8})1+L%zz}E%%@{)XxU#+zVl0Wzc+VcS5+XwiX_Qrfo`_1(8 zJzX6ufYu6L09Ij-MroJtgNqw?%uB z{N9CV&kU?DoeTOkO6u1rsb7lo9R&LA3;Ovw%lXf1qF+P(ekFSs>iBod>bKpf{q_FS z|LwaF{jT38{(TB;pzBrSzxX1wrw8=w3i^4Umh)f0L_hkTTX8hXmzsm6?=>v*yo}7n zx?>)e4ZQSbu-?ea=#5wp&&M)*EtaHf;qrsa?HAv+yiNz2l#z=#?ndrUu4d0LKmK5_ z=YC+%X7vs6W>LR}ftX*MjhL?w1^o^L{j}#$KiaS7^+H9w z|1)BuAH^r(CEvvOJPh~_0=|?aU(zH#iLW>a^~-;Z`i<%PrgjMMg;J;=?Kjh}Ns=%6 z7V3B1;5W5HfiL`m9G_OS)<4kuQQRF+zmd~tYUjdwPjO4+qy1+3Wgn2^3%-r|jhr!4 zI}iAR-Q@U+l6*PN7g;n@J0JKQN67KHAKbWpl+T*lcuILCWydnu1xv>^SbE!H8E%JV zvOSg|2bPKLung{iWxNBHnH{ktKTv#^n;v1p3*xmea4^L_d))`X2IKJ9w5h82Eycd{K*hk&iK6Qg@*KW0sw3`xfHGw=c#E z?MJKN|6VA>cxjT1mjc&s>M$K1BT< zUUr`CC(zHnznuRflKO=?Uu4ECZ3yU>=_#jQK+=DC&iBB&^K3tZerZYl;*$FLm!UmJ zE}NxY4*EHJ$>|r9)Gx#N9`1O)?HAC`ae$ovJRez$7wT_4AEADu*38m|f_@H3|0N~$ zOLD%4yPa=a3;Km5^=pvypQDlMw{Dhp1?ZQR^j}(1zbNN>sPFlJm2;!=odavE$s;mtVBc zP`|7C&enzlpIh>KXAw#L!kq8w!Lzjyz!#O|Yp}@YTyRKfJXrskyHp;t^e5Y`@RGO2 zdDtFkzu9=u|BAKuaYp(gU#Kne4WC}nzSsulN2_)#@zZ`YzASt+*P%a1_?yN{gqK;4 z{u@4{pnVB^^{eIh@+N!&{Xf-BY=QP1&vO^_?eO>JDv8%W4S6?Ld1_sM?eMWM4}5m7 zlDj2x+>r)fh@l?8CJA6Ap zYsGQ;{`m#_Q~THu8g}78|!$VpJ;HBfeC%;g_>kQlda30CyE#P^1*v|0X?@uiq zN9Dgpu;ZI?nts6J_h;k=KZadggL+jv#0wk6`FFMB^xN8w>&;-bc6?)K8s?+K<5*^= zV;OJ2vS~kD4|hF-b^o(i+7HF;z7*CQU&1o*6qb$`v8;a#OOk?W0~!SW$_3s?IZ9#(Sf6|o<9If$3a-SkHk{sb?kuWc{^Yk-Vw|Ec337m zVwu|sOKoQ?J-c8T+!f0rFWtLiJ+KFsu|2UQ-VN<&6>mqIsU$mRPs8<&cuy=dy|DD1 zjivouEDL8~>FSN8|4b~MXJMJ*>uikytS3&zvY{WAr0+lFKNk4M0{>Xx9}E0rfqyLU zj|Kj*z&{rF#{#umU@v}Z<~h86nf(#hbAs>QWV-=Ag3x$Au2-c~xWCXH*N5urT5DUv zOpoS=(e)c&_ah0Leye_*f2;EC@V+HGJ16oX@_H8Ib#_<7#dRmc$0M_Ia2-3p66Ga) z%>g@ga&6eYiT)saB?q8f#h;M>Ojt_n2J2sq9r6Cu#`kf*Ybxr+?A1djm!EGp6U#HB z+%9xH;ZnUM7vML{IlQz^5&s$G>e7Ck?MCpU=Yn!SW{yHXIs~~I`F6rJDqVf5uM;MO zH~>GEe&LVM9)!pI*j?vG@-yw%wzF$qs8D=u*lzHL=bh?y5)UUH(T|y5&|dG_mup9W zA3Zy59zRBfI1v39Sc`IX?lsPK6ZkQ|nfz!bSAolQMf&2p9^l8o82oM?*|(+fWfb=j zp*@IxjIBd^{oq`#)wA{QP3*^@z)$f-`cj?zsPXpb`W5ABKXIIG9Qd*R!t(Z5;JDig zdDZ@^wYWBFk8UB~lD!(P=~l`UX)agc&5P@N;K$(Daz9cWu>5t4E`OzjxFx;C(#VhY zqs#LL$whh9UqpNT;$E&D$*wCnH*I?~@}nmBSM*~OmuuVa$JuTMKSoa8JbsKB_%Ze# z=GEwWwAZemUR-wy_|f@#xgV*&sI?z5vX@zVbpFQuSif953j7$~On$5y_Yl9-9(})~ zTw5P_vu!;1F}{i0W8R>DG_sfTGi;ARKAt%EzZch?3Vw`@+dO`x_@MSHw#UdHXs_>m z%eAAykKUa(ZF|i9yF4F|9AciJabbafUy+V;ZMkP%5EjE-NqiooIG?}Yo(|X?<3e40 zIsS+CYCG{}+bs}ZO`9pcs2?G(dDNoS6HL(c&c-P3~+Oe$P=J$2{EqOxc z$51Qu<2Jp<+in9t7B-U~tMo&q29f@xyj?Lr_SE^2{Jf#{NX~107U#9Z)6zVVT~@Bo z2Dw}KhnQEht4t|X8kK>6A>r5@24;kfEah-|sR}=qUdTw1A7 z3;g}mWM7Jd?Syp`moT3(GMCYONX%c9C&(Xmp1)l6pKHfKd-U-4fK;@{%`wga<;Y&H zt+~A}@zf32w%J~p0k{sex$H%L3|@uto8{|;9p4{sn*i|@>{;G#H#jgav-!|s$S*X` z3G(em{-fmT0euM+~exgT>c)9N$xXQNLg7x|~sbksnBY%JVEvdEp=VQGjo8 zmGW0$Iohkf4*fXn)PZ$=@T2REaz9cWY%j!@Q&?Xx63obtgiGg9+|#;AY%7%Oec$KW z@!-ec?wD7}zBJFPbsfM+E-`<#v>yt*R34Y4uWXsv7wtjkQG8K*3;%`lj)(dVtm_Sa zbT33d{w?tZLXsb&ZMh!{9zRliki97GY2BpZBE0`BG|E$VG35Kqr@NQN z)s*iGE$p|A;>#$1`Hn1)6E;+YZ;@!ZD>{|rB0V;gaFeSSDys4X_1hG`@iyqkeA~&k ziIBg-AL9L%74fCG-)?DpEUqZG^9Fmi@DDM6`P!qs&V?c2i4gaN%@p@hVLhAjgzwdI zy_p~H)cKM8yul2Tp8w{N;QX*Y9aOQtNm%d{*`RTGfwi@W8Lv z<~pFgdcQN-HVNXZp?`UNZLV=n$zHm+5ABF@-Sou3y0am^8r$Lci{gv)+SK`r;ub7a z`n7aC;Sko%2)Csr*^B&`=!o_@z5PA5yTOm{rFeaa@`NfsR$XV(#g}I%l_{OHs9k^D^lmmN<;Ek3VF zJfgkayPzL^6YsIz1AYu_CO?YyBDp9}M7Bk_hJG}#F2M5YW@?XBuRnrwXdNK1E6Vk@ zdxdri_%U?|_S%C)q9g?1|V(SGRW@gv0twRh2vX)f0Z?Wfr81wW=YlOMgk z%Ex6b9ZxiNKD7FJ4=G+_S+bX|J!W~o{hn`yb{hCGxS9MI71k%nkJJw}?Sb)iYOg7_ z1o$yDu)IC0>W4(RXgopw$nbpcat^9Hm*v&JbA3WL{_=G~dv%{U#Woe}u;H->Be970l4ma+pC_sOJLnM_jCEWud4VG^Lk07{=ihgz zh%d$K(W1Q?_C~pSw7=JOKiDfe2;*y0&C`t53&n8`wMU=0E(iANrLz~=b3-6VuKQ*z zUKb@E(O&j0Xs^?H-D`UQ?3LZb@nvK$%8R6TNiL|+cs0r8%4Jt*XMnvjhv7Jf^q}#G z>hUW1(eYmSeW3Zr8<#t^+uG;(ZFFkL-L%vs=4ApLj^FL@#__5Am|DiM^}C zQN;Il(Dn_b;_FrvUo@Vm-v{H%H}PKEgAiYl!R7s9OY^-^d=W0`Eyh=l%eA<1h31F& z${m1tLUnvm+?L6u8&8DXXskamD z9=>_nqc|?4_@e&N$>(W(dnIfSgS~vmmB*JVdsSVR1E*5{a`1lWt>OypOt4pY6Whzk zk7C?!#{(_G#}Tw1O>vgz*GcJm7F`da^-fwZqxBY=uhV>w<_k0qrv8`u6>9(FCyIN@ zU)0|6d>nmuo4nQs?3LyAsu)iIfEWI$x~@QS1s^CM-?1ioApA=XHF(dF;=D?7(KyDx z4d#h&;eMth#J&3xjQh=Pua=IZ3&M4AF!3h&fxSx4{d!lUA3a^sURortodxlg7>xO= z!d{BUt0Wic9o!G)%D27G_6YdVwe0V?uY=;NiQ8*~6Tn_)>+D7L+^}DAyxM4Syh=PI zSAKSRdt~-{RA(=;XRUHYEZ#psJk&qZ^+%Tn{W$d2yw(@&pt6KU@u2o%oC&s_518Pvi`ZuO?@9S*^Bze%mFCZom2B#Kd@JHGuey$ zKygCxMfPxWxsF?UpKTi0tMQV*C$ExR6hHC((Oy%h=d}RXtC8EQB7cEmUihb~f7}pX z-{5>G&=cQZm+AO$-3c%s%3dwZhxmPbwcfvK^gN$9-)?C?t7&2Rx<<`$^*Fw-m(HjB6`flizbw9{ z>*9;zkIs`_H;G&9w~2@3%I;g<-kBfI)%#Iwcaq~Acfa!MQXBLW{-AiGyh`)ha6QIX zpLg!JJpuOegs>kXJz6@i^%y)qAm&xEJ=%{%xo#-twey(0_;XF9$L4B}qP>z_E`R$6 zYz<(q{ARKj`GMR@a&1`uItuMI%)U}PAM6#Y=kpF8Uo>A=eV-M{Me&v6a-G`i0o#*c zuciZ0F4gfx`j*)XD%o!^Ph{40EnRUt1 zTqxSh(GC50_QVHlPceI4x_R1TmFIp-s*s;jhoW4^wR_O^G|1(>?C%+`mh1(RWxhi{ zdX7Q4f=8{?E&@Nsk1UUSO*byw5*Alzyy`T_OXNQ)jmCwdA6wc#=H`|6U&P=d-^PBv zV&0*C-K3-v^)vayP_C(cS8DyiUf!d4e2MRIgR{KwkK(HYvI+mA@q}xBd7LnNJ*%@9 z*>eN6kkskUyvABjj zVU+Kyj&lIt`8vu~JeJFK*F(1FK`!4A%&V&9B7Mos)E>znK`xgowo)4aai4tT@0oW{ z+{eEtj}vx(&Uw1~bLjpZ(nofDAF=q{3Gt9z*%QjIi!ys%tg{!{vsStMeXNb|iHGt% z-CtNZ9^-3m*FkmXgT3O5@%}>6Bg*g764wh``o6TPaSukIbGW()Un`a*-d&9)5mb+Wp-I)m;Gg@@D^@`!QRZS7U3++slUdYvCUhU*yMB zcb>myuG9vDAMIYezOCAi6t|=fBRNI5j*`yTLSBa$@Lgt?pA0|vbXB_c1!bw z^Q7|rYlEL#_(#cJFwV(LMSG-x+Ppf78Wfb>fz9+e8 zeIk4sw#Vy74XW!8ai8G%p5l?#U244##%Nqf>sMrE%3tJ9M)SUoFjF z=>y8w*EjfC@{gtrwl6wOv{&&s9Iw6^TBThM_6lq!dyyYVF3J<6ck*y5baIj0q>pTS%vl^y5Rd3bJGa*mSYo;Y{AfRR)5g6~KSbjJ z(wpR>>yO3W=*RgV4XPW=@+!aHL3&VsvALeZr##SjD#~@&lvUa=uvd`Vt0KNYF)#d6 zI{t!wi0(IW_d&UC{%TO&C19`cuQ;BlW-t9ZW=pTvk{`&AEzMu(@bbA+VSBHugiR?Nz1U#`^)d-a#JsF8gXN%<}4EfA2Vl;>&v)=KFD54z9Zt z>=oEd_Np?kEqOHET^Q$py{^>Rt0Imh*L|ZF$2r79`HRLA>Ao0WIp=EaDv&Ge#k@+# zQ$MD9Jx7dte?OG#wtWWI4FNyemu%X&H_G>7o)GQT#N~R|y;{2(?3LY2_98z}x*&Ve zb>wIO?KSa;!F88|y@Gc!Km!kzBFCb;BUO67&C_@dU+vuu$#~7swUX$whK+u)Acx9qVuH zc|PJ1^J;Vwj&nZDuGS*p$HxCh-Ic&OQJ(J^W|8$;7cW+8+q52Rt8KT{YHVwpYL%$4 z#(TBarXCQGW91Bp8V_Kxx~^3rc*c`>$CG$xt;&kBEFKW=)B_grSUlKpDF1izeovhF z$oxrmGLzQdZ=Ecg%sk)oyx)6$-%Ji=zY3iZFI>NY(5f| zKKgO0PP6O3l&{S5g`k$@KfAa>&zA>R=9SI%ujc$0#@&3n@T(oe)d^%@vF9r5zp5vg z$L(o4UEN4G`(++sT*-6Ie=oJ4F9y0I+KKqI*Rph=QTnBLo{javO zS;zL}!_`T|7y4fqhcS;HLVXSRFT4F5+213-M?Dn!1+Vkn*&EV+O?&Tjz_Auef3V#oN@%g^iX;!$b_(DCD61Zlp9Ij3#9nqI7q@$C4 zIq-#bzNQh(*AcBT?GfTDKALp|Up->|vE1u?&_UJ_eDw%iGkS-sQ;09`Q=CsY%~!#C zo8}exY6&r4Lu+o)9wok%G4Ajs??Z-;n2(;3jBECQ5o%bsFOh$NFYsM%yO-;2-~wMs zf$O-|TeQcBuY^l{!7p0bSM&_#Yu2C<>Qv$j{R!}e&zHMDVdW>FWA`Y=)mU?@wt)Dm z9&5HQr*uR;1HKR+!ADn+aow=b2z46q)ls4RUbe5g(Tr#bUn_zFsVIpx1(KVdhI zj(ua!L!g7*Blv<}^^ak`j_kZudz|=6N_^S1d#m^;`w8T$7BwUm&Sbv4JKm-}L40`*x3z!&(;+f9ji zbh60439bWN;6o99^^e1D)1D;0YR9qv+N|y%fIj*`zM98drWeo={wpKw{(w;<)bok2 zt|gpLU>x3Iyq{R_=NR*^)X?Jg8C%)CtfO5&(IM$yCb|^p2tE?RuU<2Ggn9w-m7L9e zCbxBjpTM}oV|hNNI&agSBKvAvT$%e}`l@4>m|x9J=6PIh9qUdppI_(eX#-#2Gk@I@ z{X}5r;^qae106ALUo-3IiH=Y&B>PgHudKg^|EeC(xb_=(yY>w66%zgnwaRP zq2BfvS?3q)ComsVLdW2g@A--t_yV7O)iGXV-vrkIF7S~SIvzOecI{c>D^($X-`DvF z-a@CE=L`Pb?h*MH>Y>0@ysj`}!3gzY(y?hS-xmOWoyu2nUW^Cx5#tU`gkQZ~OOcM< z74oaFujF6NdZapU*V+xZfE(i}wZ9rF(tqJP;Hy@`%5g^SB)DuOiRE zbICd;vyN8|yhD4A_-bwz^`o%wYD1o5>=&lXoaaEt;Av(Zb-pe&@FnwEs*c@7=Bv04 za6#7w!PmjV?$G{Ce0k2TY`%*1w4Q0KW8%#b>I~wmzKio!jKi&UKD&Ok`fq0a^Yg;y z3)nsK)wVG6HFnhqbtdtZx{UKx@a0y14?lr%*H49Cy+eDR?910#nS2#?-*mcJk5uO! z+6x9;z@3+;#Jn(4q+i8#@;aWu{g1%;%-74^A1c#m-M!&3ch=qI{)CLHde*+V`?Z#4 zKUB^mTrFkBWz`2jzYluIxFQ!YU$51Dq?}K^na|()cG38`D(dzw2DJpijOgYYgyCB$}GZFdsKOKw8EuG&ry zI<8Uf@U^A5-6e3HPq=0iu27lzDmHG*e1&E)Ul$Or%LrG>C0z3N*2uV`EsX0z!u3zW zRd;lG?W@@5M%j(q!F~AtefXVn9c8{6W;0*!#XnXqC%&3p;%iHOwF9`4A1hZ7t`3)Q zZON|&FJr!zb$qO}5-!is^4ga_TX>)0mi%hRgIo_q$nLKsTwN~VlKrY(yRSXX!F6|< zM93#%_ppu^6JJ*mUk#1r)zM>-AEIu+d`7;CK4na-chu1LEVfYJBqI7um8yr53D(0i zo%tF&@J{VT>Q6+*b6*a9g9fqQBCo?JWnPD|YhMY6`d`oye6*a$e0hi6sVyYF8YVDb zZtI9T4dbrAoN;-)A$2y{SM>{(snhK082`JuzQcU7dxVaPbbg($%M5&h&;0dDtRH)d zT<61epd-fJa|P>|>bz6yAp7d6P#+Wd1o|d*|6*M2Lqh65i7(W(7zg~H(|r@@82g9W zPISIrGVldH`>Lb&f#RMUh3n+_qIGKQFZ5r{d|h#JNWGl+@($v<1AHOwmwTTmbilZw zV{|I}`^Z&{YwW=J+9Kl1JCXet#!+YF>#qC2VcHJF(1%j+&@=C_FZd6FU zg7|7!YUT_1h+EI~0Uv=j#^oJ0UwfJOY7=}_z~AR2h5fX&GOk+6Ct8WG=6_aZ-%wxu zeTSG|J!hEbG3>U~W1!1?UsGRk;ky1Z;llZFgulnQGr~`#I_GPzkbU`=RBYWUcOMwW z9lnO`%aaVLSCV}tE0j;b-}}yDJL$NAap`<5Ht+>L!E>qW+tDKZJ+1>>(KF5VtMk=n z;0t{A6_;{G;kq$@KJfzAfnP-&>YB%V9Z?h4I*G4t;lD5rr{a*j9}{s1`9$bC#?`(s zq+UgQA)mlF5XYR(CuF|5Zxehq#33Kv`az>r}!2Az1U;h+2;9D?B}-hKAErJje@V0A@yqF%lj(l z6HfDmJOy}R_vlYFKgR2iJ0(BwcRziPRQS-J6%eI<~o_queiqzt0Re+po^oQUhNypQXm3Y>{yY z*OBeMI?8-qHDIKAE%D`ht-N+0l-65d7gqird2~~Zaa9kzOM8|0icMy}igCDAcR)w@ zf%F{4bj=KEzc6_# z^R@L=cWJK^U*YR{zc1{|#r>GMJR0Lp-ORW={*mfjvai&OmFdfYFYG7JiukzI(z~=b zh_ApD^L%uB|Gii8t2$p%17F}XZ$BmW<*Jtymq+6|;0yNCJePIci~RjE;tT&FK7Q}N z6x00*cKarBJ^}xQ>-vQM`oplhwdI5>E_8I;e*qWx^N9I4XZT3Xv*u4A`9kxrK9xx=ty9PQ$28DY+ka9+Dd z(lO^(G49CiJRegv_h@O|?nVD+GrM;M3; zUaj|NZxLVNKl3^=#)12M%Kf|!t2`QglgI+LulBhk)fliH z&Ar;+}E=Mzrz1sz}~h})>Qz4tP%OK55PU$h?} z?>>c$#Xbcq`vPB?uXsQCd-W@nYY3Mw;0`YIJxn^%d_*5p8Owc>wgr2tcj)`Jy_`=V zo}zzN?)5Y||B~%1dOzFOrDR`oh%f)KW#&uVM+RPS#CY+$j4QOBb(}%C<`S-$OSrbg zS1`eR%_3a$2v_{L^77SuLg95v_(c<627jLrar>s_d#dxvz7k2UA7NkcGv)U8a-T`o zG5f8Uk1Z>d>xi$Wqf#AI?)|mRyqdH=6oV_<1cc3-t3e6t5@wn_VonE$KdV!cg!1oecO1yXq`pB4R(xU z(Bget^7l;-vyPV$UpEt99VeBSudc?zI%2%QFWY^hKkN8U!WAQ2;gj9LwWWRAEsro? z?^Ul=ag5PbCG)N^W3rv;AYy2JA*qCho>o{ZnNcASFhp;YM zs2*~1T~y{PGKl%=Os`VzCBAyf%$JqFFX&edeEIGYd@UHM-b{R9UDRp5WL)qQxNdEn zaozCZNHs>dvaj>HmD_$o)-k+0>-cVVm2yAn7#m++yD#=W9lL$GwA61w+_igzU&Za3q+?)0d37xI{vp_X{V1vbMSR_A;0t`_^(nD0 zmoBpZh3m+CRX@XgJxF{#NPNXz;>#+(hoA5X9S_)MlzJQS6@P>M1jd1Qq3@qC`g^Co zPa1WH_gUsE?fpb~i1<<_x?^7$FYE;N1wLw@WL($mI!e8r_-Z?z>yAqM)w<)jpYsse z*TckDQSb-a$Hs|4aO8$8&67?}k26 z9wi;CCzaRkt#m9{ry2S=ZO=2V^B3%;KBD&vQ=CT!2XejbR6i%M^)B-B6mq7}JcjM0 zWg+9zb-dG{BXrK&O^N=#r$~Q~>&X5-`)|heX8053G14(uW*v*YZ!U++pkw_DjBCWn zqtyAtS9}iZh;cZjqg>a@e5C}ghsl2}Aik0=@l~)7VBpI)o&D4@j?Ijtk?1M^DOvFAm`^$6*hBpqufm)Cz4yAGpMWoKV)YOFJH zNaoAa!F;9TpD2$LUx9Ra`x91t$@Yc#D39ASWt4gs*;oBbTz9~}pua2oSLtHN3j;4P zUyqV~Jwbe>T(U2#ys);}Y$rNjcN_SU`7CuGOg3nae|g@e7r2gWUy()3*RqaJlqZR= z<|$>Kk0q|BVLwyiWyY15JxaZY_)1^F>yH?RThG0d`SJ_D`fmCYoWHlGef~1#OT%-J5~o+@IY_97lEQzDoi|FomvmH?as3D#F>l$TTxPp3b{!e@Huwmo7}pJtjZ*I?z7oQ|DqU{}n>jCBKzuz*e090Rmz=Nm zwcdu^1AI=sISeie2fTgvv8BuMR~V`OT1 z{e7|P?y&pBc(WclUkL+W;4`mJiFIwL$opY%9htALSDCNn-qp%;#8=uSz7R(+Zs0JQz5fe3$U1_rhBuh6bkl0(dE%=(Q{K33#aF@nOD`fP@_eio ze&VFv&ru&HzJkj+&jDZfywlH9fZc@wzSS!lKL0`Zk`$-d+~2mVW$E&H!!%38`- zvvat9RD#lTt4j1=8H;^Pu&4Y{TnD(IQ+f&Wb>lwgsE?42NulFrafnXjqaUaCPslo^ z(v0i%@M`5n($RZfdHsadJ{YU{7(Rz}Y);C>)7%Z^YvQGYGonm*p%SsPn2t4 zhn0?UUI<)m@ALf%p0^p7vcrAayQE`E(lPK5@9)=j96){#cAt8sxPAYYdQ18uFU(G2 z`w9yG7!=nF=_3gkr%-53WYNdm8Oq5y2V)uVR$AI7~F7|a~uDnlsk96!f z&paPHdJF5=@L+K|rmWt#xsJI>k)AL4d(!bSgO1QSKZ8p2_vy98;l_2q7vf{&UDk1F ze6{it=~(?>dFP{*js^Ow%$K;&EIgla9kTd7?S0ZQJe_r{bR3G-@cx{)lB<nxvoG?Gu}=>$txM{u;=GFwG7S2 zrlpm6Zj{|Tr{f-H?B4Etj16@L7woG;+Bc%>_#cCg&^bT-ON>KNksswhZ}9@xfqiw| z#pCwB&;H)ia*p~q&BsiI@*LoT9vR@O|6F;6=411nmCe8Wt9U<&_haVk?6&*04@k$v zmpmWAuV47pouqwfK`BqMkV&zsJLG)|u&?mlX8YB3e8Qk3bk1L|MEmkQQQSHou7fy) zevYz|`8u@b0qsNLD}6ra6X45kKgWt!nJ+yKid)O`RFv`}A2&<+P!aEy^TLL1=4+An zbET8)KK3}<7v=@>H@zM*-aq8XeE~!obnFng4r_ft`-pV(AHjV9r*(vVfJ)ds>@EEP z^R+YO6Hk%d*S%Spd_vYSyNYqW;s0D&qU$(}pFiQWj<65#1zhNhw0*+3c3k>^_A%+$ za)Eh1h79%gLed}gwztSQV>KTO_f4v)Z^APZc#AzY-)r`J#eQx}?*m_`(^9LMuXNMr zN*C#vb!k4zbw>^tQI-CJ*wt{pFO=7#pd<5Tp?fa%Io<}MBRm5%R5f%R4 zlRQU#n&zYbcLCK? zqaXOMJl-T3Ik}I|5Vs>e%vbBebJS-^$7T^9!7uEy-0NwwpRmi9?-;XPmPtkh z{tJ3Eead`gUU^FErukU?s)c>I;lB(z_6S_9%g<3$q+^FmI>J7{H~4}cEuS%8p6<_; z*JwVbe#Cj9+x{MYA~eoyC%TTS3_3z*jHlFnkFke~>-*w5z=io%FY<|9C|_;Yb$s8# zz6hX?ew^}Oz|}3yD_zIe4LU;SzVhWgsqp>e`SXbvxDN81+H-k5HnE27>-E~FwNFUL z`rmVW1iyCkoMP*3yZ$S5zu7M3@%Q!j9AETdDXPlJSW!;haUbfh5xD^tv*NdvEdx9)7;394lx3u2 z@F{n6gnhss?b>}(+J}zw+C9R)k`I{Ym4|fvw?RkfoWEX)`Km{(TjoD+@dDQYF3h(& z;lHB0exWQU9g{-G&FqWL>!TkB{e8~vp@;7qw)@P`XS7dgJ|-)i=ivEr9UBe~hWzzsSdJ0%+_r)fL$%x2m^sUW^;KU|((DvVDaHk5*qG`|5JZzF@b& zMLOnKft`4>A`XSVP}1Zl!t*P*-eIUaQr|JIA+677pObw>BbFB@69UW!9a=3_uo~sVb;b{>5o=i^ZEZ`@w4{#v;eHOh5@v+$NJF)T; zvcCsk@Ds6KwyzOGMym_SzHmP>>C;%i^m6&kGKyY%niE50}T zi6-Iibw9DBfS<^(yVKu|`GnQ{$M|uy!X^6&yY*1@gXVe#*SC9w-6Jk{iG0GleMOT;0o=X&9D zr5^3_Rog4_>ryYgh4;h00=t;c@2THgeS)4p5xt$`kg~J+@1^EBp(4Lu0oMU8_|4!( z_Fvb{`9gU|&%cCUb=&Uk`U&r`j`@k4_r&?*12~`Xbbq0|OMKPGD^qts$BZ;?9oKsX zT)>?-*Ana6K#~1uTnBLo_w&WJVZPdXzfj&MT)3YP???XT%Kd!gEKmwq35 zL%156xNibn$ivHBr(wL%13Kcm>1yWd%6)p24+vM}Kb6V9`Z^!eOLxiDDOt(yVZ3&a z#8+-UhEL-8?%kI8%FOLiJ|w=<|Id8%(Zvym?Bb9=4;_K4;k|uwJj{8qM_EC*n*PT2 z^}pg*yAEO zRa{5*tJxhGSNotf$|}MIzl!(6&$#7R(Ff?+k#U_lc#ZN2;R>G4b`M-`)wMak$lv4p zGQ)TCbLM9pbbvaKo->cr+ z7e43o^O@kkx(eX>)PPIIU24AST~yqD09*%lpL~<~>RHNh+c$KL@)_ak{*dD%-VeTY zyB}bvJBsapS?MU(wZMhzcGR%l$A+&_z93xDj~Ewp%-7ozF1z)%)pHeb-3Ec{s>y4V z9>Ntl<9{m-!Tx<8nCA=r-R=?d5$A8&N%;Hd8f6Xf)h6cSW^vo${Y;pT-jB@V_7JWw z4Y+_i&qIlEC|cxv#C2fz$nP`9ia0cXjq(-YLL9>Tjq`DcgY&Vk`6_s8d)&-3{=L*= zPt4p0fqmipi7MtR^GZtliuz2ouUX{xZrRrp=5gz|zBb?j?mQ1A+E;gx>!P?0;x_8E zOda!ebWOYV4dJT3l>2gczf*NuL4Qy7i##X18{-<**siT5TuBL+Q+W=?3q8OWaMkWE z_-bv}dI?wEOfz3j;i@~tyxu0`iVIwaceZO;!sVIe4lei~E53X`V7`v6c}`nLxVl`z zCC6>>1-nlRT!%M4r>!Sk4YSRB!4AsZpD4KALFA!No*2Y@jcR*N+d#N75-ww&Q_gh- ztfN3j#7FpnI)Q8d?fF<+a-Z90LEew^w9*o{LO$sc39c8`cdIDhjVtYhZ# z=e2K%uTX{KQ2Hq;4iT>JjJRZ8N{mCwBgNGn;0N;&el_%C=4(jj^V%lD75%5MFM-P` zzq+M3q<9!tW6cYivK#GFxZE9F7%%Kn<|`_29ozVVrV_4}>Ega7hxvkElyRXC(C`!H z>xkADw0?xEzDexA7q}2F^!m}sJ^=WFzwZ#Z4)1(H(+F4m3bT$FSGoPY>{oNRh`f#z z&qwc%m@m)HFKShUOKCOZf*q85Ux)l0B=~#G&)5$c*8x|&sP!jY)mI8!|KYwX^w*C* z`uT75_o?U1eox2Sm;Zuy6|OsQ{@_oUuguVe+E&C@-RqUDJ8GXdk6Xtzz<>+5^IVkZ z@9T>6_qdKcAA9y@zK&~Ms8tiL+BUW?yx*z$SkT`S30O}_U&+s_J$3XxY8R~|hq{Dc z{Q>teF>mDOe|4*7{$zKKGkycAOHdi=qH^|QkOzxw;PI0I@&ik2K?li~sQgw{& zWVUN79&sJmSMUY%b#=Z58u$XA`SX>SPc#&nPvAQ6Ux<(KU$Bmior|;`377X;o{xAx z;#j%!d#kt&zv}xX;~G};vbGc9YLjp|6^Afh=mEZfE4-h;)%dcuGvVrX376c*gndCL z|GtdtfGb|sb|G9nb1LIk?fS3oA-ul<{Fmzp|Aq6Xg?(j)zM}0)e05aVeLa%=_fh_U;8tznyy#0-3V7! z!i7A^>3!~)j~?myh@R{|YMSCuP{g5n@w~pi>XDHzLt7VXdl0VFIoy{km)%?OCC4Gy7p_|^ zaP7Q(r}jg_6};|$)87YPGW$K~VD|`rkMnm3`^s#$MEeo(<$0sBeWutV^SE_fKQ`b3 z?mQ1A`ukv!{vOwn?LKu7+x-cROEeGRN(%eJ`!R3I-Cwox_sCa!yo~GQ)+O3c2v^5w zo{zwVc~kCu73YN>n2$|^%=wBZJX&2u_ov0g^U^lEPpCv4y+uB^0N0Uq^!$$bI zhyP`>KgK*S^%&XLo3m?t&MvORgXO^mJUAjgV%$mLCo-46s_jko6&Y%=AJh5$U%C4z zFz&$b+3r0Zqt#BbuWW^$LkYW&zGBux=W8DWU*Howm)d7)D>825I>6QRkQtZG*AfF? z;Ipr|YK#279b5--2>w3qV;zs`d{rAve0AN({tM%%l)rBt#{O%}^3iG+@rCEqU>r`x zN2@plzP!gUuET0x)9Q&YJQu@hzMuo_1oj0!5{Iykb>#0~CBAyZesZ_{y=-6AhcT`p zov&#>C%&>lckB!O1@L9p-^U*|&tsg|?osB;`xoZRU-P=QFYy)lhdX>>9T?+59KyJL ze`Z{sx-sf&WM6?3D)`)C!+KiiaK?3P(v>F;qJ*cbBX=n>4<(AL+rUl3pQ;`t`U`bg&U}==XEDbY8BO&Qzs=>bUBXX<4jQ8_BfgTm@p>Bg zLcAzeNXoj88cr-yD#Vddn;VfvG#b@v3bB)^?kzC^dB=W zyEy*SLDex%Gb1y&;K#U z`9k;o4xsuD`|s`EhY$NeJOM5|@6mtHuXFkI>+!dgJqcH2TaJ%i=kW9K;b;2#yhke? zt@8WGMy?-wM4sdM!B{mz_ErC>;7j=X;40=@#^smxd1Bo1(FzylIo^*v8agF+W*x77 zagFi~@f8y~R=m%265~3uF|GZM>^>pcJ;v47xNY?uI(a_k`4T#%M1DVapRwwHNXOs@ z>?hpj%Wi(}`NZ7UfPL6K%KoeCWY%$5XIlF`=~#V7dHt7_j<64m$1Yzzk2%8^>JI1; z7jekby+&C}^D%XM1^aSDUh01Ko6%EP$J7pQYJVUdld_ISi03^@&o_xkeIn=~AFXsO zPOTHnndM_D?R2w-X|dZS7h5Sm35>e@>S?)d~Sg;U$x4s^7bfRSk<){FW!&&i2T0i zbk_0M&NsC`k&Y=zN4s^0)qLDiJ=F4d#x-UBSoLGlu|CTERp@9JSFwD-Pe3QH$S1De z^-E6oo>z6u=!|6slXHE(G?(y?Q{c|O|Z%SuP9br|^jZh`Bn1!L6}`g|1q9O!7* zPgv=QItzAhH~&(;G{;q(*X|MiK6W|hIrR&;eq1{B4D~?bt9ByWeOHA4j(H>3X$fil z&&|5RI;HU~?ayRi;kenp?CNM`Uj^%0s^|0l9D!@*!m;W~;tTy8 z*cbd?xu2(?Y@Sc#@eoq>5y^iXQX5O3buRj>y*Ej^FsIu=;0Oq%eU-HMWy)|oNcks z%8fjlOaafK^#74{998?Sb|mSD=TM@LY3%11=VP(`98aLIjxt}+5qVDN9L5zod7Sz= z>4@*kgpSDH%Do=|_JP>~KhgA#c|Pbm_A}@Ro$i`#YsuTO% z_rKy@?I_YQdN0Sv&FVBdpO1d9jx3$t_OHMNonj)-xqSFI^$XH5BIcvpxZuC?>$MZu zzII&qrJ|9J%1X`)!7u!bejol2LmaA;>SZg!tnxzH?(O>fwobEMTH)E!zxV8Cz7Gt1 zVLw3IW8BYK5`A0QSI?tsc|SmQk+b^&pabyR<;(BT`Xl&4e>M0f?;F~2>#vk5vacq| zzPut&k>g`(XkmYe@#AP^Uou~aL$H(jX14pxcL+rTj}w!yS#qYYJFRd+c{k1x6ucvoyxcl>wHfeMmpmDH1Lbhm%9%j`+M+( zb-uX3)joHe`X%Xzbw2Qmdfk@Ow7laz%``xeeD?15%)hrN2lha93Np{z~w!k z`MPSsIQ46NK8kfd=;#zK=m7rUC%hv#zv>dW?rHf-*_w1rm03rtb*qB*W$>$^3z#o| z=lfcKbi{p`PV2ZOKM|Y7_bbd?I8ObBbi{fZbi}xvUQd&CtiF$N-4p#v*@kqi`^4;5 zVFz+vSZv?KN=GZc;J=g$S;u2*GTO1EWBeanKSD>R{8vQk2Vp(}SL{m0HMB9K9Y?ru zU#8QzveJG#=;#xD-@3_+E4F%^+N=9}QP;x0;*S^Jhiuu`!o(LxtNdQ}tH=v+-R_Bu zYu?&%YL;-dtgKAm*KVDb*u6Y`Oo>*-F0PiP?2qO1+Wj4M8phoaVI4h9&FVVRF?mvD z_hUBwz^sRkYrO#%aOZg_u}|J`hWS2;{CT7oxDNaT;&$p1=4-}?W_5!;AH{tEc)wF| zyI_8A$P1e;Wn5#YG^-m4m+vX=`vR9!eih>deehqY&)9z3E@oWHWzFihgexQb1aKiw z()(WnXguf_+U<`)QdxVajWV5=7aMg~l z%sv?S``C}9`AE2woxaBf+|a+&{zSUSJ^-!*`$AnCn8iA_FKkv-!iBmP?>FXO#{R0^ zI&Dkyv0LDpvbt-{qnZ3oxPoF{ZI<7671wtwH7~?>-ITU9YDC+D&$w~=3l;_nEf8?*6tDh z9_RO8#(a4~=c?7jSL)=-=3m{?xOH4x8*l-4o`(|iuUNJ?`@?l)fA713`D&kXuDT83 zg1^W6jef!ne~-K{EpS~i>s)nP!qqM89=M$Hs~9iz0AHCs*?wy;XTDPN&Q-S~T)tJD z=Kz;+-QCDn(B}H1?C+6J;JV>|GOp|IJXhVGa76{KO0CzT|K)9CT=!l++SWDt>$gPe3hIA`u7c2 zGp?onuazB0$F4H#XxWdF{0#VlU+oaM{GI>NP9nbI5?^-xsuf>2uk2UBSMVC<>xHJT zm0IEp`4{$eU_Nh_e@T5voL@d#@l|j>lHG%^tiUy-<^%0y;!AnJY+o2xU-Nq_zO3R9 z_KCJ#%Y3b!`n58U_=<>p6?}F4h4&-Kd^I0k+&%@X{a*!f8T>^39L9BQ>jzpB@rC;W z%GLL^;tTcx-QickS4!aOo&B}4Bk`3kGhgWw3-h|A{(aM2=4)u@2ihsb7w!viny-T2 zH>Z;)_Sg3aTx;ijt?Wd6HGF1{Lw4<}+hX5bLBDFSua>CbtMNnaRN|}dVaDY&UrHgr zN^~J^w~b?5$@tgG&cs)X#24&So{z<@57oU=IM2sOMBA-AWU3UZX6{z`0`y25Ude9xd z@(KTq%-4~PA8Dr(Unz+%r}7Co&%u05uQ1z*&etFVU*I!uHzoEb8ob4=58*m8U*VgW zuj5-k(*90-bv$IYFS~qM?Pn?&hlqs0%HQUmr{H^r>$Lu-u2t%Yuf&%ehcFJr3#a!X z%Y4<|%zPbN^RX5rzVN(9#7C$2!g*mQzy&|yi!rX_8b8+lLAX2*n{~A7SFLoE^HtbA zbc$ThxT2HSD!Y@8)nBoWm5xKrw=k~8){nI_h_A3qe97MrV>b@fcbokS?4#6U(+B47 zwU_NHcB|m4^JDEy;;YLgzU2H1aR}p%i}~n@u2p_O_LZ)19Kw9;x{di7+PFeHi};E> z;?8`O>kiCE@978db83WP=zQ&A;0t`_?WV*y)Mk-C=g%iz;5x7`#BJpc=Ihwj724Uv zS6bo={;#in04x86I0BqGT=Wa#P*mXRfA?DDhlV(Wap3cA#Ua>N!=21mpmT*bocL;a z)E)bh>kjCMb(LU-fq} zuA^I5Y9ZpQCt2P;fYp4o!UaFk(EQ6BZ!@OMR0r)$`=bx#x+A!n*N^P_39I_iDqoF0 z#X5HH%eaQ8*D4;;vF;nQj@3u8UUGjTEB;;9P5#|#|0?Da-VYtYS4!v@=v=9dBpss* z%yw^=FDo78dPv6AbGPtcHQm}M-M-3+Bw7*?ng%5VO$qoXz&wO_6$C7wBif# z4evuff$IjuzS{k_U!{#ET>d26S4HxB0vUOZbqw4mblkdE*^_kitToR^Mchv)>*z1? zKEvw8h5LoFec8?L8}=^GzK*s+-;+UnbwAB~RqxOKYroxkmA#0su*8>LyZ2h~1^)y4 zvddRSx<3);E&2HStxfqd>JI49+{*Ul={{Gjq5S~OO%>Y*le=FO<8HZ!ab<>nqK%>X z*j2gvSaX!u4>sGc&eskGzQAW*pAzei$U}waVg7vL1+IhqD_YC@eQO_LzIOUuud)x> zeWcgyCz2w6ll_Ep499c%I`Z$HgA4cPWV?r7t$)T`&+9slHR>qacZqyeKUy4LuqW_^ z{j0u*nXmTVbJbeX5&N0IFXEV6_hmNh!aAk}uAxWvDuYSK+K4%BBR^vETJQ@y=xbeTmEX&8NXAwDDC3$jV7xkzbi{rD=;#zK*azkb zaHYTCzOPsGO?Ei7SE(l*LzB!pf^WUvHs(2X()uCJFCU{N>WI45`xx_ec;_ctGwF!? zYoQ~?RqnbL=fya{7wWVwfotNR@#>DGW7og=J__h)x9@9ZUj_PdIf%%Ut3|(X-tb=K zXQX3V_|=N!g@*N7CCNGtX*#M?t&Jxg1OE_phlr0(>A0o-SMUkOHS?hH>dvGi?hAm9 zn9t?*6S93FU(E) zdy;h=J!HJP3+WhhX+CZVSL!LoHMHhaZ6fi7`+l9~OWqHVn~yZ9@qEn01B}ae>Uecm z;wvlh<<#>r3-*}^7y9=-PcyFm*YzsRU~ecj%ktKC!b|piMx80UyzP1S+3KdqsQX8 zQSl=CIaYZN?1P}>{zDvsp9rKF*HN9HYLiLFY|TlYO+u?e1osRL^J%TUf z_puecuVaTNdX-<2j>zw!BlzxXes9%}wyKAqW8HJCV`I%{+7!|;@OXK33|iDDGA_hz z=+PwnmnS}6t)uzqIi+HKrkp82rv{OK&3my|`4#Dy!F>FWc^`rPAs_u<-Aezxod3bT zpkwCWtmAQwpJ`#zQF+209Wl=_HuzP~&&=~m*Ks$4j?fvOEA@WlWRdr$;W~ExMEnTz zc=EVyzL0f{zrZ>k-TIj}m2_-!Nk`NT7)}ls{gUs0y~w!Q7mQbTCmqrM0>8%m-gtjn zx$obGpMV~bcE;uD?o}FSKK5*^Y<`bAt$88iI;!(CZ5ruV{iJz5g73cezpVT!bTH{? z=mS)DFs>O3$E!ae9q~N|(9td~t9(Mn1wRqdwFbVS_&evNsK(N7fH$F#yF=Myqt%FB$)-}t#UopemPq@&zt0xtAd zqXO5=mE+YPl8)$`Ku63Qr~4){u7+2buh|2#%KoGy_A^08w{aoQ=@7V%YW-Y0pLDE! z%IsI|+P&3$gx$h#fG^+*E@r+)_l{S8r0Xc^N9br5mzCXH^-WNBq($7`VfU<|6A3Tt}Xdi8q+9rp_<4i*+4cnve2& z2mEU7FC@N5$DbN>gwB2CD^cWrCR_(`8+Au!8S~Zu)U4tq9Z`3HUt^x*X5A59&bWrw z^k|omj-F@S@vHKB2lzrir#8*F+DA-K_aq(B&jG*2{NBh{x%)Y=d*rJD;lFkml~oQV z9g(jV(s7|-zpvf;5%vN51upb+;)1WgH1=qhl8#-Hj&}PdrS|VpKlxQ4X$Xfuef`e)5{?-XA+uZ#=vvH30LYwWBE>fXdxtb^k= z_;RXFD`;N?68qdU3C1<5c8xZZ_`*JS#BJ>3+ezC0WfhMxejKgr%L-S|kJ;ZxUT0jX z>n5oC5MOw%HTVh$zb)@COj+#r2Ob=)>RPM(9(>e^b@yLiu|}Ikd_`biF4sedkKiLI z^5`E@-7%Q>s{X7p>&VEz>Yn3$wbgI4j*-?cwHAFoF0-f~>HFqhrNe_5~eV_A=Xv&ezWje1Xrr-ISQ$$JZ6NpB&c#u5Q6s>^Qcs zKV0#Rb~W)8c)l|BCFh0pAFz(?y%W@*6JN*+F%HCixAwW$KEU?Xb;o|W`%;!~7_6?U zp>>$I*zUV`^w2IrX58y%^!nix$XIz<~Yqe|0?$iH|pHK|>D$ZA~BltpI z7#+v=ft@vIqPidPh3DUcFQ@WCc|8q&qGb=Z>$>jm`MTD?7x>KcQKJ89684z?yu}M# z2YjI(N`B0^hP1BL<`Ay<9G;JOzf<;QwXT4AD6oQY%{*wL`b*Lg^$>J~eY&-t2EM#s z2);VkYIBLNrn&C$1sxzSbcEeURx+;9Lnf-fBEGQS7koKo_p)ErTbSgflyHh)0dKL# z$h7kKRrz{3zUUvZKGY!mm+#bxY6J0w{l4JK#r2_F{w0swGptvOl6^IZ_<;GCAD6@5 zCk_7vK9u*^zJ5&g(65QF;L8?$asue1AE)XL;Hp2*Y$rNj^9+2+e3rW3Bvzzf#dZ3c zPe9Ku={{5ZyWJz~zU^_&zv8P|$Lh9T?K<7xi+mO1XgGxL3)TAo#=e{){(Vb$tnvxj z-y@&ExDz5idg2q+-;jMpDpU`FFMR)Y`cuJISFd(G@s)Ui^Ly|WHSF6q^3^3hH^qv# z68OrUqT!JPO!sx`eC==G3w-9US7JVqDzYBJb-)*%r%?U5;Hx&P-9UU*zi8$wDAw&| z`wC0z`FZ@(i(>i8;i3?PxE&L?E?zKEJ;31aF%HDna_7;q-GeXmzx=D1uNRNWYBv&J zsU5k`1p6{RKgVcacAuY95SJdZpW=MAOXN9cE}W?TmiS7F{ulUiDxZK3kR5!1j~-DE z?X`Wcb`$Z1{}3O)pO1>kf7zXns7rA@*cbRpOy#=c%;gi+1BtKD=d7dCd|7?(7Whbs zK0vRgL~hpo*HVjqAq~t&KTgMO@KGz`(6wtPs$SwNCHQiCUq?O;iF_i|!}Bro$~rAZ zd}T!bwHYpl^Dn#kMBTpT{0Mey_lW!}Jl%YLov&LAe053rS*iI~SCRP_t^*zO<6gr$ zdg>;r2a|oZ{IxRuRoPE;e95?us9CSwN_+)He8f1M@~g7HhmI-9PISJ0XW%Q(Ck&^= zd?H=z3;#R%t37L3$M(UK)ZY_d=&xcN#{R?*imULecGqiV z9qsxF&-vzg44Lg7VfV2ur?Tshfzy~T zPnL0cqLb7=5w5n=D&tq-C$a(;c-L|H47h+Be=ju-^%Uv9a2?t1BkP&3i|0>L|4g{B z4;k-w%I;-90bIye>ozd1GZ#!!4<%fgFWJ6;%c(eo@j?$7m+v-_M=zYD9!9vjzj6nc zRUQpKlEUuiu9&1APPqKvRAxTf_4oeMo$>cHA9H<7oIfG#%TqmBJ%af1{jIWoBKmjp zxOH4Z47h+Bc3G;Q@T@Ox9U0d_9Kt@n_;)-X+Xqcn{e%no1m2H0=E{1lp>N{b#JH{- zJXt-GaK+cM-2)fqvs-c7dj{(m{+4lh{xn%Vif}2tW?XK?ZM*Za!oui ztBr&U`{nR{r|f=9al1?4I&=PH^%%mHTE}(|T$PI3A&vPuYr$kSK)5^`+`%QsZRm(R zN2y|5XD^(r9;@rP(H&gy*RWss`|2mSzgoRB;~KYovU(ih$~Nqsvp4AIlzmy%9oU!M zvXuR5baGbt9qrq0tI+*vcKvGi(PsYw9qb)6F7gWn)&i%v&x@|ub#Urn}2zSna8c;I@Ev*xbt>XV*b_LSzJAY z>mWYDeuiYc!HqIZ|PRvLDI^_uBt5&sG zS8#Zp4?4CqO7oF$4Kd=9c`0!|Docu+kKjk1kNzFRd^~lX;wM~~k9a@q)9rjBBXG?g zu}(RXa3P-nu1e(-bv43IOk1ZMMY!N6fXm2NU;ISSBJYs%3D_5|8`++5MQ5&4jwW2u z|4~1YKE^y>?D_|M9)1Gn57!Dm5nrbaCBEYKRyJ-&0_Jgh2-h$JF5t#^O6_ARzu(2Q zzbt@KXdK>Z4x1+H8MeCGf40ezA+qL^r<0GycAIP|_S+-6I5HA0Q%EU+Tg?gx3 zWn8mYPF9bnK0w2_=Kh3R{>yIM?mE_Nmy)>@|Lef*O!f!=g}z9$!hBu3cCvZ`@#X!F z`PyuM4qeelKUjA!9zb#LgrC5;n|ESdp6oj1ShBCC`zqrn?CMxQyi7VuG(tzu@#gdE zd>v=t3w-83USgh8SET>Kb)X~0?cGJ_ST{vIQSZxDs825EU%}lNSO0C+E5{RG$iFZS zqhEEh9)gZtlAU;nuagXXfzQ6`7$~xTkL$p%qVJoY&g&f`2d!65Aij_ng0CKtKlSx_ zkHy9z=!kW`w%u9B_Q6xslZh{^^I;rDe{a;W-1~;W7uGvcKVV$ZgQloWgsWTlRp4@} zAC2+CPQaJ{a=u@oX%EH~@~>A;A|10LZbL`(v*qU&1m+c&$5`noKeqt5nn$w#>ZoH} z!Nw`-DY}lEI1Yg?&n|p@9oHjA_gL5=<~hcL_=s`$i23M=PEr3#I>!HA znLG!4b)Ccg?udu^8ar>jaw_o^l=$i~d=IhFuSSZrdn>-==QANbCP$m?MCa=?17F}1 zJeOLhMT(4%xDNQrE@HkCKViP&@%74IiLcBXd*$+O_zC4Wi+zt`KV%-a#f#<>3i~

`%U~mWn34}pQ8Sa_`-de7zaLI?)@fm-voTMEn&Vg0@t>WuUAeZzG^p_=cC>4 z@36W*r64Zi3wcg>Pv+~)1yj`1i7(uz1HPQfbD#s{2Vdz|nXlTt7}rZ3>y^I|Um=OF zwD|r>*?;+k-Qm1e$Bf1IP8Y;w;43b0ow;y|`gh_B_vtvzSHXP>G`Nms%$IL(=4;zG z*DI$JUv&!m)pE_pxK;mG>LWr&>{I9#acJD~DQZxkk7Az!_yXVMo{v^}VeMPYSM^}Q z*Q)i(--)kgi7&hJ(dxNZ$Twk^cJqn!Z+>g)ci_BskBCFiDfuJjE4pHe`VZ1Eu2v@h zf_=r`V;#NqLdSLMl_2TpQO$O5ydT*Zw~M_WIb5XO+to2R#vJeM>W9yRFRbf_e#U$~ zxcdg>AH-K!;wxe^FN|CCPvkg+yb$AV-iL8{s>A9TWM7G3W%I(!$82BmR<4I0{P_mu z4C1T%dal#pSHp%p$5^LX<$KTtM=QRd1Kx-ESUuKkCpuqe8u$XA_*|)ZVYJA+5Z8fy zp+6Dak9BMx6jsk7T_a9J>i)v@Q1w-;<4gVx%2}jimt^;L{Y0dz@cJmm z3q8P>cLdv4!)l253UB2uU;YsX=KKNdD{wUXuizZ^U;EA8poEC8 zjApj4_=$zcxfqm+U9(<~gzP=J;iWr__JX@kL5v9a$0m!W|ZEP(~47 z*gt`|jXr2!zwacuv@l;dFYw#ttNsAT^84KVR=9t+{u|!6of*18yPfWn_NFb?w_V!L z1f9CXdfK(iHYn$ij=ugDc_9(*qaUaGzL<~5b9_f}+-@Inwi?{=`#h&*1^YL|eW&vr z&%AZfXz;%EN_7e~~ zuBYcu#ECD@OBVY?={!FA0bk;@WjjE}{Ql_cIiKji%|>M`@rC^W7zg5*)B7>)`iW4) ztbbn#^Br#f-d^wpe;-}Ue6>&cnYxLdJB+#(@!3UxpNrcVcl;opkEza$+FfK{Z54{! z;0x<%fg6~wu|M0WH0$$Gtf#@g?5?L-t#22|?{g+mdy&~rbiVF3@C82e_EX}%A!UI@ zKA1ltzrb~Jd>QI(*&{?Cl-=+1Ao`-!hEm-q^7ZO%6^A7f{5UC|KWy5r68 z2g(@g7bXs2yGNhXn1319JM89P1?MBth4r+Q;A`8d8a@Bd^O&Ht?hk&f@(HYGbPHVDE!wC| zCBA$&@Om2fvTOHN>uFXxCN5#VyuW9@BD-$V9wxrpUNPI3@j1H2y0+-&=vwe<#TWd! zGW=J${>4k_jmk9Q3+qjK!Z-6QdptJ84)$Pvs}s&T8TM~N@ro0aLW!cSn`Dtsj4TDRM`$^~R!Shs?GA@28e z-KxjJz6!=iLp@Y`6yrLgbE~Qax_wRL`3OFdhnIWbkZkwh3+q;Kf$OFEZ7xZ-jRUHZ#8=NGclauZi$G%Cs(C2m+V9|Rl?d^Lbt~{? zciqa0FROY8_sw}u;yilBpyBE$>fd{x;y9H21^WZ!Nqv2eNU8BL{&!yI3&*%`5^5Vz z^*HGmn{3vxcE|76`HXQpGq7--1AD>Is&8TyA5*G`kBzM3zM*fGi%7?|D(*)^$FTUG zN7+yKi~Rma&z}n0y*wWghu{YiLm1Z~iw9Iaq5IXv%-8=~9E#6yCJw<*U|qCU^b2>m z>|5nx(h=*T&=Gdf*LBh8YenZ1x%i0n;3lyjz|#>{N7A}`@E?^~?|^-QkIZk`zOJ3~ zt#S$R)l;GMN8pN1G~0>J*C+#D;1lz`)b)-;k^8@J9lQCLr}qHU`dl8j%@^RS`JmsL z&hM%Fxmvvg+1K&x?>i1O|GiYc;yV}iTQYoH2l)in6|%>%eYGzStLKo8SXThQ#yDi` z=albEVo>ldm}Y!gb*9abITBiOko@rC`5$EkI9_|@)79JhPKeDpL;Rhvo2 z+A}P0IqX;M#_i^;vvFGy->(3>)A>5rz!&($-%ItYku!_)tGEty#JD{tv)y~@zEdtE z`>IP+Mn}v?_^<9J;lJiiRVNwz7slbX{{ml;QyAAZM|`KW5?`?!IsbCIPJ^ESA4#F( zzT{UY6JOq~E8|z~&d2Vcxh}}h3!5)s_sNs_{E1VA-G{zYt|T2j4_3zRfeYjI|5f1X zo~lkE9a9zZtFW(NlUWZB@zrMF3w-9~DRI9^OObgYt^-_c{mu1`hxiH`_yV7O#g#3x ze#CWh{);Y#ys$dRI`*ITopKfNg}e~sK%V6EzBJ%MofZ?g+Iy#}Q;9FsX&8smuNw2! za@T3Hzfau7>qE0=eW(13_`-8)z?Tu%EWb9|>Wu9*i-Q_m+{sMCPUDZ9sd80;Q#C~*q=`z~Sko{sO7 zYe~nh%EiYVMDS7jH|FaXl;>PPe8sl?-^_EG#+l=6@KFCwcjc8$nN6F0)x%iFRAY73le9h*t?;@#@`;`h<7%HfO}&V8L_Pt2jsDBYd;&TKW}59w z=j$m0U*J=ifl_L{-D9!;C4WBg0@pztLflS{V!kHKpQc_+d?mJL{{_CBirdfuIN>K^ zKF*`th6_JYw@JB<>^}XFh21;c&jDYE+ktZ!*P*S|RZo+S*iR0Aor>FXUrxr=EpW|V zFipLLbWGNmb#w|>!G5%1T_G}>`8uq#y6PF?3;W5P<_qJ6edYL~Uy^fpKGuz4T){=t z)Juu4x>_?|+24P^A7FqXzwi2k1N#B!{Fsmav5f18nyssz)&0a`ULOKqZp}y77xKdF z*^F!U@@eV};tS71hM&NE?rZu6?|d7)sJBN@?NoZRlDxLIxW^~>4ZM|aVr0^ z+s9O{Gv^@~zuhDFf=(?XnXhY3+N9h}Ix5u`ahv|+qaUaE%I6cac-*zkj4RT(P1SSy zeEfg%RX1=!kBsp5p8E6DSu`IzDqIi61Yf}u_`c0QEZ(+iA@LPoQW?94j?GuIj=pnQ zM^AW@5+nP{JZxcK4(Elyl@#|sR!@L^ZCBNy`-!)#_aQrJUx-7fhoX}iSNlQdsk6zx zP!GZWjPcQpdMI^`*$?SD-eS-ZI+JVQ|4OX4l|L7^{)p?qe?dpziNfxOZC~{==@?vE z8M{Y(MBNb#vyQWeoTpw!IwHS^j>vbN-k$^e!n#6M;Oc+bCgoPr5$g)z*BG~r_EqdY z1*<%#K-|vlvx@vktiuSqkJQvuy+S(1Dm))ichpZ~9fPNyr~Z?4MBM=$ovJ$u)@d}u zaQ|aU;94Brq})b2Hi@_m9r1a2AF|#1A7LMu?wF6zvF#+x#~rG=NXOKxm7R~Mha#O~ zeQ3ma>gA*(>LKW8^sBQB^<%N?LnYNi1|3_bvwgi4-=y45I#zGZ@zH4=<@*Bc=Bx1s z%y9ztVfP68f=*p%Vt@wvT!0)7?qF>nFndNsL8xr1~J+$8Sj6M2x` z`Dj%S!EV7b@*L>VHkEN@wi{Trl;&gh|M9E(6X2Z6@9o-G_s!1O7veVR+R!BCYllUf zlsidB)U}w8@PB=+Ypwi5f%uq{G>|ZlTi5YbgO1P{`j^^|PCZdv{{q*6eL;_&^O!GB z$9ZZi&BtiiqCeq$exIWNI>khOf8DZ8%6!tX_N>arA>@VOi{PTv+c2WH^tWu<|_hDzY!EKf=CxMBmn} z=jX&8fp%yV8M=0vuWcQel zm>1yNh549+h&bappK<--iXE$#6JL=xDi|LL8S3rmY{nJbX1aPc*%#_<*q2lFc0nB} zABMkgxQuZ{rzq+@q+@Cu_FvEue%a}Mj@|g^f5_SR2><23i20g5Xu5h0>4cdAO$d`vH>Y#t4rA{R2Q{i)u*mUK*gP?>rgeE{ebzl3ppL$2#S(y?w^i+qB( z_R)`1buDm(8bu$IuBHE{>-eTYN9fFdrT>@MC+~Q&xH=8jvFj%yx0lCHGz@25FmAiJ z+G6Fw1w1$+&w;=9w6T31+PPEJTe^QT(MkLqkrDGps29<5MB;N8S923T&%>#_Q05D`pkqgZ`8up-=c>0!N9<>E zT1VIi>`UJ=L~1GF6u-j17kjMzEAv?F`-^>FjxTyM&fhhGbv*0E5$Y_`5&uEQ@AEIk z^nI+B@far%N2@#<`2gMyTh+RDt5iY3jdaH zC8slAucbd!rqXjLyN_kN4-R3y5clPLqF7v3eBr#{3;6{6V-|iQsi^l;e2hL?K|ett z^Ew{3Z?3+6+53@lA@S97TzUDj(oudMGVCkAE;_U!hpYc0MNJT2SQiDK$Sa+`-wOFe zVx2jk@T9$JhMw1veVOgPTKapb`Gl{17t`}VU`O&1*8yL?v&Hv1XursP{_$=_eTew# z5cwDQf_;|T?jsg`6ZG#})`@*-yQ}J>gbV$9;4Zr#-! zhpyj8RUgymuMd-QXv=P_UH^Hue6!i9bg-j8_UbU!DDOHU=lbDCoU*T@B``UK&s-=1{@ zE~oM@j2C*yxV+afU&9xw>XU@4dMfvsoW@n~`OyZxx&*G~<*ND=;flD#7yP2k7xLB6 z^~~2LD^>Mr!j+bAA+IcVp9y|Z#s&LQZeUzfdR6rq!qt*s|K+rf1>?3s$Ed)yfh2sE za5dDpWB0yBb3X`nkN#KWryL)z8Prcr5w47c3-hM0`|qvtLaX=)9XoDh9VZ;rPkoMX zwe3(|zJeBU6#mD`zJfOiTtoV)|0Z0%T6b_^K3U<)3S1k>zMdys!7Iz_zpVHw_&wJK zyHD)N_I1{Xe(DQ^E9w$ouv_qjxScs%irdtmm}}@yY}QXIF>W^(xsHtM$ZZo}U<-NLwL%%85#)A{<8_aOrp?6chd9^-|M@L#~yBXC{3V7hu8 z;llmyPUG5Ad~CUu`I@(Ix_Uj~QtG%*?li6~#YfL=jBEVz>FN!Ht9myxF8IH4uZwOe zJ|+dO2`i_oHxe$a*Mcvna9PDi#G%0L%-5*i>FP~{E48~jd|Aau#O=158Q07K=c_jp zE<8^Gd|}@7HEvt^d%2GZzl!Vjv@)&(X&oj;xIBAUtPjzY@X?P`>m7Fc_u)I8>E9Dy zxw;nT?-usu37xOrLVRV!I>cuCL>=yvL&xCz2b%gVI<8v{xPY6av)`(e91=V2a%zZI!Reb}z@FaGY_?n03B-JK;in1TMGZBm7tG zU5x9jx#z2Q=sK?CdI-3j@~c~lk8y$P;`!&RcM>kdZQyc>uPwz#-`&jDtR13abibJ8h&GA>qb*}*zaOa6AF%HFwj6=8%{5||?=zivF%#aJz`v_OvubD5r z-zh&~6^DS!dmrN(aq#5bN6$X7y7SQXin@8h82=avXyHf=;n} znXliG|9XJ<3jfB!?rC5?`f(~>mHEm($hgj#+fVHvzOn<|=`&ewuHL!oUDDCJ+^l0j*(EnFc^`77$o*Yb`GkxMaR_=uA7EUbmJ8Gb&ByK$ z%$M8skgQ|Nqm1i}1^v`Tq+?>9JN~Op`o3NGFU+?NvETRL?RTkqk93Tt8P{ffk@i0N zams%ISMXjbZj+7=8gzut1cm=AF>WV|jN7=5tYcsS>o{>?KlNqOQQ66z`6%c2uzTMl z%vaMRj4RT*OV#_NWBl#^j^{i?l8mc;?gi>Yq+`C`7XA}{*{yyw@|?QI#e7`ePklw7 zk1pvb_X}b7&@po|-&gKkyld5mq+{}(%FIXDJ>s_i3Fd3Y{0r2FNymJDLg?sJy$$=o zbO$czm=UXe_5^FrW)eN{ipxTX%!)FotJwY#_zx8>(g zz~2W0=K4X`@neII&^d1}CFVJGPZziU3)hkP@}`)t@yjnzA0r*H&IcV)ue-g@*ClXG z9HgmTq@({a>n>o+IOm3S8p{YwA+cF;(XIXth6D_N%}J|JCqs=IgMU-KtiSj@Xw5 z9i8%Dun)|4;DZ0^5V)rFUZ5sP$NK%*zMR%k&U0j3!RMK;F$ZbttE6M|uI2TsRyxA} zSn-t=xQ=Mtt*V=JtbLdL1a!pb%k94k<~am1ai8d$yuf@Z120q`CmqrEg^qr)uWTpE zCkBvzLA`C2hhqFVTKS2Bd5&S9RsD;MYupe`eNESKetG?>m5!KCzz_Svd`t;kN4D-( zwTg6%{gv}V=!nmkd*9HO@`J!q@cb-{CyL?&Mz1%l}eIai5h`!0p!56Ae>N;i^7j%SQ z?rYq(vimK?q4Zql>#7l&`UdIPCFy9_?yYcPyjJruu!wODtJ%G3weDBvn02&^%SuN% z4k3?*PW7Ts{s&rzd5UywIG{4?Fu;ZV;y$6{x3m>t8R?jLk@?!JP9ws7^aFnn{>ycQ z-NUcey}~*k*0_7sr}}(c<&KVWJ!H3U(($kI^i5=*?c%Dx!x>!Av8j>wS*1naOM2``o@X=;3*Z?aLFsP<@)_qc6m9XfwNaxIY10&?5<4 zaZO!L^D(}lVz_c9hdicM^yPj#><3k!la6)oasIU#U-T&-{W#?(;J*@4v;FEiK4Z`k zI_CzV|F6XUL|2jPFt`qIwH#sYn|Mgav_VJc+*e$QWySSPa2>mTBJ-G;=R9tkFLHi@ z&Vl>+Vz2UiY@c)br|rAxbMn3i~*PTHGyk^roKr!0vGso8yD{1uJ7f(?~V_D z)9+Kd55IN_-;Z3oH`^cTJg4vbh5v$`WEL}DneFzd`hxsK;=iQt8+x5_&6sH3N6&sx5&OCb?on9UryB>GOoP;T40{NJrGQn2)f}zSgx?bsF+b zD;;Z>Fs|_{HT50RG40ZPw6ZVgSpO#DI;?e%sxL{$uuD3^KEN0J1awM>I_-~C*Z!My zZ2N6x>srh=zlcMd$fdqZI=1X)kw??OeDvc~z6!gCj!kc|j>9_lsQQX@^bTVG1%C&= z%iS-;e1eX4^TOB-<~V`#+C74=h9sZAOXOdJYkyevwa%B=#|OSJpZi)r7V9UF=V07f z;a5G?5%qbpd;dra`*Nv%^vq|z+R|)ap86{FJ+k|zWW{jhOaVGoi~Rl%SNyQ*8$Axa zU)lOGdXw3Hbsb+Y=m?$j_FQ6~lQ`479-BXp^a9thJ0ByDo5v$vrs!XT5ASW-?+bsQ z9wODXWMA(a>O#U*zk>ZeaJl90;a5?2WCX71L#ovOkdEHn*-wC9x9ScVSM3MP*O>=J z)DGe+wa(0!Q@E`1FYwiHGe75{`Q$3~1LCXOCB6#g_hk3}Gx)i7f!p}Gcau*Ysm`P4 z1jb%xzPiuizk7%A^HJpeU#X$y=ceT6t@OewK5i+$Prk!C&Kwd^Um_im-^1>W^U=63 z&F+1y$OkYC_%B?yN912V%2yW=uGm49$ya5&ul|_%QdK4LG1-@Y4|nFH%$MCb6x-Jv zC!mAfBl53|_@0co@DrYBM17fb42-Hwo+In%UBNo`BOOG2RroL1Ps`iPmqzy0O?(A@Xkqs>;e7PtR9%btSa%oOS7;^U@?@*jRfMbd z2@6~f*F&;>b*y4s=Pr+^U8G~v!NT7QyLU=QdA|vC^nWZpe}ee>#K0H$%=^m{^XP1m zc{Hw*T2Q(`8~#g&pVypLr3t@{1M|il=6vJiLdJ4{deROEw{7(nlh-r`YG|H z{D|ix_;Skbp#yZZn@@O-E>Av@IETj%T<~8wfA$mMzv?bhUn3pk70M@IU(iYEW?Wm5 zzyF+cOb8v_UU!FIMO|B~uzj`m?yK%a_nkC|?~_jcj`eb?u9fRF@KyVUl;@C+uN!oP z&d|TqJg1?^JO|gYYxlMHn8%aHZS#ffSG#+JUmbjr`Udd@zlw2SKD*#obNh2J?xxSg ze2n&2zaYD>d$O|m1nj=KluzT++DW4#|dJKGlPkgRa zyRSd2xV{{&13!U0I&&BMiL-`Wq%J4E@O&olID!<>-{Z`Gr%-6K#{nf8^|Me4h?7pC%Fx+=i zon>6(W?iJdO?=@#3h-rjK3efwkS`*+`!LS0B5N3z@bk$#7r1u8OeYZ51&q5L~ZBZSB?z z1Vvf2%G#=pVqigm1(5`;ZETA~S~b0V8ZWh>t+KU<@!zkK+SabEm7vw8+LqO7`+sNO z^Q<$+%*WnlR`dIX-H`0ebDsA(&w0;#&di)i^T$6BU+ra@KNg#>dgS$Es*Z~NSsjP` zkMTIPlJ<2p(>N4a&OTAHaY(M0sJPYZ0w|7|d=>3(kv^f-9W3_i`YKbt3Vn4wXP!6f zxY7n(z@2Spo^_^Fj{A^t9yQO2c5q&}WYNLm1HzS>$Z^Eq7wfB5{-xGep|8;Id3W_IoAd$E2^WW{c;GI$Xbxi^DVfQI_qY3fLg>`{P+( zz-^aL;JDzcSbgDsEjV7OUR7Uh@56juv-e;jh_99@>=SnL1>K@us!w$MkbPn`joaTO zpYUE(TA%1to&y6MR=9j`aDPuf&;8LwS#lrZt8KsBKOy}fEyp?4@9XyDw(e;)4j~T) zPWV0I)bU^LkM|#3Ar2y3X&FbS{k~Y;$No|pUyVP@IyUf?@h==dd=Tqi^Hm5p@zwAX zi}BHB|3Vx+FDdyK;p%I^1>9&)zID0oL7azVKX35{=TZA(&yVD|oqp5xAoa&^1M^j~ zJbF&= z?qyuj+oZnb`e&)1OR3IlRlce{tov&hRfvAXSKU-+_&QMCq*dbj>hcQFpK!G~gv+Wv zfqG%EAM=umwcl8 zlG2Xbp$mKWiC*td85!9DUPj+*a$pY)! zx$iNx>oE7fXrH_157zfNbkM%o^heY&>j$yEW>=1NrwJGCmxjN`cu{B_(@J0J zycW2y{^+V?T(jnnb$>v(aQ`phLcUw-`6JqkcmNlC)nCQ9&RRFt{UPDP{j7k?u5nxS z3Fs@W=vRyHb8RF4>exCllV5yF-+Ah*!@{?~4_zkGPLWTH>0wPIG@uxcsl1apCiYUI!Mj*uQ4gAEA5S zV9D2R&HW$3h5JU8DvnmT&|c^)qc8dab-C`xdE9=kb)V~D(tYALoaaD~=r`*47*^I> zaeVdF%D-@2{5^CJeKow#d30^%IQM^vFWjFAd=;xNE53Rew=)oNUe5rI<54e;bBmEw zkA9u?^|_mGKW!dY5r<-5k>|wZ@jImMQ+JPd_aVL_Wy*8l_u4b&cI&tfGT;L4EDw45 zeI&&np% ze7@BA1deNkt6SolGk=2nV8Ye?C+?4Sh4MIe#BRMnSIs!thwDfuKosGz@6nGPhag6xz#ao9@SS{pJv_v z*7KI@G17gy#Jab-52czBmOd9|6vy{D_;d)sS(WAag~$Z1BtIThxkH!pQMSI+FR@^{0qnLlDbdLo8qn{zN%js(Xme*YDU@KQ(`JX#KJNKjwC)2-i>pF5u46kf-ijbJRV~1AXCV z*Er_u=s}0OhY_y8JD*Q|RsYw_bC%B{-#}kDzJI*b*T5s(!-=nkGV80$J>7Jlm=xji z8gK!3mWDj_)s>^Za31(7@(JH0=BsA@5$+L$EBG$!3xAJsztro`jUuY&ab zSzS+yxTcx<3qdW(7kmQ8ubT{?ILbYS`06T?PpJK|-N(45%spVr;ONAdOUu@f0L+Eu8pMl9B08kBX3V%N9p`qN+-kpO`?8|ygn8)XyBb9+`0A`7oYi8P}uzJ>n4JtNsYq z7x+q_%KNwUb!6l9e1U$s@!_}dd#gMe<4}vlwW#6_@jCIz%o3?aU}N1FA8abMl1(5B=AXt(;>tvnYKzwcFF^vmph zSEg|sUz+I=LkU+@!G(6IxN_Y;VTB9r1y1-Ebe%eqah*lii@rf|jGa=Rd;+@1^|gt~ ztgn~mc*LQ^S5n~%?Na&5HI5;R=M_V@;Hy@DQ^dZ zjvVs|oTpfQwfy=7Tj~JlkH{xF0vyL3tL_kci7(_6Xa~kIyYmU?9_>z^Aax)22rucY zxx+$VHrL73@v-Mb#>f1+a-|9=*@#T%>q3*#<6 z23*j6`$W4_AsW=*#mI`?mK~=Bxe*j~GpSwU6NZ z%Wl3@-NRSWZcXZ5OWz^hCVhFY`)v4Xo%GcWJ3V5It}pqVSiAXB=R@$-`hAM85?_Bc z@C81z+R1a>swc;M0_OoP@Zpo=_5-hY#9=yLGx)h~W$_6j0lwOLy7bkG72+M@3%-hW zIOVIw`b6D3=J;phT;vFUS&VD$$bMoR@#Q<3^@Vm| zKc`xsNPdu8o@|w`s&%Gf{mcKVJ@ZGz5qt!tPi&stPmCwN8YEv%#}Ph(c6-j0J`r0X z{!aQzmMPCEHje4Pnfr0JzvlTS(#-q(@iD|PtQ=n>zTPwN1wQe)eCLmmCvx)%oCk44 zyE|vgIEMO(38XLA&&%ug$aB(XGp-%0R*3g?|Jud#A+*D(JO^>?`MX&s8u2yJz!&%| zG>-8c>i{?p@(HZN_~tTSi<(x5e-K|-hXG$sufrgY9TL}$1^vV%;tO#^JDiFm_`*6& z-8|-N^|lq_pTrmHOyJ9|{7aobs>ibzsql zWF2#!`SivCRXRm z@+;ruI!^;%@UQ9%7}tiK{lt;P7wVYctJv|;3O|mEcBr^oC9cLN?iBwfzS7d~!52PX z=(?2^u3qD4@cW3&qwn6+PaH*j`Hx|ru$wQde4_igX_@t?t_wMi7rt<(_=xywoyFrL z`0}6f$$qAthW$A%`TvN6)vFa>E~P)fC%}h4#JC=Kv!6Ix_j}2g)AMcUtLtyvAHC-? zuBun>6dw~`^*8c31isL&La$G=+6SZRt5zqxh;cjkzCGhM;s`#vWuDXg=AGg{#8=($ z@~ra_u1ql+?G8%aYu^6i7}A&L7v&kZi;ZK~etYAXQt~^UFTa5=@R{xZdDd6kbDVGE zJcuLO?ODM6QS&s4|B}9Z(elI*<2L-OvyO4iJ-oj-miP+z85i1N^i|_N(Oi8s*Kr&D z(X+>_6P+*D&`xf1n zh%e+{XopkzSFt|fx5+0kJ|ZvlUB-MhPH7ZX%#`5nh@~`&aC_X`aO*8NX zKC`FE)9+oobDO8(JkS^NujWgbuc|qX!cBZ3{{mmd=3n{lCr5oEd@9!`mMrftP9VPU z{0_9kuKI+U7s6M;NBzajSMx=UqA&3knO&axSF!%pBcDf-)m@3+VBAi=&G&ohkp309 zzrUD4aqO1kHsWaPk2Qw*kYztpa9WMq@J0MN{0r@lN2Gtn8pXjB$DTti;%M_eQRoYN zB)-VF5)btk0pcrotc9;q!-Di}*FHYrN~IM4BEBjNe1T8!oNt|}{psBN3+E|T_iakv zmc^a#n?3_g`>dgR|a|~Hwq8&g**rCFzVizuNJHOUi>RFPeZ%AFPFMc_7^9T zzM{`t=*uD9yMC+ai*U^}-~#S!c=8+{y*ZALI1l1jJ(u%|U_J9SWP79NPjRe1i+!TE zINF&{WN?u`Vth<}mG!l-<}`6eHC-n?lIte1(Tv-!@v+zY`w}dyi*`xAcI@ddPNFzs zT@?JHerEUnXz+zRr{M~YW7SiQVgSVvc@E;}be@C!zU6Ah)ws96IGOmux+wUYKH|Fdq`W^sYThyK33Pve`0vYmzahjaEd6Wq^NnJl9!J?9%TmWA@~~c8 zzl7shzrVjYh2n_yTD#+DwO-qL5Z9v-Upo|@pDh7yCDUMi2wmXjSA2bKJ;P*+1Yu>tJ+>j#aZisFcQ2l#br-hnvcc_-Re7}us51H|bR$CMIBA7wV``EvHmvJ16<;zOL=r@JlC(z1Q)$y@dUyZzN@4Oa#d2Z!6UcYL9IE&)g za$ITiXshuNc?$X!;)wCFMdAw2KhAw5#WDRM>kDzTYkb6UfeXHhc%)*?msYn@45j{9 z=lyKVYXi42uBA-_L=D9;?NA)U%Kg?5N6d#plCS9Qdu5(8W6<&LqlvF@g~d7yH7rQqcCGVe_@d)u z{+Qn8%dBf{UA$5ZBi&>Eh<;(rzl`$^tNu@iHho#eQT0{e@=oKt(0@C}(e=y#aW=&< ze7xDe((*c5^?opQ7WZc}fubL*@T=<`wfYB($fH9CoAVGAN3K7o-Zx*Dsp>v`2lI8q z&H-W$@ztvERqXg^m4B&z4_`&QJEec6?w;m8hIHTkhw`o~K-bY*n6LX*t`uI8P+x6W&A4V)p5Q)?;)v%-BaZOpQrA~;T=WcSQmx9FrO;4?rVk1iZA4= zDT!=X=GfR|Fu$#r8xS|F3PmtAq}b>3mn zmv*0wb2N$J3hcXeie!f4|Oz& zDWui~^UNp0?L$rZm5LWX<2=CCHBP}ralFtNN3|}PC$7Ltx$Sd@o)AaW3q#+O{jvHq z_xaQxQ7V{2KEw<9>i*ubWf(g1!)^wg;Fm56y=zpg0EI7XC#X2kG0c`A|k*hWU2<`;4n` z#wsy^;+S1Wmi@8Vd?Md@E$TUbISyU9ZJ<~{aqK!#`l{@YcIAc82ZbQ>rSj!n%HzPTPlnHJ+VwZ%@pfD3VK zxtQw&(+8dIzL?_Z8eCqVz`A?$L(EszC9A|Fieq-&9pkoPpOrC=UW+_|T4wsP%sZ6N z*Xo}tV*N2T(LCOpK;-d5xP|j6e56oZzMpd5600f=uC|BGxS%ieH@{pTx_99!F2a1cSKl+ju{n6$;I*Uujqg~=k?K<6kiQXSyxAs*R zjjML?Rj9rQaptRgOlkCmX>3az8=R*3~@x9@wt4j7Y*l_N8>!eg>l)pn8)o_ zx-K(H<96zw7WyK9LHf2Uj=-f=GhfY5vhH<#U24$Rr~Dw#c}KPMl`P*DZ*U&y9y;;1 z$^IB$C8m&1#70~Agw6dilYbF*6K3A-R-vMu~uSw}I zx&D2we+Ryxd;e1$$Hr}|#Nm2AA)j}GxP$LP_qpdge*~_i#5I!q{xXVV^U3Bo7K_Vj zp4LnKD^o92AMiXa{WQn%OrFfRkbl|L zAJfWnpP?`8H_h#4V;n8@Oq?3O@{J?-Xp?#LC>n<@C%!sQ zDPtU|L8wPZq~D*gahCgX;wv(Q>rCJ)b{=1spsx=Z`O?nM?Rteg_{xlrez^|Q@e_`t zmR==}Cf)nSSny@@_*kn4zlb_h_#_@zjT$QCec}Zk@91?HTSXD316- zKJiH$T_uep#u1zk<74LpWqhPK9%G0j;*8JbJ3dzbXJ}6Ad^iv0wTMUjr&3?dgTxio zAN{{%ew|*g1z(6$=m(7Js6l7CucSCu4=rQemx6%{#1V1Mo+i(EZGDb)CY+~OpNP*fwP(2cF<-4Q=)Tx|RmBDWf==3g&U~eIo$0=ce4_nN<*7%5ujZNj+?w{Eab51csc~@} z#j#H2tB9lVd2_~mBG>25S;f(69P-aK_bZ*Rg$BOBCv=(bI26xuo`&< z67|Gai>xz&uO2yHFZKNkReh;(^uNfsX3d}Nt|xuPj^X(u;%-+QaokMs=pXp~M+N$Q za+0~f;JC%Us(eLuGhb`>4ibwgj**}=7bj4E>?+fI2ysLmz}Lxf{L218;%bUx_37p~+SMO>-G@x%HOyoEdVa~c zT7Es-eKo}~sl+k*%+SpIL7msObGX*Em}KowD9htnSlC+o*feFV;H}FEL+L+v8#;@rCsc@C9GC zd%XkWHrlO8-D`D~;yTh-@K+Z4vbl~4-Gh&$%vU!*9v3GOU#a6KWX8i!)xT`kJ#h8- z%{tNfT58}6d=eb~%Cnx+kYhau=P6eAu9>B&`=Ysch2Nt-QT1 zue5s~40MlndtYH(T31}0O#1R4W-))XS@#%+kgo<`Wn4>_SBhoCSHqdyAHkPh`6}Xo zI70WHBNW{eU#A%O0-yL?zIkC?j&*XJN98N}JLao?Ri(I|`0~$ohA(v=40MlrwCDGX zYwNzaIF{0r@Fkv^eyRf-!)U!h&)&A-4$ ztc&$^@8s3u4C1T$T#NCM;uNHByXGAjhgwcH=PNp2HyQW>pIO=DnSVtt&+Yn0oTpYl zQ4#Czbw`#)_u2N!H}DDMUx`0)9Cz%k6w8S(n9#(k&qFSNV)kBmzTtroLLU#T}g z8}|YC{h4ts*;3P^%X)Tko)g~7e7$`0YEeUc)yr`Rd>Qp+XPyJTkgs-2Tw7*T ziCc)T)Epik;S%PYRzg9()qfP*WJMvK5uuO3Ao^2{uIaY zx|%9+EAizy+!=kT>uJa*z(@LZ#F46+N%Kc@FgBlH=nzns?kreAUfizMQUq z)#^ekBF_mabu;L;*w?7}whSs>JQYS70Hpi-NDN-Je{q zV8qo`ncFUwI^iyw^Q{Tj6?A^d7c*e2lF-Uk~QK&;wvWmBlt3oLr%=oFduTg$GEDl zUL!6dT<|a8a@xOe-uk~YuBMyThy{eJvrPU4pJ`tMQ37;!?r| zUj;6weYNe2eEo>_0pt4Z3v0v|2$$~y);(|;`Et^~eE(uxRj;lQUnE@cFW_?8zi{5f zKN;6I-drOtBV1jQug_b3qWM&_zd+x`zQR{={C24?&2yLd67khtCSO&3!ut`&aqEb? z#Fqⅆ++Qx_8ni+9a;VDR+s>2^V|u11{hO&-w2Eign~x|H63?N7Tt%Wqsn&x2nWSies|Y ztS{6zRDHGOST|{X$pW8J=gHtAonXDA^}nq9*_9#pb;MVvyeEv zj^KHRw_3z0j-HKWo2O;&ixHd8?e_FxT&aO)yQ37x`ZD`h^dxgUG~#QufiLix4NsnR zreu!$ws9WlUOUH(OXq8ufiLh`D6T|~zKZi?ef4dwBP9>!IPREIE!GfUs57A*j@FsT zS5cRXR4}fy=AZ4pp7@G;*(cBrjQfRNr&H*>HsR-dqH#vGxQqDeJbGfLe}XT&a3K!R z3C5u$^wpR7TDa+K_YK5XV1${kV&{)meBrpj1>GY~od+?lO7i=!5Uy^Ct1S7dL0=vH z7+2$hYOz+2qZ}XYj-$#~txjAK>k84Z*1K_4n#h-2&!=4;OGx$dtLU+H!&lYfCP@a@!nSAeT} zFyr!(-)|zmBI_Afsr=rmKYC9w*TtYO;A)k)=2gyfe~tKR9?5y3-F)?WpHqXrq9=16 zef^$laWC=Ja-1{zf?r$dD>#JXc>er(?pt(yjdF%BHP1mDJLI?>AHcZo**MRAE8%J# zZN`PXve5m$R{FB?d+5t^DC4?zf3;|$IEIgRCXT9qAtwzuxac1wO%ZzUvAdInFz99_R~v`A2XZ�X5zMXJs@_uRf`(pXBs+(B( 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 = packedMsgLen16; - + if(!push16(packedMsgLen16, &pPackedLengthField, end)) return -1; - + if(1) { //quick test @@ -6370,11 +6370,10 @@ static uint8_t unpack_tx_request(uint8_t **ppReadPackedMsg, uint8_t *end, void * //SLOT INDICATION -static uint8_t unpack_nr_slot_indication(uint8_t **ppReadPackedMsg, uint8_t *end, nfapi_nr_rx_data_indication_t *msg, nfapi_p7_codec_config_t* config) +static uint8_t unpack_nr_slot_indication(uint8_t **ppReadPackedMsg, uint8_t *end, nfapi_nr_slot_indication_scf_t *msg, nfapi_p7_codec_config_t* config) { nfapi_nr_slot_indication_scf_t *pNfapiMsg = (nfapi_nr_slot_indication_scf_t*)msg; - printf("\n"); if (!(pull16(ppReadPackedMsg, &pNfapiMsg->sfn , end) && pull16(ppReadPackedMsg, &pNfapiMsg->slot , end) )) @@ -6406,7 +6405,6 @@ static uint8_t unpack_nr_rx_data_indication(uint8_t **ppReadPackedMsg, uint8_t * { nfapi_nr_rx_data_indication_t *pNfapiMsg = (nfapi_nr_rx_data_indication_t*)msg; - printf("\n"); if (!(pull16(ppReadPackedMsg, &pNfapiMsg->sfn , end) && pull16(ppReadPackedMsg, &pNfapiMsg->slot , end) && pull16(ppReadPackedMsg, &pNfapiMsg->number_of_pdus, end) diff --git a/nfapi/open-nFAPI/pnf/src/pnf_p7.c b/nfapi/open-nFAPI/pnf/src/pnf_p7.c index c04285c62e..5960f4af8e 100644 --- a/nfapi/open-nFAPI/pnf/src/pnf_p7.c +++ b/nfapi/open-nFAPI/pnf/src/pnf_p7.c @@ -1772,7 +1772,7 @@ void pnf_handle_ul_tti_request(void* pRecvMsg, int recvMsgLen, pnf_p7_t* pnf_p7) struct timespec t; clock_gettime(CLOCK_MONOTONIC, &t); - NFAPI_TRACE(NFAPI_TRACE_INFO,"%s() %ld.%09ld POPULATE UL_TTI_REQ current tx sfn/slot:%d.%d p7 msg sfn/slot: %d.%d buffer_index:%d\n", __FUNCTION__, t.tv_sec, t.tv_nsec, pnf_p7->sfn,pnf_p7->slot, req->SFN, req->Slot, buffer_index); + //NFAPI_TRACE(NFAPI_TRACE_INFO,"%s() %ld.%09ld POPULATE UL_TTI_REQ current tx sfn/slot:%d.%d p7 msg sfn/slot: %d.%d buffer_index:%d\n", __FUNCTION__, t.tv_sec, t.tv_nsec, pnf_p7->sfn,pnf_p7->slot, req->SFN, req->Slot, buffer_index); if(pnf_p7->slot_buffer[buffer_index].ul_tti_req != 0) { diff --git a/openair1/SCHED_NR/fapi_nr_l1.c b/openair1/SCHED_NR/fapi_nr_l1.c index 23e18f5787..6a77d0e3c3 100644 --- a/openair1/SCHED_NR/fapi_nr_l1.c +++ b/openair1/SCHED_NR/fapi_nr_l1.c @@ -172,7 +172,7 @@ void nr_schedule_response(NR_Sched_Rsp_t *Sched_INFO){ nfapi_nr_ul_dci_request_t *UL_dci_req = Sched_INFO->UL_dci_req; frame_t frame = Sched_INFO->frame; sub_frame_t slot = Sched_INFO->slot; - //printf("Inside nr_schedule_resp SFN:%d, slot:%d \n",Sched_INFO->frame, Sched_INFO->slot); + AssertFatal(RC.gNB!=NULL,"RC.gNB is null\n"); AssertFatal(RC.gNB[Mod_id]!=NULL,"RC.gNB[%d] is null\n",Mod_id); @@ -181,71 +181,69 @@ void nr_schedule_response(NR_Sched_Rsp_t *Sched_INFO){ uint8_t number_dl_pdu = (DL_req==NULL) ? 0 : DL_req->dl_tti_request_body.nPDUs; uint8_t number_ul_dci_pdu = (UL_dci_req==NULL) ? 0 : UL_dci_req->numPdus; uint8_t number_ul_tti_pdu = (UL_tti_req==NULL) ? 0 : UL_tti_req->n_pdus; + uint8_t number_tx_data_pdu = (TX_req == NULL) ? 0 : TX_req->Number_of_PDUs; - if (DL_req != NULL && TX_req!=NULL) - LOG_D(PHY,"NFAPI: Sched_INFO:SFN/SLOT:%04d/%d DL_req:SFN/SLO:%04d/%d:dl_pdu:%d tx_req:SFN/SLOT:%04d/%d:pdus:%d;ul_dci %d ul_tti %d\n", - frame,slot, - DL_req->SFN,DL_req->Slot,number_dl_pdu, - TX_req->SFN,TX_req->Slot,TX_req->Number_of_PDUs, - number_ul_dci_pdu,number_ul_tti_pdu); + if (NFAPI_MODE == NFAPI_MONOLITHIC){ + if (DL_req != NULL && TX_req!=NULL) + LOG_D(PHY,"NFAPI: Sched_INFO:SFN/SLOT:%04d/%d DL_req:SFN/SLO:%04d/%d:dl_pdu:%d tx_req:SFN/SLOT:%04d/%d:pdus:%d;ul_dci %d ul_tti %d\n", + frame,slot, + DL_req->SFN,DL_req->Slot,number_dl_pdu, + TX_req->SFN,TX_req->Slot,TX_req->Number_of_PDUs, + number_ul_dci_pdu,number_ul_tti_pdu); - int pdcch_received=0; - gNB->num_pdsch_rnti[slot]=0; - for (int i=0; inumber_of_nr_dlsch_max; i++) { - gNB->dlsch[i][0]->rnti=0; - gNB->dlsch[i][0]->harq_mask=0; - } + int pdcch_received=0; + gNB->num_pdsch_rnti[slot]=0; + for (int i=0; inumber_of_nr_dlsch_max; i++) { + gNB->dlsch[i][0]->rnti=0; + gNB->dlsch[i][0]->harq_mask=0; + } - for (int i=0;idl_tti_request_body.dl_tti_pdu_list[i]; - LOG_D(PHY,"NFAPI: dl_pdu %d : type %d\n",i,dl_tti_pdu->PDUType); - switch (dl_tti_pdu->PDUType) { - case NFAPI_NR_DL_TTI_SSB_PDU_TYPE: + for (int i=0;idl_tti_request_body.dl_tti_pdu_list[i]; + LOG_D(PHY,"NFAPI: dl_pdu %d : type %d\n",i,dl_tti_pdu->PDUType); + switch (dl_tti_pdu->PDUType) { + case NFAPI_NR_DL_TTI_SSB_PDU_TYPE: - if(NFAPI_MODE != NFAPI_MODE_VNF) handle_nr_nfapi_ssb_pdu(gNB,frame,slot, - dl_tti_pdu); + dl_tti_pdu); - break; + break; - case NFAPI_NR_DL_TTI_PDCCH_PDU_TYPE: - AssertFatal(pdcch_received == 0, "pdcch_received is not 0, we can only handle one PDCCH PDU per slot\n"); - if(NFAPI_MODE != NFAPI_MODE_VNF) - handle_nfapi_nr_pdcch_pdu(gNB, - frame, slot, - &dl_tti_pdu->pdcch_pdu); - - pdcch_received = 1; + case NFAPI_NR_DL_TTI_PDCCH_PDU_TYPE: + AssertFatal(pdcch_received == 0, "pdcch_received is not 0, we can only handle one PDCCH PDU per slot\n"); - break; - case NFAPI_NR_DL_TTI_CSI_RS_PDU_TYPE: - LOG_D(PHY,"frame %d, slot %d, Got NFAPI_NR_DL_TTI_CSI_RS_PDU_TYPE for %d.%d\n",frame,slot,DL_req->SFN,DL_req->Slot); - handle_nfapi_nr_csirs_pdu(gNB, - frame, slot, - &dl_tti_pdu->csi_rs_pdu); - break; - case NFAPI_NR_DL_TTI_PDSCH_PDU_TYPE: + handle_nfapi_nr_pdcch_pdu(gNB, + frame, slot, + &dl_tti_pdu->pdcch_pdu); + pdcch_received = 1; - { + break; + + case NFAPI_NR_DL_TTI_CSI_RS_PDU_TYPE: + LOG_D(PHY,"frame %d, slot %d, Got NFAPI_NR_DL_TTI_CSI_RS_PDU_TYPE for %d.%d\n",frame,slot,DL_req->SFN,DL_req->Slot); + handle_nfapi_nr_csirs_pdu(gNB, + frame, slot, + &dl_tti_pdu->csi_rs_pdu); + break; + case NFAPI_NR_DL_TTI_PDSCH_PDU_TYPE: + LOG_D(PHY,"frame %d, slot %d, Got NFAPI_NR_DL_TTI_PDSCH_PDU_TYPE for %d.%d\n",frame,slot,DL_req->SFN,DL_req->Slot); nfapi_nr_dl_tti_pdsch_pdu_rel15_t *pdsch_pdu_rel15 = &dl_tti_pdu->pdsch_pdu.pdsch_pdu_rel15; uint16_t pduIndex = pdsch_pdu_rel15->pduIndex; - AssertFatal(TX_req->pdu_list[pduIndex].num_TLV == 1, "TX_req->pdu_list[%d].num_TLV %d != 1\n", - pduIndex,TX_req->pdu_list[pduIndex].num_TLV); + AssertFatal(TX_req->pdu_list[pduIndex].num_TLV == 1, "TX_req->pdu_list[%d].num_TLV %d != 1\n", + pduIndex,TX_req->pdu_list[pduIndex].num_TLV); uint8_t *sdu = (uint8_t *)TX_req->pdu_list[pduIndex].TLVs[0].value.direct; if(NFAPI_MODE != NFAPI_MODE_VNF) handle_nr_nfapi_pdsch_pdu(gNB,frame,slot,&dl_tti_pdu->pdsch_pdu, sdu); + } } - } - // if (UL_tti_req!=NULL) memcpy(&gNB->UL_tti_req,UL_tti_req,sizeof(nfapi_nr_ul_tti_request_t)); - if(NFAPI_MODE != NFAPI_MODE_VNF) + for (int i=0;iul_dci_pdu_list[i]); } - - if(NFAPI_MODE != NFAPI_MODE_VNF) + for (int i = 0; i < number_ul_tti_pdu; i++) { switch (UL_tti_req->pdus_list[i].pdu_type) { case NFAPI_NR_UL_CONFIG_PUSCH_PDU_TYPE: @@ -264,32 +262,22 @@ void nr_schedule_response(NR_Sched_Rsp_t *Sched_INFO){ break; } } - - //printf("Inside NR schedule response SFN/slot %d.%d. \n",frame,slot); - if(NFAPI_MODE != NFAPI_MONOLITHIC && number_ul_tti_pdu>0) - { - LOG_I(MAC,"SFN/slot %d.%d Sending ul tti req \n",frame,slot); - oai_nfapi_ul_tti_req(UL_tti_req); } - - if (NFAPI_MODE != NFAPI_MONOLITHIC && Sched_INFO->UL_dci_req->numPdus!=0) - { - oai_nfapi_ul_dci_req(Sched_INFO->UL_dci_req); + + if (NFAPI_MODE == NFAPI_MODE_VNF) { //If VNF, oai_nfapi functions send respective p7 msgs to PNF for which nPDUs is greater than 0 + + if(number_ul_tti_pdu>0) + oai_nfapi_ul_tti_req(UL_tti_req); + + if (number_ul_dci_pdu>0) + oai_nfapi_ul_dci_req(UL_dci_req); + + if (number_dl_pdu>0) + oai_nfapi_dl_tti_req(DL_req); + + if (number_tx_data_pdu>0) + oai_nfapi_tx_data_req(TX_req); + } - if (NFAPI_MODE != NFAPI_MONOLITHIC) - { - if(Sched_INFO->DL_req->dl_tti_request_body.nPDUs>0) - { - Sched_INFO->DL_req->SFN = frame; - Sched_INFO->DL_req->Slot = slot; - oai_nfapi_dl_tti_req(Sched_INFO->DL_req); - } - if (Sched_INFO->TX_req->Number_of_PDUs > 0) - { - oai_nfapi_tx_data_req(Sched_INFO->TX_req); - } - - } - } diff --git a/openair1/SCHED_NR/phy_procedures_nr_gNB.c b/openair1/SCHED_NR/phy_procedures_nr_gNB.c index c1dd64af5d..9f40821d04 100644 --- a/openair1/SCHED_NR/phy_procedures_nr_gNB.c +++ b/openair1/SCHED_NR/phy_procedures_nr_gNB.c @@ -164,7 +164,7 @@ void phy_procedures_gNB_TX(PHY_VARS_gNB *gNB, gNB->Mod_id,frame,slot,pdcch_pdu_id,ul_pdcch_pdu_id); if (pdcch_pdu_id >= 0 || ul_pdcch_pdu_id >= 0) { - LOG_I(PHY, "[gNB %d] Frame %d slot %d Calling nr_generate_dci_top (number of UL/DL DCI %d/%d)\n", + LOG_D(PHY, "[gNB %d] Frame %d slot %d Calling nr_generate_dci_top (number of UL/DL DCI %d/%d)\n", gNB->Mod_id, frame, slot, gNB->ul_pdcch_pdu[ul_pdcch_pdu_id].pdcch_pdu.pdcch_pdu.pdcch_pdu_rel15.numDlDci, gNB->pdcch_pdu[pdcch_pdu_id].pdcch_pdu.pdcch_pdu_rel15.numDlDci); diff --git a/openair2/NR_PHY_INTERFACE/NR_IF_Module.c b/openair2/NR_PHY_INTERFACE/NR_IF_Module.c index 26978ebc30..db3251ae99 100644 --- a/openair2/NR_PHY_INTERFACE/NR_IF_Module.c +++ b/openair2/NR_PHY_INTERFACE/NR_IF_Module.c @@ -216,7 +216,15 @@ void NR_UL_indication(NR_UL_IND_t *UL_info) { module_id,CC_id, UL_info->rach_ind.number_of_pdus, UL_info->rx_ind.number_of_pdus, UL_info->crc_ind.number_crcs); + handle_nr_rach(UL_info); + + handle_nr_uci(UL_info); + // clear UL DCI prior to handling ULSCH + mac->UL_dci_req[CC_id].numPdus = 0; + handle_nr_ulsch(UL_info); + if (NFAPI_MODE != NFAPI_MODE_PNF) { + if (ifi->CC_mask==0) { ifi->current_frame = UL_info->frame; ifi->current_slot = UL_info->slot; @@ -226,16 +234,7 @@ void NR_UL_indication(NR_UL_IND_t *UL_info) { } ifi->CC_mask |= (1<UL_dci_req[CC_id].numPdus = 0; - handle_nr_ulsch(UL_info); - - if (NFAPI_MODE != NFAPI_MODE_PNF) { if (ifi->CC_mask == ((1< Date: Mon, 9 Aug 2021 19:41:22 +0530 Subject: [PATCH 82/91] Code cleanup and documentation update --- .gitlab-ci.yml | 1 - doc/{NFAPI_archi.md => NR_NFAPI_archi.md} | 23 +++++------- executables/nr-gnb.c | 9 +++-- nfapi/nrNFAPI.md | 20 +++++++++-- nfapi/oai_integration/nfapi_pnf.c | 20 +++++------ nfapi/oai_integration/nfapi_pnf.h | 13 +++++-- nfapi/oai_integration/nfapi_vnf.c | 27 ++------------ nfapi/oai_integration/nfapi_vnf.h | 6 ++-- .../nfapi/public_inc/nfapi_nr_interface_scf.h | 2 +- nfapi/open-nFAPI/nfapi/src/nfapi_p7.c | 13 +++---- nfapi/open-nFAPI/pnf/inc/pnf_p7.h | 2 ++ nfapi/open-nFAPI/pnf/src/pnf_p7.c | 6 ++-- nfapi/open-nFAPI/pnf/src/pnf_p7_interface.c | 10 ++++++ nfapi/open-nFAPI/vnf/src/vnf_p7.c | 22 +++++------- nfapi/open-nFAPI/vnf/src/vnf_p7_interface.c | 10 ++---- .../PHY/LTE_UE_TRANSPORT/dlsch_decoding.c | 10 +++--- openair1/PHY/NR_TRANSPORT/nr_dci_tools.c | 8 ++--- openair1/PHY/NR_TRANSPORT/nr_dlsch_coding.c | 2 +- openair1/PHY/NR_TRANSPORT/nr_ulsch_decoding.c | 2 +- openair1/PHY/NR_TRANSPORT/pucch_rx.c | 2 -- openair1/SCHED_NR/fapi_nr_l1.c | 36 +++++++++---------- openair1/SCHED_NR/phy_procedures_nr_gNB.c | 16 ++++----- openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c | 14 ++++---- .../LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c | 8 +---- .../LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c | 8 ++--- openair2/NR_PHY_INTERFACE/NR_IF_Module.c | 6 ++++ 26 files changed, 135 insertions(+), 161 deletions(-) delete mode 100644 .gitlab-ci.yml rename doc/{NFAPI_archi.md => NR_NFAPI_archi.md} (76%) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml deleted file mode 100644 index 8b13789179..0000000000 --- a/.gitlab-ci.yml +++ /dev/null @@ -1 +0,0 @@ - diff --git a/doc/NFAPI_archi.md b/doc/NR_NFAPI_archi.md similarity index 76% rename from doc/NFAPI_archi.md rename to doc/NR_NFAPI_archi.md index 6bc906f494..2c92f9497d 100644 --- a/doc/NFAPI_archi.md +++ b/doc/NR_NFAPI_archi.md @@ -60,7 +60,7 @@ void handle_nr_rach(NR_UL_IND_t *UL_info) { ## P7 UL reception at VNF -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 message, UL_INFO struct on the VNF side gets populated. The NR_UL_indication() function is then called at the VNF, which uses UL_INFO. +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. ``` @@ -68,17 +68,6 @@ Through the infinite loop [while(vnf_p7->terminate == 0)] running in nfapi_nr_vn if(FD_ISSET(vnf_p7->socket, &rfds)) { vnf_nr_p7_read_dispatch_message(vnf_p7); - - // Call the scheduler - struct PHY_VARS_gNB_s *gNB = RC.gNB[0]; - pthread_mutex_lock(&gNB->UL_INFO_mutex); - gNB->UL_INFO.frame = vnf_frame; - gNB->UL_INFO.slot = vnf_slot; - - gNB->UL_INFO.module_id = gNB->Mod_id; - gNB->UL_INFO.CC_id = gNB->CC_id; - gNB->if_inst->NR_UL_indication(&gNB->UL_INFO); - pthread_mutex_unlock(&gNB->UL_INFO_mutex); } ``` @@ -87,7 +76,7 @@ vnf_nr_dispatch_p7_message() is the function that contains the switch on various ## P7 DL Transmission by VNF -DL messages are scheduled at the VNF, through NR_UL_indication() after processing of UL_INFO. The function performing the scheduling of channels (and consequently p7 messages in nFAPI) is gNB_dlsch_ulsch_scheduler(). +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 @@ -109,12 +98,15 @@ graph TD slot_inc -- next slot --> pselect ``` +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 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. -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). A point to note is 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). Ideally, it should be received within a duration significantly lesser than slot_ahead so that there is adequate time for PHY processing. +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). ```mermaid @@ -124,7 +116,8 @@ graph TB slot_inc -- next slot --> pselect ``` - +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/executables/nr-gnb.c b/executables/nr-gnb.c index 7a8ff0dabe..f09d25e6d7 100644 --- a/executables/nr-gnb.c +++ b/executables/nr-gnb.c @@ -133,7 +133,7 @@ void tx_func(void *param) { } void rx_func(void *param) { - + processingData_L1_t *info = (processingData_L1_t *) param; PHY_VARS_gNB *gNB = info->gNB; int frame_rx = info->frame_rx; @@ -142,7 +142,7 @@ void rx_func(void *param) { int slot_tx = info->slot_tx; sl_ahead = sf_ahead*gNB->frame_parms.slots_per_subframe; nfapi_nr_config_request_scf_t *cfg = &gNB->gNB_config; - LOG_D(PHY,"slot rx %d \n", slot_rx); + start_meas(&softmodem_stats_rxtx_sf); // ******************************************************************* @@ -214,7 +214,6 @@ void rx_func(void *param) { gNB->pucch[j]->pucch_pdu.rnti = 0; pucch_removed++; } - #if 0 for (j = 0; j < NUMBER_OF_NR_PDCCH_MAX; j++) gNB->pdcch_pdu[j].frame = -1; @@ -253,7 +252,7 @@ void rx_func(void *param) { stop_meas( &softmodem_stats_rxtx_sf ); LOG_D(PHY,"%s() Exit proc[rx:%d%d tx:%d%d]\n", __FUNCTION__, frame_rx, slot_rx, frame_tx, slot_tx); - + // Call the scheduler start_meas(&gNB->ul_indication_stats); @@ -265,7 +264,7 @@ void rx_func(void *param) { gNB->if_inst->NR_UL_indication(&gNB->UL_INFO); pthread_mutex_unlock(&gNB->UL_INFO_mutex); stop_meas(&gNB->ul_indication_stats); - + notifiedFIFO_elt_t *res; if (tx_slot_type == NR_DOWNLINK_SLOT || tx_slot_type == NR_MIXED_SLOT) { diff --git a/nfapi/nrNFAPI.md b/nfapi/nrNFAPI.md index 9b996bbedf..264c0a3b07 100644 --- a/nfapi/nrNFAPI.md +++ b/nfapi/nrNFAPI.md @@ -2,7 +2,7 @@ ## Conributed by 5G Testbed IISc -### Developers: Mahesh K,Gokul S,Aniq U R, Sai Shruthi N, Sudhakar B +### Developers: Gokul S, Mahesh A, Aniq U R ## Procedure to Build gNB and UE @@ -34,7 +34,21 @@ sudo ./nr-softmodem -O ../../../targets/PROJECTS/GENERIC-LTE-EPC/CONF/oaiL1.nfap sudo RFSIMULATOR=127.0.0.1 ./nr-uesoftmodem --rfsim --phy-test --rrc_config_path . -d ``` -## Procedure to run NR nFAPI using Hardware +## Procedure to run NR nFAPI using Hardware (tested with USRP x310) -To be updated. +### VNF command +``` +sudo ./nr-softmodem -O ../../../targets/PROJECTS/GENERIC-LTE-EPC/CONF/rcc.band78.tm1.106PRB.nfapi.conf --nfapi 2 --noS1 --phy-test + +``` +### PNF command +``` +sudo ./nr-softmodem -O ../../../targets/PROJECTS/GENERIC-LTE-EPC/CONF/oaiL1.nfapi.usrpx300.conf --nfapi 1 --phy-test + +``` +### UE command +``` +sudo ./nr-uesoftmodem --usrp-args "addr=*USRP_ADDRESS*,clock_source=external,time_source=external" --phy-test --rrc_config_path ../../../ci-scripts/rrc-files + +``` diff --git a/nfapi/oai_integration/nfapi_pnf.c b/nfapi/oai_integration/nfapi_pnf.c index 5957f173f3..df32c05b60 100644 --- a/nfapi/oai_integration/nfapi_pnf.c +++ b/nfapi/oai_integration/nfapi_pnf.c @@ -37,8 +37,6 @@ #include "nfapi_pnf.h" #include "common/ran_context.h" #include "openair2/PHY_INTERFACE/phy_stub_UE.h" -//#include "openair1/PHY/vars.h" -extern RAN_CONTEXT_t RC; #include #include @@ -67,6 +65,7 @@ extern RAN_CONTEXT_t RC; extern void phy_init_RU(RU_t *); extern int config_sync_var; +extern RAN_CONTEXT_t RC; extern pthread_cond_t nfapi_sync_cond; extern pthread_mutex_t nfapi_sync_mutex; @@ -110,8 +109,12 @@ extern void nr_fill_prach_ru(RU_t *ru, int Slot, nfapi_nr_prach_pdu_t *prach_pdu); - - +int nfapi_pnf_p7_nr_slot_ind(nfapi_pnf_p7_config_t* config, nfapi_nr_slot_indication_scf_t* ind); +int nfapi_pnf_p7_nr_rx_data_ind(nfapi_pnf_p7_config_t* config, nfapi_nr_rx_data_indication_t* ind); +int nfapi_pnf_p7_nr_crc_ind(nfapi_pnf_p7_config_t* config, nfapi_nr_crc_indication_t* ind); +int nfapi_pnf_p7_nr_srs_ind(nfapi_pnf_p7_config_t* config, nfapi_nr_srs_indication_t* ind); +int nfapi_pnf_p7_nr_uci_ind(nfapi_pnf_p7_config_t* config, nfapi_nr_uci_indication_t* ind); +int nfapi_pnf_p7_nr_rach_ind(nfapi_pnf_p7_config_t* config, nfapi_nr_rach_indication_t* ind); nfapi_tx_request_pdu_t *tx_request_pdu[1023][10][10]; // [frame][subframe][max_num_pdus] uint8_t nr_tx_pdus[32][16][4096]; @@ -1146,16 +1149,13 @@ int pnf_phy_ul_dci_req(gNB_L1_rxtx_proc_t *proc, nfapi_pnf_p7_config_t *pnf_p7, // LOG_D(PHY,"[PNF] HI_DCI0_REQUEST SFN/SF:%05d dci:%d hi:%d\n", NFAPI_SFNSF2DEC(req->sfn_sf), req->hi_dci0_request_body.number_of_dci, req->hi_dci0_request_body.number_of_hi); - //phy_info* phy = (phy_info*)(pnf_p7->user_data); struct PHY_VARS_gNB_s *gNB = RC.gNB[0]; if (proc ==NULL) proc = &gNB->proc.L1_proc; - //int slot_tx = req->Slot + 6; //Ref for PNF is slot_rx, so align slot number with tx thread before passing UL_DCI info + for (int i=0; inumPdus; i++) { - //LOG_D(PHY,"[PNF] HI_DCI0_REQ sfn_sf:%d PDU[%d]\n", NFAPI_SFNSF2DEC(req->sfn_sf), i); if (req->ul_dci_pdu_list[i].PDUType == 0) { - //LOG_D(PHY,"[PNF] HI_DCI0_REQ sfn_sf:%d PDU[%d] - NFAPI_HI_DCI0_DCI_PDU_TYPE\n", NFAPI_SFNSF2DEC(req->sfn_sf), i); - nfapi_nr_ul_dci_request_pdus_t *ul_dci_req_pdu = &req->ul_dci_pdu_list[i]; + nfapi_nr_ul_dci_request_pdus_t *ul_dci_req_pdu = &req->ul_dci_pdu_list[i]; handle_nfapi_nr_ul_dci_pdu(gNB, req->SFN, req->Slot, ul_dci_req_pdu); } else { @@ -2318,7 +2318,7 @@ void handle_nr_slot_ind(uint16_t sfn, uint16_t slot) { oai_nfapi_nr_slot_indication(ind); //copy data from appropriate p7 slot buffers into channel structures for PHY processing - int slot_ret = nfapi_pnf_p7_slot_ind(p7_config_g, p7_config_g->phy_id, sfn, slot); + nfapi_pnf_p7_slot_ind(p7_config_g, p7_config_g->phy_id, sfn, slot); return; } diff --git a/nfapi/oai_integration/nfapi_pnf.h b/nfapi/oai_integration/nfapi_pnf.h index 463bd42692..b7ebdb36ea 100644 --- a/nfapi/oai_integration/nfapi_pnf.h +++ b/nfapi/oai_integration/nfapi_pnf.h @@ -19,8 +19,7 @@ * contact@openairinterface.org */ -#if !defined(NFAPI_PNF_H__) -#define NFAPI_PNF_H__ + extern nfapi_ue_release_request_body_t release_rntis; int oai_nfapi_rach_ind(nfapi_rach_indication_t *rach_ind); void configure_nfapi_pnf(char *vnf_ip_addr, int vnf_p5_port, char *pnf_ip_addr, int pnf_p7_port, int vnf_p7_port); @@ -28,4 +27,12 @@ void configure_nr_nfapi_pnf(char *vnf_ip_addr, int vnf_p5_port, char *pnf_ip_add void oai_subframe_ind(uint16_t sfn, uint16_t sf); void handle_nr_slot_ind(uint16_t sfn, uint16_t slot); -#endif +uint32_t sfnslot_add_slot(uint16_t sfn, uint16_t slot, int offset); + +int oai_nfapi_nr_slot_indication(nfapi_nr_slot_indication_scf_t *ind); +int oai_nfapi_nr_rx_data_indication(nfapi_nr_rx_data_indication_t *ind); +int oai_nfapi_nr_crc_indication(nfapi_nr_crc_indication_t *ind); +int oai_nfapi_nr_srs_indication(nfapi_nr_srs_indication_t *ind); +int oai_nfapi_nr_uci_indication(nfapi_nr_uci_indication_t *ind); +int oai_nfapi_nr_rach_indication(nfapi_nr_rach_indication_t *ind); + diff --git a/nfapi/oai_integration/nfapi_vnf.c b/nfapi/oai_integration/nfapi_vnf.c index 8c8a19e883..4ac5ed41be 100644 --- a/nfapi/oai_integration/nfapi_vnf.c +++ b/nfapi/oai_integration/nfapi_vnf.c @@ -1014,31 +1014,6 @@ int phy_cqi_indication(struct nfapi_vnf_p7_config *config, nfapi_cqi_indication_ return 1; } -// void add_slot(uint16_t *frameP, uint16_t *slotP, int offset) -// { -// uint16_t num_slots = 20; // set based on numerlogy (fixing for 1) - -// *frameP = (*frameP + ((*slotP + offset) / num_slots))%1024; - -// *slotP = ((*slotP + offset) % num_slots); -// } - -// uint32_t sfnslot_add_slot(uint16_t sfn, uint16_t slot, int offset) -// { -// uint32_t new_sfnslot; -// // uint16_t sfn = NFAPI_SFNSLOT2SFN(sfnslot); -// // uint16_t slot = NFAPI_SFNSLOT2SLOT(sfnslot); - -// //printf("%s() sfn:%u sf:%u\n", __FUNCTION__, sfn, sf); -// add_slot(&sfn, &slot, offset); - -// new_sfnslot = sfn<<6|slot; - -// //printf("%s() sfn:%u sf:%u offset:%d sfnsf:%d(DEC:%d) new:%d(DEC:%d)\n", __FUNCTION__, sfn, sf, offset, sfnsf, NFAPI_SFNSF2DEC(sfnsf), new_sfnsf, NFAPI_SFNSF2DEC(new_sfnsf)); - -// return new_sfnslot; -// } - //NR phy indication int phy_nr_slot_indication(nfapi_nr_slot_indication_scf_t *ind) { @@ -1053,6 +1028,8 @@ int phy_nr_slot_indication(nfapi_nr_slot_indication_scf_t *ind) { gNB->UL_INFO.slot = vnf_slot; pthread_mutex_unlock(&gNB->UL_INFO_mutex); LOG_D(MAC, "VNF SFN/Slot %d.%d \n", gNB->UL_INFO.frame, gNB->UL_INFO.slot); + + return 1; } int phy_nr_crc_indication(nfapi_nr_crc_indication_t *ind) { diff --git a/nfapi/oai_integration/nfapi_vnf.h b/nfapi/oai_integration/nfapi_vnf.h index f4fd6a2bf9..478956f75c 100644 --- a/nfapi/oai_integration/nfapi_vnf.h +++ b/nfapi/oai_integration/nfapi_vnf.h @@ -19,9 +19,9 @@ * contact@openairinterface.org */ -#if !defined(NFAPI_VNF_H__) -#define NFAPI_VNF_H__ void configure_nfapi_vnf(char *vnf_addr, int vnf_p5_port); void configure_nr_nfapi_vnf(char *vnf_addr, int vnf_p5_port); -#endif + +uint32_t sfnslot_add_slot(uint16_t sfn, uint16_t slot, int offset); + 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 9c3dd6fd8f..9d245446c8 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 @@ -1475,7 +1475,7 @@ typedef enum { //section 3.4.7 rx_data_indication -///table 3-61 +//table 3-61 typedef struct { diff --git a/nfapi/open-nFAPI/nfapi/src/nfapi_p7.c b/nfapi/open-nFAPI/nfapi/src/nfapi_p7.c index 16b014dcb5..878666dbcf 100755 --- a/nfapi/open-nFAPI/nfapi/src/nfapi_p7.c +++ b/nfapi/open-nFAPI/nfapi/src/nfapi_p7.c @@ -3636,16 +3636,13 @@ static uint8_t pack_nr_uci_indication_body(void* tlv, uint8_t **ppWritePackedMsg printf("Unhandled NFAPI_NR_UCI_PUSCH_PDU_TYPE \n"); break; - case NFAPI_NR_UCI_FORMAT_0_1_PDU_TYPE: { - nfapi_nr_uci_pucch_pdu_format_0_1_t *uci_pdu = &value->pucch_pdu_format_0_1; + case NFAPI_NR_UCI_FORMAT_0_1_PDU_TYPE: pack_nr_uci_pucch_0_1(&value->pucch_pdu_format_0_1, ppWritePackedMsg, end); break; - } - case NFAPI_NR_UCI_FORMAT_2_3_4_PDU_TYPE: { - nfapi_nr_uci_pucch_pdu_format_2_3_4_t *uci_pdu = &value->pucch_pdu_format_2_3_4; - pack_nr_uci_pucch_2_3_4(uci_pdu, ppWritePackedMsg, end); + + case NFAPI_NR_UCI_FORMAT_2_3_4_PDU_TYPE: + pack_nr_uci_pucch_2_3_4(&value->pucch_pdu_format_2_3_4, ppWritePackedMsg, end); break; - } } return 1; @@ -6556,7 +6553,7 @@ return 1; static uint8_t unpack_nr_uci_pucch_0_1(nfapi_nr_uci_pucch_pdu_format_0_1_t* tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { nfapi_nr_uci_pucch_pdu_format_0_1_t* value = (nfapi_nr_uci_pucch_pdu_format_0_1_t*)tlv; - uint8_t *ptr = *ppReadPackedMsg; + // uint8_t *ptr = *ppReadPackedMsg; // printf("\n Read P7 message uci_0_1 indication unpack: "); // while(ptr < end){ // printf(" %d ", *ptr); diff --git a/nfapi/open-nFAPI/pnf/inc/pnf_p7.h b/nfapi/open-nFAPI/pnf/inc/pnf_p7.h index 1e2e2fa21d..82533d0b97 100644 --- a/nfapi/open-nFAPI/pnf/inc/pnf_p7.h +++ b/nfapi/open-nFAPI/pnf/inc/pnf_p7.h @@ -158,5 +158,7 @@ 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_p7_message_header_t* header, uint32_t msg_len); + #endif /* _PNF_P7_H_ */ diff --git a/nfapi/open-nFAPI/pnf/src/pnf_p7.c b/nfapi/open-nFAPI/pnf/src/pnf_p7.c index 5960f4af8e..092b967189 100644 --- a/nfapi/open-nFAPI/pnf/src/pnf_p7.c +++ b/nfapi/open-nFAPI/pnf/src/pnf_p7.c @@ -940,7 +940,7 @@ int pnf_p7_slot_ind(pnf_p7_t* pnf_p7, uint16_t phy_id, uint16_t sfn, uint16_t sl //We align the pnf_p7 sfn/slot with tx sfn/slot, and vnf is synced with pnf_p7 sfn/slot. This is so that the scheduler runs slot_ahead from rx thread. - pnf_p7->sfn = sfn_tx; //gokul + pnf_p7->sfn = sfn_tx; pnf_p7->slot = slot_tx; uint32_t rx_slot_dec = NFAPI_SFNSLOT2DEC(sfn, slot); @@ -1142,7 +1142,7 @@ int pnf_p7_slot_ind(pnf_p7_t* pnf_p7, uint16_t phy_id, uint16_t sfn, uint16_t sl else { pnf_p7->timing_info_ms_counter++; - } //gokul + } } @@ -1772,7 +1772,7 @@ void pnf_handle_ul_tti_request(void* pRecvMsg, int recvMsgLen, pnf_p7_t* pnf_p7) struct timespec t; clock_gettime(CLOCK_MONOTONIC, &t); - //NFAPI_TRACE(NFAPI_TRACE_INFO,"%s() %ld.%09ld POPULATE UL_TTI_REQ current tx sfn/slot:%d.%d p7 msg sfn/slot: %d.%d buffer_index:%d\n", __FUNCTION__, t.tv_sec, t.tv_nsec, pnf_p7->sfn,pnf_p7->slot, req->SFN, req->Slot, buffer_index); + NFAPI_TRACE(NFAPI_TRACE_INFO,"%s() %ld.%09ld POPULATE UL_TTI_REQ current tx sfn/slot:%d.%d p7 msg sfn/slot: %d.%d buffer_index:%d\n", __FUNCTION__, t.tv_sec, t.tv_nsec, pnf_p7->sfn,pnf_p7->slot, req->SFN, req->Slot, buffer_index); if(pnf_p7->slot_buffer[buffer_index].ul_tti_req != 0) { diff --git a/nfapi/open-nFAPI/pnf/src/pnf_p7_interface.c b/nfapi/open-nFAPI/pnf/src/pnf_p7_interface.c index a5cd9bcd16..0db1feb398 100644 --- a/nfapi/open-nFAPI/pnf/src/pnf_p7_interface.c +++ b/nfapi/open-nFAPI/pnf/src/pnf_p7_interface.c @@ -175,7 +175,17 @@ int nfapi_pnf_p7_rach_ind(nfapi_pnf_p7_config_t* config, nfapi_rach_indication_t pnf_p7_t* _this = (pnf_p7_t*)(config); return pnf_p7_pack_and_send_p7_message(_this, (nfapi_p7_message_header_t*)ind, sizeof(nfapi_rach_indication_t)); } +int nfapi_pnf_p7_srs_ind(nfapi_pnf_p7_config_t* config, nfapi_srs_indication_t* ind) +{ + 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); + return pnf_p7_pack_and_send_p7_message(_this, (nfapi_p7_message_header_t*)ind, sizeof(nfapi_srs_indication_t)); +} int nfapi_pnf_p7_sr_ind(nfapi_pnf_p7_config_t* config, nfapi_sr_indication_t* ind) { if(config == NULL || ind == NULL) diff --git a/nfapi/open-nFAPI/vnf/src/vnf_p7.c b/nfapi/open-nFAPI/vnf/src/vnf_p7.c index 4b68f016a8..2c98cb538b 100644 --- a/nfapi/open-nFAPI/vnf/src/vnf_p7.c +++ b/nfapi/open-nFAPI/vnf/src/vnf_p7.c @@ -1473,7 +1473,7 @@ void vnf_handle_nr_slot_indication(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vnf { if(vnf_p7->_public.nr_slot_indication) { - (vnf_p7->_public.nr_slot_indication)(&ind); //gokul + (vnf_p7->_public.nr_slot_indication)(&ind); } } @@ -1982,7 +1982,7 @@ void vnf_nr_handle_ul_node_sync(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vnf_p7 phy->zero_count, phy->in_sync ? "IN_SYNC" : "OUT_OF_SYNC");*/ - phy->sfn = new_sfn; + phy->sfn = new_sfn; phy->slot = new_slot; } } @@ -1998,7 +1998,7 @@ void vnf_nr_handle_ul_node_sync(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vnf_p7 phy->previous_t1 = ind.t1; phy->previous_t2 = ind.t2; } - } +} void vnf_handle_timing_info(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vnf_p7) { @@ -2034,9 +2034,7 @@ void vnf_handle_timing_info(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vnf_p7) void vnf_nr_handle_timing_info(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vnf_p7) -{ - uint8_t uplink_slots[6] = {7,8,9,17,18,19}; - uint8_t is_uplink_slot = 0; +{ if (pRecvMsg == NULL || vnf_p7 == NULL) { NFAPI_TRACE(NFAPI_TRACE_ERROR, "vnf_handle_timing_info: NULL parameters\n"); @@ -2055,20 +2053,16 @@ void vnf_nr_handle_timing_info(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vnf_p7) //int16_t vnf_pnf_sfnsf_delta = NFAPI_SFNSF2DEC(vnf_p7->p7_connections[0].sfn_sf) - NFAPI_SFNSF2DEC(ind.last_sfn_sf); int16_t vnf_pnf_sfnslot_delta = NFAPI_SFNSLOT2DEC(vnf_p7->p7_connections[0].sfn,vnf_p7->p7_connections[0].slot) - NFAPI_SFNSLOT2DEC(ind.last_sfn,ind.last_slot); //NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() PNF:SFN/SF:%d VNF:SFN/SF:%d deltaSFNSF:%d\n", __FUNCTION__, NFAPI_SFNSF2DEC(ind.last_sfn_sf), NFAPI_SFNSF2DEC(vnf_p7->p7_connections[0].sfn_sf), vnf_pnf_sfnsf_delta); + // Panos: Careful here!!! Modification of the original nfapi-code //if (vnf_pnf_sfnsf_delta>1 || vnf_pnf_sfnsf_delta < -1) //printf("VNF-PNF delta - %d", vnf_pnf_sfnslot_delta); - for (int i = 0; i < 6; i++){ - if (vnf_p7->p7_connections[0].slot == uplink_slots[i]) - is_uplink_slot = 1; - } - if ((vnf_pnf_sfnslot_delta>0 || vnf_pnf_sfnslot_delta < 0) && is_uplink_slot == 0) + if (vnf_pnf_sfnslot_delta>0 || vnf_pnf_sfnslot_delta < 0) { NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() LARGE SFN/SF DELTA between PNF and VNF delta:%d VNF:%d PNF:%d\n\n\n\n\n\n\n\n\n", __FUNCTION__, vnf_pnf_sfnslot_delta,NFAPI_SFNSLOT2DEC(vnf_p7->p7_connections[0].sfn,vnf_p7->p7_connections[0].slot),NFAPI_SFNSLOT2DEC(ind.last_sfn,ind.last_slot)) ; // Panos: Careful here!!! Modification of the original nfapi-code - vnf_p7->p7_connections[0].sfn = ind.last_sfn; - vnf_p7->p7_connections[0].slot = ind.last_slot; - //printf("VNF SFN/slot modified"); + // vnf_p7->p7_connections[0].sfn = ind.last_sfn; + // vnf_p7->p7_connections[0].slot = ind.last_slot; } } } diff --git a/nfapi/open-nFAPI/vnf/src/vnf_p7_interface.c b/nfapi/open-nFAPI/vnf/src/vnf_p7_interface.c index 5c0ff7b068..2137965a7e 100644 --- a/nfapi/open-nFAPI/vnf/src/vnf_p7_interface.c +++ b/nfapi/open-nFAPI/vnf/src/vnf_p7_interface.c @@ -99,8 +99,7 @@ struct timespec timespec_sub(struct timespec lhs, struct timespec rhs) int nfapi_nr_vnf_p7_start(nfapi_vnf_p7_config_t* config) { struct PHY_VARS_gNB_s *gNB = RC.gNB[0]; - uint8_t temp_slot; - uint16_t vnf_frame; uint8_t vnf_slot; + uint8_t prev_slot = 0; if(config == 0) return -1; @@ -174,7 +173,6 @@ int nfapi_nr_vnf_p7_start(nfapi_vnf_p7_config_t* config) struct timespec slot_start; // clock_gettime(CLOCK_MONOTONIC, &sf_start); clock_gettime(CLOCK_MONOTONIC, &slot_start); - long millisecond = slot_start.tv_nsec / 1e6; //Check if we have to change //long millisecond = slot_start.tv_nsec / 0.5e6; // sf_start = timespec_add(sf_start, sf_duration); slot_start = timespec_add(slot_start, slot_duration); @@ -216,7 +214,7 @@ int nfapi_nr_vnf_p7_start(nfapi_vnf_p7_config_t* config) pselect_timeout = timespec_sub(slot_start, pselect_start); } - if(setup_time > 10 && temp_slot != gNB->UL_INFO.slot){ + if(setup_time > 10 && prev_slot != gNB->UL_INFO.slot){ //Call the scheduler pthread_mutex_lock(&gNB->UL_INFO_mutex); @@ -224,7 +222,7 @@ int nfapi_nr_vnf_p7_start(nfapi_vnf_p7_config_t* config) gNB->UL_INFO.CC_id = gNB->CC_id; gNB->if_inst->NR_UL_indication(&gNB->UL_INFO); pthread_mutex_unlock(&gNB->UL_INFO_mutex); - temp_slot = gNB->UL_INFO.slot; + prev_slot = gNB->UL_INFO.slot; } selectRetval = pselect(maxSock+1, &rfds, NULL, NULL, &pselect_timeout, NULL); @@ -266,8 +264,6 @@ int nfapi_nr_vnf_p7_start(nfapi_vnf_p7_config_t* config) curr->slot++; } //printf("Frame = %d, slot = %d in VNF main loop. \n",curr->sfn,curr->slot); - vnf_frame = curr->sfn; - vnf_slot = curr->slot; //vnf_nr_sync(vnf_p7, curr); diff --git a/openair1/PHY/LTE_UE_TRANSPORT/dlsch_decoding.c b/openair1/PHY/LTE_UE_TRANSPORT/dlsch_decoding.c index a82356f16a..39900113b7 100644 --- a/openair1/PHY/LTE_UE_TRANSPORT/dlsch_decoding.c +++ b/openair1/PHY/LTE_UE_TRANSPORT/dlsch_decoding.c @@ -780,11 +780,11 @@ int dlsch_encoding_SIC(PHY_VARS_UE *ue, for (r=0; rharq_processes[harq_pid]->C; r++) { #ifdef DEBUG_DLSCH_CODING - // printf("Rate Matching, Code segment %u (coded bits (G) %u,unpunctured/repeated bits per code segment %u,mod_order %d, nb_rb %d)...\n", - // r, - // G, - // Kr*3, - // mod_order,nb_rb); + printf("Rate Matching, Code segment %u (coded bits (G) %u,unpunctured/repeated bits per code segment %u,mod_order %d, nb_rb %d)...\n", + r, + G, + Kr*3, + mod_order,nb_rb); #endif start_meas(rm_stats); #ifdef DEBUG_DLSCH_CODING diff --git a/openair1/PHY/NR_TRANSPORT/nr_dci_tools.c b/openair1/PHY/NR_TRANSPORT/nr_dci_tools.c index c04bb308e2..c562dfaa41 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_dci_tools.c +++ b/openair1/PHY/NR_TRANSPORT/nr_dci_tools.c @@ -211,8 +211,8 @@ int16_t find_nr_pdcch(int frame,int slot, PHY_VARS_gNB *gNB,find_type_t type) { for (i=0; ipdcch_pdu[i].frame,gNB->pdcch_pdu[i].slot,first_free_index); if ((gNB->pdcch_pdu[i].frame == frame) && - (gNB->pdcch_pdu[i].slot==slot)) {return i;} - else if ( gNB->pdcch_pdu[i].frame==-1 && first_free_index==-1) {first_free_index=i;} + (gNB->pdcch_pdu[i].slot==slot)) return i; + else if ( gNB->pdcch_pdu[i].frame==-1 && first_free_index==-1) first_free_index=i; } if (type == SEARCH_EXIST) return -1; @@ -227,7 +227,7 @@ void nr_fill_dci(PHY_VARS_gNB *gNB, nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu_rel15 = &pdcch_pdu->pdcch_pdu_rel15; NR_gNB_DLSCH_t *dlsch; - //printf("find pdcch from nr_fill_dci \n"); + int pdcch_id = find_nr_pdcch(frame,slot,gNB,SEARCH_EXIST_OR_FREE); AssertFatal(pdcch_id>=0 && pdcch_idpdcch_pdu[pdcch_id].pdcch_pdu,(void*)pdcch_pdu,sizeof(*pdcch_pdu)); @@ -285,7 +285,7 @@ void nr_fill_ul_dci(PHY_VARS_gNB *gNB, nfapi_nr_ul_dci_request_pdus_t *pdcch_pdu) { nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu_rel15 = &pdcch_pdu->pdcch_pdu.pdcch_pdu_rel15; - //printf("find ul dci from fill_ul_dci \n"); + int pdcch_id = find_nr_ul_dci(frame,slot,gNB,SEARCH_EXIST_OR_FREE); AssertFatal(pdcch_id>=0 && pdcch_idul_pdcch_pdu[pdcch_id].pdcch_pdu,(void*)pdcch_pdu,sizeof(*pdcch_pdu)); diff --git a/openair1/PHY/NR_TRANSPORT/nr_dlsch_coding.c b/openair1/PHY/NR_TRANSPORT/nr_dlsch_coding.c index e01adc1bf2..2ae2549df3 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_dlsch_coding.c +++ b/openair1/PHY/NR_TRANSPORT/nr_dlsch_coding.c @@ -292,7 +292,7 @@ int nr_dlsch_encoding(PHY_VARS_gNB *gNB, } G = nr_get_G(nb_rb, nb_symb_sch, nb_re_dmrs, length_dmrs,mod_order,rel15->nrOfLayers); - LOG_I(NR_PHY,"dlsch coding A %d G %d (nb_rb %d, nb_symb_sch %d, nb_re_dmrs %d, length_dmrs %d, mod_order %d)\n", A,G, nb_rb,nb_symb_sch,nb_re_dmrs,length_dmrs,mod_order); + LOG_D(NR_PHY,"dlsch coding A %d G %d (nb_rb %d, nb_symb_sch %d, nb_re_dmrs %d, length_dmrs %d, mod_order %d)\n", A,G, nb_rb,nb_symb_sch,nb_re_dmrs,length_dmrs,mod_order); if (A > 3824) { // Add 24-bit crc (polynomial A) to payload diff --git a/openair1/PHY/NR_TRANSPORT/nr_ulsch_decoding.c b/openair1/PHY/NR_TRANSPORT/nr_ulsch_decoding.c index 9492f3a402..3aad4980bc 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_ulsch_decoding.c +++ b/openair1/PHY/NR_TRANSPORT/nr_ulsch_decoding.c @@ -431,7 +431,7 @@ void nr_processULSegment(void* arg) { if (check_crc((uint8_t*)llrProcBuf,length_dec,ulsch_harq->F,crc_type)) { #ifdef PRINT_CRC_CHECK - LOG_D(PHY, "Segment %d CRC OK\n",r); + LOG_I(PHY, "Segment %d CRC OK\n",r); #endif rdata->decodeIterations = no_iteration_ldpc; } else { diff --git a/openair1/PHY/NR_TRANSPORT/pucch_rx.c b/openair1/PHY/NR_TRANSPORT/pucch_rx.c index 70a0d419c9..0bace9dbed 100644 --- a/openair1/PHY/NR_TRANSPORT/pucch_rx.c +++ b/openair1/PHY/NR_TRANSPORT/pucch_rx.c @@ -88,8 +88,6 @@ void nr_fill_pucch(PHY_VARS_gNB *gNB, int frame, int slot, nfapi_nr_pucch_pdu_t *pucch_pdu) { - // if (NFAPI_MODE == NFAPI_MODE_PNF) - // gNB->pucch[0]->active = 0; int id = nr_find_pucch(pucch_pdu->rnti,frame,slot,gNB); AssertFatal( (id>=0) && (idnumDlDci:%d\n",frame,slot, pdcch_pdu->pdcch_pdu_rel15.numDlDci); + LOG_D(PHY,"Frame %d, Slot %d: DCI processing - proc:slot_tx:%d pdcch_pdu_rel15->numDlDci:%d\n",frame,slot, slot, pdcch_pdu->pdcch_pdu_rel15.numDlDci); // copy dci configuration into gNB structure // gNB->pdcch_pdu = pdcch_pdu; @@ -118,7 +118,7 @@ void handle_nfapi_nr_ul_dci_pdu(PHY_VARS_gNB *gNB, int frame, int slot, nfapi_nr_ul_dci_request_pdus_t *ul_dci_request_pdu) { - LOG_D(PHY,"Frame %d, Slot %d: UL DCI processing - pdcch_pdu_rel15->numDlDci:%d\n",frame,slot, ul_dci_request_pdu->pdcch_pdu.pdcch_pdu_rel15.numDlDci); + LOG_D(PHY,"Frame %d, Slot %d: UL DCI processing - proc:slot_tx:%d pdcch_pdu_rel15->numDlDci:%d\n",frame,slot, slot, ul_dci_request_pdu->pdcch_pdu.pdcch_pdu_rel15.numDlDci); // copy dci configuration into gNB structure // gNB->ul_dci_pdu = ul_dci_request_pdu; @@ -203,39 +203,35 @@ void nr_schedule_response(NR_Sched_Rsp_t *Sched_INFO){ LOG_D(PHY,"NFAPI: dl_pdu %d : type %d\n",i,dl_tti_pdu->PDUType); switch (dl_tti_pdu->PDUType) { case NFAPI_NR_DL_TTI_SSB_PDU_TYPE: - - handle_nr_nfapi_ssb_pdu(gNB,frame,slot, + handle_nr_nfapi_ssb_pdu(gNB,frame,slot, dl_tti_pdu); - - break; + break; case NFAPI_NR_DL_TTI_PDCCH_PDU_TYPE: AssertFatal(pdcch_received == 0, "pdcch_received is not 0, we can only handle one PDCCH PDU per slot\n"); - handle_nfapi_nr_pdcch_pdu(gNB, frame, slot, &dl_tti_pdu->pdcch_pdu); pdcch_received = 1; - - break; + break; case NFAPI_NR_DL_TTI_CSI_RS_PDU_TYPE: LOG_D(PHY,"frame %d, slot %d, Got NFAPI_NR_DL_TTI_CSI_RS_PDU_TYPE for %d.%d\n",frame,slot,DL_req->SFN,DL_req->Slot); handle_nfapi_nr_csirs_pdu(gNB, frame, slot, &dl_tti_pdu->csi_rs_pdu); - break; + break; + case NFAPI_NR_DL_TTI_PDSCH_PDU_TYPE: - - LOG_D(PHY,"frame %d, slot %d, Got NFAPI_NR_DL_TTI_PDSCH_PDU_TYPE for %d.%d\n",frame,slot,DL_req->SFN,DL_req->Slot); - nfapi_nr_dl_tti_pdsch_pdu_rel15_t *pdsch_pdu_rel15 = &dl_tti_pdu->pdsch_pdu.pdsch_pdu_rel15; - uint16_t pduIndex = pdsch_pdu_rel15->pduIndex; - AssertFatal(TX_req->pdu_list[pduIndex].num_TLV == 1, "TX_req->pdu_list[%d].num_TLV %d != 1\n", - pduIndex,TX_req->pdu_list[pduIndex].num_TLV); - uint8_t *sdu = (uint8_t *)TX_req->pdu_list[pduIndex].TLVs[0].value.direct; - if(NFAPI_MODE != NFAPI_MODE_VNF) - handle_nr_nfapi_pdsch_pdu(gNB,frame,slot,&dl_tti_pdu->pdsch_pdu, sdu); - + LOG_D(PHY,"frame %d, slot %d, Got NFAPI_NR_DL_TTI_PDSCH_PDU_TYPE for %d.%d\n",frame,slot,DL_req->SFN,DL_req->Slot); + nfapi_nr_dl_tti_pdsch_pdu_rel15_t *pdsch_pdu_rel15 = &dl_tti_pdu->pdsch_pdu.pdsch_pdu_rel15; + uint16_t pduIndex = pdsch_pdu_rel15->pduIndex; + AssertFatal(TX_req->pdu_list[pduIndex].num_TLV == 1, "TX_req->pdu_list[%d].num_TLV %d != 1\n", + pduIndex,TX_req->pdu_list[pduIndex].num_TLV); + uint8_t *sdu = (uint8_t *)TX_req->pdu_list[pduIndex].TLVs[0].value.direct; + if(NFAPI_MODE != NFAPI_MODE_VNF) + handle_nr_nfapi_pdsch_pdu(gNB,frame,slot,&dl_tti_pdu->pdsch_pdu, sdu); + break; } } diff --git a/openair1/SCHED_NR/phy_procedures_nr_gNB.c b/openair1/SCHED_NR/phy_procedures_nr_gNB.c index 9f40821d04..172fdd354b 100644 --- a/openair1/SCHED_NR/phy_procedures_nr_gNB.c +++ b/openair1/SCHED_NR/phy_procedures_nr_gNB.c @@ -148,15 +148,15 @@ void phy_procedures_gNB_TX(PHY_VARS_gNB *gNB, VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_gNB_COMMON_TX,1); - for (int i=0; iLmax; i++) { - if (gNB->ssb[i].active) { - nr_common_signal_procedures(gNB,frame,slot,gNB->ssb[i].ssb_pdu); - gNB->ssb[i].active = false; - } + for (int i=0; iLmax; i++) { + if (gNB->ssb[i].active) { + nr_common_signal_procedures(gNB,frame,slot,gNB->ssb[i].ssb_pdu); + gNB->ssb[i].active = false; } + } VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_gNB_COMMON_TX,0); - //printf("find pdcch from TX func \n"); + int pdcch_pdu_id=find_nr_pdcch(frame,slot,gNB,SEARCH_EXIST); int ul_pdcch_pdu_id=find_nr_ul_dci(frame,slot,gNB,SEARCH_EXIST); @@ -568,7 +568,6 @@ int phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx) { for (int i=0;ipucch[i]; if (pucch) { - LOG_D(PHY, "SFN/slot = %d.%d, pucch[%d]->active = %d \n", frame_rx, slot_rx, i,pucch->active); if ((pucch->active == 1) && (pucch->frame == frame_rx) && (pucch->slot == slot_rx) ) { @@ -598,9 +597,7 @@ int phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx) { pucch_pdu); gNB->UL_INFO.uci_ind.num_ucis += 1; - //printf("SFN/slot %d.%d pucch active of index %d set to 0. \n", frame_rx, slot_rx, i); pucch->active = 0; - //printf("Decode pucch num ucis +=1 in %d.%d \n",frame_rx,slot_rx); break; case 2: num_ucis = gNB->UL_INFO.uci_ind.num_ucis; @@ -617,7 +614,6 @@ int phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx) { pucch_pdu); gNB->UL_INFO.uci_ind.num_ucis += 1; - //printf("SFN/slot %d.%d pucch active of index %d set to 0. \n", frame_rx, slot_rx, i); pucch->active = 0; break; default: diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c index 5e474f1bd2..5bb1ccd1e4 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c @@ -60,7 +60,7 @@ uint16_t nr_pdcch_order_table[6] = { 31, 31, 511, 2047, 2047, 8191 }; -uint8_t first_sched_entry = 1; +uint8_t vnf_first_sched_entry = 1; void clear_mac_stats(gNB_MAC_INST *gNB) { memset((void*)gNB->UE_info.mac_stats,0,MAX_MOBILES_PER_GNB*sizeof(NR_mac_stats_t)); @@ -400,18 +400,19 @@ void gNB_dlsch_ulsch_scheduler(module_id_t module_idP, clear_nr_nfapi_information(RC.nrmac[module_idP], CC_id, frame, slot); - //first entry + /*VNF first entry into scheduler. Since frame numbers for future_ul_tti_req of some future slots + will not be set before we encounter them, set them here */ + if (NFAPI_MODE == NFAPI_MODE_VNF){ - if(first_sched_entry == 1) + if(vnf_first_sched_entry == 1) { - printf("First sched entry at slot %d \n", slot); for (int i = 0; iUL_tti_req_ahead[CC_id][i].SFN = (frame + 1) % 1024; else gNB->UL_tti_req_ahead[CC_id][i].SFN = frame; } - first_sched_entry = 0; + vnf_first_sched_entry = 0; } } } @@ -442,7 +443,7 @@ void gNB_dlsch_ulsch_scheduler(module_id_t module_idP, schedule_nr_prach(module_idP, f, s); } - // This schedule SR + // This schedule SR nr_sr_reporting(module_idP, frame, slot); // Schedule CSI-RS transmission @@ -459,7 +460,6 @@ void gNB_dlsch_ulsch_scheduler(module_id_t module_idP, } // This schedules the DCI for Uplink and subsequently PUSCH - nr_schedule_ulsch(module_idP, frame, slot); // This schedules the DCI for Downlink and PDSCH diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c index 139b22788d..79d8ce64e6 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c @@ -1036,7 +1036,6 @@ static NR_UE_harq_t *find_harq(module_id_t mod_id, frame_t frame, sub_frame_t sl harq->feedback_slot, frame, slot); - //printf("handling harq \n"); remove_front_nr_list(&sched_ctrl->feedback_dl_harq); handle_dl_harq(mod_id, UE_id, pid, 0); pid = sched_ctrl->feedback_dl_harq.head; @@ -1076,14 +1075,12 @@ void handle_nr_uci_pucch_0_1(module_id_t mod_id, for (int harq_bit = 0; harq_bit < uci_01->harq->num_harq; harq_bit++) { const uint8_t harq_value = uci_01->harq->harq_list[harq_bit].harq_value; const uint8_t harq_confidence = uci_01->harq->harq_confidence_level; - //printf("handle uci 0_1 find harq SFN/slot %d.%d \n",frame,slot); NR_UE_harq_t *harq = find_harq(mod_id, frame, slot, UE_id); if (!harq) break; DevAssert(harq->is_waiting); const int8_t pid = sched_ctrl->feedback_dl_harq.head; remove_front_nr_list(&sched_ctrl->feedback_dl_harq); - //printf("handling harq \n"); handle_dl_harq(mod_id, UE_id, pid, harq_value == 1 && harq_confidence == 0); } } @@ -1152,6 +1149,7 @@ void handle_nr_uci_pucch_2_3_4(module_id_t mod_id, } } + // function to update pucch scheduling parameters in UE list when a USS DL is scheduled // this function returns an index to NR_sched_pucch structure // currently this structure contains PUCCH0 at index 0 and PUCCH2 at index 1 @@ -1193,7 +1191,6 @@ int nr_acknack_scheduling(int mod_id, __func__, pucch->csi_bits); /* if the currently allocated PUCCH of this UE is full, allocate it */ - if (pucch->dai_c == 2) { /* advance the UL slot information in PUCCH by one so we won't schedule in * the same slot again */ @@ -1223,7 +1220,6 @@ int nr_acknack_scheduling(int mod_id, /* if the UE's next PUCCH occasion is after the possible UL slots (within the * same frame) or wrapped around to the next frame, then we assume there is * no possible PUCCH allocation anymore */ - if ((pucch->frame == frame && (pucch->ul_slot >= first_ul_slot_tdd + nr_ulmix_slots)) || (pucch->frame == frame + 1)) @@ -1235,10 +1231,8 @@ int nr_acknack_scheduling(int mod_id, get_pdsch_to_harq_feedback(mod_id, UE_id, ss_type, pdsch_to_harq_feedback); /* there is a HARQ. Check whether we can use it for this ACKNACK */ - if (pucch->dai_c > 0) { /* this UE already has a PUCCH occasion */ - LOG_I(MAC,"pucch->frame = %d,frame=%d \n",pucch->frame,frame); DevAssert(pucch->frame == frame); // Find the right timing_indicator value. diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c index 9aa757d9d4..fbd8a4b5ca 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c @@ -32,7 +32,6 @@ #include "LAYER2/NR_MAC_gNB/mac_proto.h" #include "executables/softmodem-common.h" #include "common/utils/nr/nr_common.h" -#include "nfapi/oai_integration/vendor_ext.h" #include @@ -1346,11 +1345,9 @@ void nr_schedule_ulsch(module_id_t module_id, frame_t frame, sub_frame_t slot) 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; - //printf("SFN/slot %d.%d harq id = %d \n", frame, slot, harq_id); AssertFatal(harq_id >= 0, "no free HARQ process available for UE %d\n", UE_id); @@ -1358,8 +1355,8 @@ void nr_schedule_ulsch(module_id_t module_id, frame_t frame, sub_frame_t slot) 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 */ + * 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 @@ -1370,7 +1367,6 @@ void nr_schedule_ulsch(module_id_t module_id, frame_t frame, sub_frame_t slot) add_tail_nr_list(&sched_ctrl->feedback_ul_harq, harq_id); cur_harq->feedback_slot = sched_pusch->slot; cur_harq->is_waiting = true; - int rnti_types[2] = { NR_RNTI_C, 0 }; diff --git a/openair2/NR_PHY_INTERFACE/NR_IF_Module.c b/openair2/NR_PHY_INTERFACE/NR_IF_Module.c index db3251ae99..16bffb14f4 100644 --- a/openair2/NR_PHY_INTERFACE/NR_IF_Module.c +++ b/openair2/NR_PHY_INTERFACE/NR_IF_Module.c @@ -48,6 +48,12 @@ extern int oai_nfapi_crc_indication(nfapi_crc_indication_t *crc_ind); extern int oai_nfapi_cqi_indication(nfapi_cqi_indication_t *cqi_ind); extern int oai_nfapi_sr_indication(nfapi_sr_indication_t *ind); extern int oai_nfapi_rx_ind(nfapi_rx_indication_t *ind); +int oai_nfapi_nr_slot_indication(nfapi_nr_slot_indication_scf_t *ind); +int oai_nfapi_nr_rx_data_indication(nfapi_nr_rx_data_indication_t *ind); +int oai_nfapi_nr_crc_indication(nfapi_nr_crc_indication_t *ind); +int oai_nfapi_nr_srs_indication(nfapi_nr_srs_indication_t *ind); +int oai_nfapi_nr_uci_indication(nfapi_nr_uci_indication_t *ind); +int oai_nfapi_nr_rach_indication(nfapi_nr_rach_indication_t *ind); extern uint8_t nfapi_mode; extern uint16_t sf_ahead; extern uint16_t sl_ahead; From 902f3a83d4544a9a168f57ad09e2d57c001de538 Mon Sep 17 00:00:00 2001 From: Raphael Defosseux Date: Mon, 9 Aug 2021 17:02:32 +0200 Subject: [PATCH 83/91] fix(ci): when using modules, no more adb-connected UE required Signed-off-by: Raphael Defosseux --- ci-scripts/html.py | 5 ++++- ci-scripts/main.py | 8 +++++--- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/ci-scripts/html.py b/ci-scripts/html.py index 9eadf30279..40bb3f9b9f 100644 --- a/ci-scripts/html.py +++ b/ci-scripts/html.py @@ -182,9 +182,12 @@ class HTMLManagement(): self.htmlFile.write(' \n') self.htmlFile.write(' \n') - if (ADBIPAddress != 'none'): + if (ADBIPAddress != 'none') and (ADBIPAddress != 'modules'): self.htmlFile.write('

' + str(self.htmlNb_Smartphones) + ' UE(s) is(are) connected to ADB bench server

\n') self.htmlFile.write('

' + str(self.htmlNb_CATM_Modules) + ' CAT-M UE(s) is(are) connected to bench server

\n') + elif (ADBIPAddress != 'modules'): + self.htmlUEConnected = 1 + self.htmlFile.write('

1 commercial module is connected to CI bench

\n') else: self.htmlUEConnected = 1 self.htmlFile.write('

1 OAI UE(s) is(are) connected to CI bench

\n') diff --git a/ci-scripts/main.py b/ci-scripts/main.py index f6177cde49..8a76d8dbce 100644 --- a/ci-scripts/main.py +++ b/ci-scripts/main.py @@ -573,7 +573,7 @@ elif re.match('^InitiateHtml$', mode, re.IGNORECASE): if foundCount != HTML.nbTestXMLfiles: HTML.nbTestXMLfiles=foundCount - if (CiTestObj.ADBIPAddress != 'none'): + if (CiTestObj.ADBIPAddress != 'none') and (CiTestObj.ADBIPAddress != 'modules'): terminate_ue_flag = False CiTestObj.GetAllUEDevices(terminate_ue_flag) CiTestObj.GetAllCatMDevices(terminate_ue_flag) @@ -677,10 +677,12 @@ elif re.match('^TesteNB$', mode, re.IGNORECASE) or re.match('^TestUE$', mode, re signal.signal(signal.SIGUSR1, receive_signal) - if (CiTestObj.ADBIPAddress != 'none'): + if (CiTestObj.ADBIPAddress != 'none') and (CiTestObj.ADBIPAddress != 'modules'): terminate_ue_flag = False CiTestObj.GetAllUEDevices(terminate_ue_flag) CiTestObj.GetAllCatMDevices(terminate_ue_flag) + elif (CiTestObj.ADBIPAddress == 'modules'): + CiTestObj.UEDevices.append('COTS-Module') else: CiTestObj.UEDevices.append('OAI-UE') HTML.SethtmlUEConnected(len(CiTestObj.UEDevices) + len(CiTestObj.CatMDevices)) @@ -714,7 +716,7 @@ elif re.match('^TesteNB$', mode, re.IGNORECASE) or re.match('^TestUE$', mode, re CiTestObj.ShowTestID() GetParametersFromXML(action) if action == 'Initialize_UE' or action == 'Attach_UE' or action == 'Detach_UE' or action == 'Ping' or action == 'Iperf' or action == 'Reboot_UE' or action == 'DataDisable_UE' or action == 'DataEnable_UE' or action == 'CheckStatusUE': - if (CiTestObj.ADBIPAddress != 'none'): + if (CiTestObj.ADBIPAddress != 'none') and (CiTestObj.ADBIPAddress != 'modules'): #in these cases, having no devices is critical, GetAllUEDevices function has to manage it as a critical error, reason why terminate_ue_flag is set to True terminate_ue_flag = True # Now we stop properly the test-suite --> clean reporting From b89d67d9db616cd33c6a0b403376f63361083e40 Mon Sep 17 00:00:00 2001 From: Laurent THOMAS Date: Mon, 9 Aug 2021 17:28:28 +0200 Subject: [PATCH 84/91] fix memory error detected by sanitize-addr --- openair3/NGAP/ngap_gNB_nas_procedures.c | 46 +++++++++---------------- 1 file changed, 17 insertions(+), 29 deletions(-) diff --git a/openair3/NGAP/ngap_gNB_nas_procedures.c b/openair3/NGAP/ngap_gNB_nas_procedures.c index 8efab98dfa..3d71464bbf 100644 --- a/openair3/NGAP/ngap_gNB_nas_procedures.c +++ b/openair3/NGAP/ngap_gNB_nas_procedures.c @@ -766,7 +766,6 @@ int ngap_gNB_initial_ctxt_resp( ASN_SEQUENCE_ADD(&pdusessionTransfer_p->dLQosFlowPerTNLInformation.associatedQosFlowList.list, ass_qos_item_p); } - memset(&res, 0, sizeof(res)); //res = asn_encode_to_new_buffer(NULL, ATS_ALIGNED_CANONICAL_PER, &asn_DEF_NGAP_PDUSessionResourceSetupResponseTransfer, pdusessionTransfer_p); //item->pDUSessionResourceSetupResponseTransfer.buf = res.buffer; //item->pDUSessionResourceSetupResponseTransfer.size = res.result.encoded; @@ -799,16 +798,14 @@ int ngap_gNB_initial_ctxt_resp( ie->value.present = NGAP_InitialContextSetupResponseIEs__value_PR_PDUSessionResourceFailedToSetupListCxtRes; for (i = 0; i < initial_ctxt_resp_p->nb_of_pdusessions_failed; i++) { - NGAP_PDUSessionResourceFailedToSetupItemCxtRes_t *item; - NGAP_PDUSessionResourceSetupUnsuccessfulTransfer_t *pdusessionUnTransfer_p = NULL; + NGAP_PDUSessionResourceFailedToSetupItemCxtRes_t *item= calloc(1, sizeof *item); + NGAP_PDUSessionResourceSetupUnsuccessfulTransfer_t *pdusessionUnTransfer_p = calloc(1, sizeof *pdusessionUnTransfer_p); - /* mandatory */ - item = (NGAP_PDUSessionResourceFailedToSetupItemCxtRes_t *)calloc(1, sizeof(NGAP_PDUSessionResourceFailedToSetupItemCxtRes_t)); /* pDUSessionID */ item->pDUSessionID = initial_ctxt_resp_p->pdusessions_failed[i].pdusession_id; /* cause */ - pdusessionUnTransfer_p = (NGAP_PDUSessionResourceSetupUnsuccessfulTransfer_t *)calloc(1, sizeof(NGAP_PDUSessionResourceSetupUnsuccessfulTransfer_t)); + pdusessionUnTransfer_p->cause.present = initial_ctxt_resp_p->pdusessions_failed[i].cause; switch(pdusessionUnTransfer_p->cause.present) { case NGAP_Cause_PR_radioNetwork: @@ -993,7 +990,6 @@ int ngap_gNB_pdusession_setup_resp(instance_t instance, uint8_t *buffer = NULL; uint32_t length; int i; - asn_encode_to_new_buffer_result_t res = { NULL, {0, NULL, NULL} }; /* Retrieve the NGAP gNB instance associated with Mod_id */ ngap_gNB_instance_p = ngap_gNB_get_instance(instance); @@ -1028,14 +1024,14 @@ int ngap_gNB_pdusession_setup_resp(instance_t instance, pdu.choice.successfulOutcome->value.present = NGAP_SuccessfulOutcome__value_PR_PDUSessionResourceSetupResponse; out = &pdu.choice.successfulOutcome->value.choice.PDUSessionResourceSetupResponse; /* mandatory */ - ie = (NGAP_PDUSessionResourceSetupResponseIEs_t *)calloc(1, sizeof(NGAP_PDUSessionResourceSetupResponseIEs_t)); + ie = calloc(1, sizeof *ie); ie->id = NGAP_ProtocolIE_ID_id_AMF_UE_NGAP_ID; ie->criticality = NGAP_Criticality_ignore; ie->value.present = NGAP_PDUSessionResourceSetupResponseIEs__value_PR_AMF_UE_NGAP_ID; asn_uint642INTEGER(&ie->value.choice.AMF_UE_NGAP_ID, ue_context_p->amf_ue_ngap_id); ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie); /* mandatory */ - ie = (NGAP_PDUSessionResourceSetupResponseIEs_t *)calloc(1, sizeof(NGAP_PDUSessionResourceSetupResponseIEs_t)); + ie = calloc(1, sizeof *ie ); ie->id = NGAP_ProtocolIE_ID_id_RAN_UE_NGAP_ID; ie->criticality = NGAP_Criticality_ignore; ie->value.present = NGAP_PDUSessionResourceSetupResponseIEs__value_PR_RAN_UE_NGAP_ID; @@ -1044,23 +1040,19 @@ int ngap_gNB_pdusession_setup_resp(instance_t instance, /* optional */ if (pdusession_setup_resp_p->nb_of_pdusessions > 0) { - ie = (NGAP_PDUSessionResourceSetupResponseIEs_t *)calloc(1, sizeof(NGAP_PDUSessionResourceSetupResponseIEs_t)); + ie = calloc(1, sizeof *ie ); ie->id = NGAP_ProtocolIE_ID_id_PDUSessionResourceSetupListSURes; ie->criticality = NGAP_Criticality_ignore; ie->value.present = NGAP_PDUSessionResourceSetupResponseIEs__value_PR_PDUSessionResourceSetupListSURes; for (i = 0; i < pdusession_setup_resp_p->nb_of_pdusessions; i++) { - NGAP_PDUSessionResourceSetupItemSURes_t *item; - NGAP_PDUSessionResourceSetupResponseTransfer_t *pdusessionTransfer_p = NULL; - - /* mandatory */ - item = (NGAP_PDUSessionResourceSetupItemSURes_t *)calloc(1, sizeof(NGAP_PDUSessionResourceSetupItemSURes_t)); + NGAP_PDUSessionResourceSetupItemSURes_t *item=calloc(1, sizeof *item ); + NGAP_PDUSessionResourceSetupResponseTransfer_t *pdusessionTransfer_p = calloc(1, sizeof *pdusessionTransfer_p ); /* pDUSessionID */ item->pDUSessionID = pdusession_setup_resp_p->pdusessions[i].pdusession_id; /* dLQosFlowPerTNLInformation */ - pdusessionTransfer_p = (NGAP_PDUSessionResourceSetupResponseTransfer_t *)calloc(1, sizeof(NGAP_PDUSessionResourceSetupResponseTransfer_t)); pdusessionTransfer_p->dLQosFlowPerTNLInformation.uPTransportLayerInformation.present = NGAP_UPTransportLayerInformation_PR_gTPTunnel; pdusessionTransfer_p->dLQosFlowPerTNLInformation.uPTransportLayerInformation.choice.gTPTunnel = @@ -1086,8 +1078,7 @@ int ngap_gNB_pdusession_setup_resp(instance_t instance, /* associatedQosFlowList. number of 1? */ for(int j=0; j < pdusession_setup_resp_p->pdusessions[i].nb_of_qos_flow; j++) { - NGAP_AssociatedQosFlowItem_t *ass_qos_item_p; - ass_qos_item_p = (NGAP_AssociatedQosFlowItem_t *)calloc(1, sizeof(NGAP_AssociatedQosFlowItem_t)); + NGAP_AssociatedQosFlowItem_t *ass_qos_item_p = calloc(1, sizeof *ass_qos_item_p); /* qosFlowIdentifier */ ass_qos_item_p->qosFlowIdentifier = pdusession_setup_resp_p->pdusessions[i].associated_qos_flows[j].qfi; @@ -1100,11 +1091,10 @@ int ngap_gNB_pdusession_setup_resp(instance_t instance, ASN_SEQUENCE_ADD(&pdusessionTransfer_p->dLQosFlowPerTNLInformation.associatedQosFlowList.list, ass_qos_item_p); } - memset(&res, 0, sizeof(res)); // res = asn_encode_to_new_buffer(NULL, ATS_ALIGNED_CANONICAL_PER, &asn_DEF_NGAP_PDUSessionResourceSetupResponseTransfer, pdusessionTransfer_p); // item->pDUSessionResourceSetupResponseTransfer.buf = res.buffer; // item->pDUSessionResourceSetupResponseTransfer.size = res.result.encoded; - uint8_t buffer[100]; + uint8_t *buffer=calloc(1,100);; asn_enc_rval_t enc_rval = aper_encode_to_buffer(&asn_DEF_NGAP_PDUSessionResourceSetupResponseTransfer, NULL, pdusessionTransfer_p, @@ -1122,22 +1112,19 @@ int ngap_gNB_pdusession_setup_resp(instance_t instance, /* optional */ if (pdusession_setup_resp_p->nb_of_pdusessions_failed > 0) { - ie = (NGAP_PDUSessionResourceSetupResponseIEs_t *)calloc(1, sizeof(NGAP_PDUSessionResourceSetupResponseIEs_t)); + ie = calloc(1, sizeof *ie); ie->id = NGAP_ProtocolIE_ID_id_PDUSessionResourceFailedToSetupListSURes; ie->criticality = NGAP_Criticality_ignore; ie->value.present = NGAP_PDUSessionResourceSetupResponseIEs__value_PR_PDUSessionResourceFailedToSetupListSURes; for (i = 0; i < pdusession_setup_resp_p->nb_of_pdusessions_failed; i++) { - NGAP_PDUSessionResourceFailedToSetupItemSURes_t *item; - NGAP_PDUSessionResourceSetupUnsuccessfulTransfer_t *pdusessionUnTransfer_p = NULL; + NGAP_PDUSessionResourceFailedToSetupItemSURes_t *item=calloc(1, sizeof *item); + NGAP_PDUSessionResourceSetupUnsuccessfulTransfer_t *pdusessionUnTransfer_p = calloc(1, sizeof *pdusessionUnTransfer_p); - /* mandatory */ - item = (NGAP_PDUSessionResourceFailedToSetupItemSURes_t *)calloc(1, sizeof(NGAP_PDUSessionResourceFailedToSetupItemSURes_t)); /* pDUSessionID */ item->pDUSessionID = pdusession_setup_resp_p->pdusessions_failed[i].pdusession_id; /* cause */ - pdusessionUnTransfer_p = (NGAP_PDUSessionResourceSetupUnsuccessfulTransfer_t *)calloc(1, sizeof(NGAP_PDUSessionResourceSetupUnsuccessfulTransfer_t)); pdusessionUnTransfer_p->cause.present = pdusession_setup_resp_p->pdusessions_failed[i].cause; switch(pdusessionUnTransfer_p->cause.present) { case NGAP_Cause_PR_radioNetwork: @@ -1167,8 +1154,9 @@ int ngap_gNB_pdusession_setup_resp(instance_t instance, NGAP_DEBUG("pdusession setup response: failed pdusession ID %ld\n", item->pDUSessionID); - memset(&res, 0, sizeof(res)); - res = asn_encode_to_new_buffer(NULL, ATS_ALIGNED_CANONICAL_PER, &asn_DEF_NGAP_PDUSessionResourceSetupUnsuccessfulTransfer, pdusessionUnTransfer_p); + asn_encode_to_new_buffer_result_t res = + asn_encode_to_new_buffer(NULL, ATS_ALIGNED_CANONICAL_PER, + &asn_DEF_NGAP_PDUSessionResourceSetupUnsuccessfulTransfer, pdusessionUnTransfer_p); item->pDUSessionResourceSetupUnsuccessfulTransfer.buf = res.buffer; item->pDUSessionResourceSetupUnsuccessfulTransfer.size = res.result.encoded; @@ -1182,7 +1170,7 @@ int ngap_gNB_pdusession_setup_resp(instance_t instance, /* optional */ if (0) { - ie = (NGAP_PDUSessionResourceSetupResponseIEs_t *)calloc(1, sizeof(NGAP_PDUSessionResourceSetupResponseIEs_t)); + ie = calloc(1, sizeof *ie); ie->id = NGAP_ProtocolIE_ID_id_CriticalityDiagnostics; ie->criticality = NGAP_Criticality_ignore; ie->value.present = NGAP_PDUSessionResourceSetupResponseIEs__value_PR_CriticalityDiagnostics; From bfccbfd15dd287d1d2cfa2479e40004ad5069aaf Mon Sep 17 00:00:00 2001 From: Laurent THOMAS Date: Mon, 9 Aug 2021 21:57:35 +0200 Subject: [PATCH 85/91] sanitize heap overflow detection --- openair3/NGAP/ngap_gNB_nas_procedures.c | 26 ++++++++++--------------- 1 file changed, 10 insertions(+), 16 deletions(-) diff --git a/openair3/NGAP/ngap_gNB_nas_procedures.c b/openair3/NGAP/ngap_gNB_nas_procedures.c index 3d71464bbf..6686f8c19e 100644 --- a/openair3/NGAP/ngap_gNB_nas_procedures.c +++ b/openair3/NGAP/ngap_gNB_nas_procedures.c @@ -989,7 +989,6 @@ int ngap_gNB_pdusession_setup_resp(instance_t instance, NGAP_PDUSessionResourceSetupResponseIEs_t *ie; uint8_t *buffer = NULL; uint32_t length; - int i; /* Retrieve the NGAP gNB instance associated with Mod_id */ ngap_gNB_instance_p = ngap_gNB_get_instance(instance); @@ -1018,7 +1017,7 @@ int ngap_gNB_pdusession_setup_resp(instance_t instance, /* Prepare the NGAP message to encode */ memset(&pdu, 0, sizeof(pdu)); pdu.present = NGAP_NGAP_PDU_PR_successfulOutcome; - pdu.choice.successfulOutcome = (NGAP_SuccessfulOutcome_t *)calloc(1,sizeof(struct NGAP_SuccessfulOutcome)); + pdu.choice.successfulOutcome = calloc(1,sizeof *pdu.choice.successfulOutcome); pdu.choice.successfulOutcome->procedureCode = NGAP_ProcedureCode_id_PDUSessionResourceSetup; pdu.choice.successfulOutcome->criticality = NGAP_Criticality_reject; pdu.choice.successfulOutcome->value.present = NGAP_SuccessfulOutcome__value_PR_PDUSessionResourceSetupResponse; @@ -1045,7 +1044,7 @@ int ngap_gNB_pdusession_setup_resp(instance_t instance, ie->criticality = NGAP_Criticality_ignore; ie->value.present = NGAP_PDUSessionResourceSetupResponseIEs__value_PR_PDUSessionResourceSetupListSURes; - for (i = 0; i < pdusession_setup_resp_p->nb_of_pdusessions; i++) { + for (int i = 0; i < pdusession_setup_resp_p->nb_of_pdusessions; i++) { NGAP_PDUSessionResourceSetupItemSURes_t *item=calloc(1, sizeof *item ); NGAP_PDUSessionResourceSetupResponseTransfer_t *pdusessionTransfer_p = calloc(1, sizeof *pdusessionTransfer_p ); @@ -1091,17 +1090,11 @@ int ngap_gNB_pdusession_setup_resp(instance_t instance, ASN_SEQUENCE_ADD(&pdusessionTransfer_p->dLQosFlowPerTNLInformation.associatedQosFlowList.list, ass_qos_item_p); } -// res = asn_encode_to_new_buffer(NULL, ATS_ALIGNED_CANONICAL_PER, &asn_DEF_NGAP_PDUSessionResourceSetupResponseTransfer, pdusessionTransfer_p); -// item->pDUSessionResourceSetupResponseTransfer.buf = res.buffer; -// item->pDUSessionResourceSetupResponseTransfer.size = res.result.encoded; - uint8_t *buffer=calloc(1,100);; - asn_enc_rval_t enc_rval = aper_encode_to_buffer(&asn_DEF_NGAP_PDUSessionResourceSetupResponseTransfer, - NULL, - pdusessionTransfer_p, - buffer,100); - AssertFatal (enc_rval.encoded > 0, "ASN1 message encoding failed (%s, %lu)!\n", enc_rval.failed_type->name, enc_rval.encoded); - item->pDUSessionResourceSetupResponseTransfer.buf = buffer; - item->pDUSessionResourceSetupResponseTransfer.size = enc_rval.encoded; + asn_encode_to_new_buffer_result_t res = asn_encode_to_new_buffer(NULL, ATS_ALIGNED_CANONICAL_PER, + &asn_DEF_NGAP_PDUSessionResourceSetupResponseTransfer, pdusessionTransfer_p); + 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_p); @@ -1117,7 +1110,8 @@ int ngap_gNB_pdusession_setup_resp(instance_t instance, ie->criticality = NGAP_Criticality_ignore; ie->value.present = NGAP_PDUSessionResourceSetupResponseIEs__value_PR_PDUSessionResourceFailedToSetupListSURes; - for (i = 0; i < pdusession_setup_resp_p->nb_of_pdusessions_failed; i++) { + for (int i = 0; i < pdusession_setup_resp_p->nb_of_pdusessions_failed; i++) { + LOG_W(NGAP,"add a failed session\n"); NGAP_PDUSessionResourceFailedToSetupItemSURes_t *item=calloc(1, sizeof *item); NGAP_PDUSessionResourceSetupUnsuccessfulTransfer_t *pdusessionUnTransfer_p = calloc(1, sizeof *pdusessionUnTransfer_p); @@ -1156,7 +1150,7 @@ int ngap_gNB_pdusession_setup_resp(instance_t instance, asn_encode_to_new_buffer_result_t res = asn_encode_to_new_buffer(NULL, ATS_ALIGNED_CANONICAL_PER, - &asn_DEF_NGAP_PDUSessionResourceSetupUnsuccessfulTransfer, pdusessionUnTransfer_p); + &asn_DEF_NGAP_PDUSessionResourceSetupUnsuccessfulTransfer, pdusessionUnTransfer_p); item->pDUSessionResourceSetupUnsuccessfulTransfer.buf = res.buffer; item->pDUSessionResourceSetupUnsuccessfulTransfer.size = res.result.encoded; From eceb67215cf016dcbc65e4d4366bd547921d8c8d Mon Sep 17 00:00:00 2001 From: Raphael Defosseux Date: Tue, 10 Aug 2021 08:38:49 +0200 Subject: [PATCH 86/91] fix(ci): fix typo Signed-off-by: Raphael Defosseux --- ci-scripts/html.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ci-scripts/html.py b/ci-scripts/html.py index 40bb3f9b9f..b172ffb711 100644 --- a/ci-scripts/html.py +++ b/ci-scripts/html.py @@ -185,7 +185,7 @@ class HTMLManagement(): if (ADBIPAddress != 'none') and (ADBIPAddress != 'modules'): self.htmlFile.write('

' + str(self.htmlNb_Smartphones) + ' UE(s) is(are) connected to ADB bench server

\n') self.htmlFile.write('

' + str(self.htmlNb_CATM_Modules) + ' CAT-M UE(s) is(are) connected to bench server

\n') - elif (ADBIPAddress != 'modules'): + elif (ADBIPAddress == 'modules'): self.htmlUEConnected = 1 self.htmlFile.write('

1 commercial module is connected to CI bench

\n') else: From 37e7db80a3a9ff7f026f20c8c875b360a8c138ce Mon Sep 17 00:00:00 2001 From: Mahesh Date: Tue, 10 Aug 2021 14:22:50 +0530 Subject: [PATCH 87/91] documentation typo, build error, pack/unpack bug fix --- doc/NR_NFAPI_archi.md | 2 +- nfapi/oai_integration/nfapi_pnf.c | 3 +++ nfapi/open-nFAPI/nfapi/src/nfapi_p7.c | 4 ++-- openair1/SCHED/nfapi_lte_dummy.c | 4 ++++ openair1/SCHED/nfapi_nr_dummy.c | 4 ++++ openair1/SCHED_NR/fapi_nr_l1.c | 1 - openair2/NR_PHY_INTERFACE/NR_IF_Module.c | 12 ++++++------ 7 files changed, 20 insertions(+), 10 deletions(-) diff --git a/doc/NR_NFAPI_archi.md b/doc/NR_NFAPI_archi.md index 2c92f9497d..59c511fb52 100644 --- a/doc/NR_NFAPI_archi.md +++ b/doc/NR_NFAPI_archi.md @@ -112,7 +112,7 @@ While receiving the DL P7 message, we check whether the message was received wit 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 oai_slot_ind-->pselect; + 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 ``` diff --git a/nfapi/oai_integration/nfapi_pnf.c b/nfapi/oai_integration/nfapi_pnf.c index df32c05b60..2cbec1a050 100644 --- a/nfapi/oai_integration/nfapi_pnf.c +++ b/nfapi/oai_integration/nfapi_pnf.c @@ -92,6 +92,9 @@ extern void handle_nr_nfapi_pdsch_pdu(PHY_VARS_gNB *gNB,int frame,int slot, uint8_t *sdu); extern void handle_nr_nfapi_ssb_pdu(PHY_VARS_gNB *gNB,int frame,int slot, nfapi_nr_dl_tti_request_pdu_t *dl_tti_pdu); +extern void handle_nfapi_nr_csirs_pdu(PHY_VARS_gNB *gNB, + int frame, int slot, + nfapi_nr_dl_tti_csi_rs_pdu *csirs_pdu); extern void nr_fill_ulsch(PHY_VARS_gNB *gNB, int frame, int slot, diff --git a/nfapi/open-nFAPI/nfapi/src/nfapi_p7.c b/nfapi/open-nFAPI/nfapi/src/nfapi_p7.c index 878666dbcf..bc569c3d1b 100755 --- a/nfapi/open-nFAPI/nfapi/src/nfapi_p7.c +++ b/nfapi/open-nFAPI/nfapi/src/nfapi_p7.c @@ -708,7 +708,7 @@ static uint8_t pack_dl_tti_request_body_value(void* tlv, uint8_t **ppWritePacked { nfapi_nr_dl_tti_request_pdu_t* value = (nfapi_nr_dl_tti_request_pdu_t*)tlv; - if(!(push16(value->PDUSize, ppWritePackedMsg, end) && + if(!(push32(value->PDUSize, ppWritePackedMsg, end) && push16(value->PDUType, ppWritePackedMsg, end) )) return 0; @@ -4607,7 +4607,7 @@ static uint8_t unpack_dl_tti_request_body_value(uint8_t **ppReadPackedMsg, uint8 { nfapi_nr_dl_tti_request_pdu_t* value = (nfapi_nr_dl_tti_request_pdu_t*)msg; - if(!(pull16(ppReadPackedMsg, &value->PDUSize, end) && + if(!(pull32(ppReadPackedMsg, &value->PDUSize, end) && pull16(ppReadPackedMsg, &value->PDUType, end) )) return 0; diff --git a/openair1/SCHED/nfapi_lte_dummy.c b/openair1/SCHED/nfapi_lte_dummy.c index 9562e2de30..7d1e7e7684 100644 --- a/openair1/SCHED/nfapi_lte_dummy.c +++ b/openair1/SCHED/nfapi_lte_dummy.c @@ -17,6 +17,10 @@ void handle_nr_nfapi_pdsch_pdu(PHY_VARS_gNB *gNB,int frame,int slot, nfapi_nr_dl_tti_pdsch_pdu *pdsch_pdu, uint8_t *sdu){ } +void handle_nfapi_nr_csirs_pdu(PHY_VARS_gNB *gNB, + int frame, int slot, + nfapi_nr_dl_tti_csi_rs_pdu *csirs_pdu){ + } int l1_north_init_gNB(void){return 0;} uint8_t slot_ahead=6; diff --git a/openair1/SCHED/nfapi_nr_dummy.c b/openair1/SCHED/nfapi_nr_dummy.c index db20017fb8..1286a4e48a 100644 --- a/openair1/SCHED/nfapi_nr_dummy.c +++ b/openair1/SCHED/nfapi_nr_dummy.c @@ -17,6 +17,10 @@ void handle_nr_nfapi_pdsch_pdu(PHY_VARS_gNB *gNB,int frame,int slot, nfapi_nr_dl_tti_pdsch_pdu *pdsch_pdu, uint8_t *sdu){ } +void handle_nfapi_nr_csirs_pdu(PHY_VARS_gNB *gNB, + int frame, int slot, + nfapi_nr_dl_tti_csi_rs_pdu *csirs_pdu){ + } int l1_north_init_gNB(void){return 0;} uint8_t slot_ahead=6; diff --git a/openair1/SCHED_NR/fapi_nr_l1.c b/openair1/SCHED_NR/fapi_nr_l1.c index 4c1dd7ebdd..fa762fa5b8 100644 --- a/openair1/SCHED_NR/fapi_nr_l1.c +++ b/openair1/SCHED_NR/fapi_nr_l1.c @@ -229,7 +229,6 @@ void nr_schedule_response(NR_Sched_Rsp_t *Sched_INFO){ AssertFatal(TX_req->pdu_list[pduIndex].num_TLV == 1, "TX_req->pdu_list[%d].num_TLV %d != 1\n", pduIndex,TX_req->pdu_list[pduIndex].num_TLV); uint8_t *sdu = (uint8_t *)TX_req->pdu_list[pduIndex].TLVs[0].value.direct; - if(NFAPI_MODE != NFAPI_MODE_VNF) handle_nr_nfapi_pdsch_pdu(gNB,frame,slot,&dl_tti_pdu->pdsch_pdu, sdu); break; } diff --git a/openair2/NR_PHY_INTERFACE/NR_IF_Module.c b/openair2/NR_PHY_INTERFACE/NR_IF_Module.c index 16bffb14f4..dcd469f363 100644 --- a/openair2/NR_PHY_INTERFACE/NR_IF_Module.c +++ b/openair2/NR_PHY_INTERFACE/NR_IF_Module.c @@ -48,12 +48,12 @@ extern int oai_nfapi_crc_indication(nfapi_crc_indication_t *crc_ind); extern int oai_nfapi_cqi_indication(nfapi_cqi_indication_t *cqi_ind); extern int oai_nfapi_sr_indication(nfapi_sr_indication_t *ind); extern int oai_nfapi_rx_ind(nfapi_rx_indication_t *ind); -int oai_nfapi_nr_slot_indication(nfapi_nr_slot_indication_scf_t *ind); -int oai_nfapi_nr_rx_data_indication(nfapi_nr_rx_data_indication_t *ind); -int oai_nfapi_nr_crc_indication(nfapi_nr_crc_indication_t *ind); -int oai_nfapi_nr_srs_indication(nfapi_nr_srs_indication_t *ind); -int oai_nfapi_nr_uci_indication(nfapi_nr_uci_indication_t *ind); -int oai_nfapi_nr_rach_indication(nfapi_nr_rach_indication_t *ind); +extern int oai_nfapi_nr_slot_indication(nfapi_nr_slot_indication_scf_t *ind); +extern int oai_nfapi_nr_rx_data_indication(nfapi_nr_rx_data_indication_t *ind); +extern int oai_nfapi_nr_crc_indication(nfapi_nr_crc_indication_t *ind); +extern int oai_nfapi_nr_srs_indication(nfapi_nr_srs_indication_t *ind); +extern int oai_nfapi_nr_uci_indication(nfapi_nr_uci_indication_t *ind); +extern int oai_nfapi_nr_rach_indication(nfapi_nr_rach_indication_t *ind); extern uint8_t nfapi_mode; extern uint16_t sf_ahead; extern uint16_t sl_ahead; From 49fc03a65ebd9529beefdb904287f86df30dd699 Mon Sep 17 00:00:00 2001 From: Mahesh Date: Wed, 11 Aug 2021 13:16:32 +0530 Subject: [PATCH 88/91] Cleanup and some minor bugfixes --- nfapi/open-nFAPI/nfapi/src/nfapi_p7.c | 6 +- nfapi/open-nFAPI/vnf/src/vnf_p7.c | 4 +- nfapi/open-nFAPI/vnf/src/vnf_p7_interface.c | 88 +-------------------- openair2/GNB_APP/gnb_app.c | 37 ++++----- openair2/NR_PHY_INTERFACE/NR_IF_Module.c | 8 +- 5 files changed, 30 insertions(+), 113 deletions(-) diff --git a/nfapi/open-nFAPI/nfapi/src/nfapi_p7.c b/nfapi/open-nFAPI/nfapi/src/nfapi_p7.c index bc569c3d1b..6111b69bf9 100755 --- a/nfapi/open-nFAPI/nfapi/src/nfapi_p7.c +++ b/nfapi/open-nFAPI/nfapi/src/nfapi_p7.c @@ -3523,7 +3523,7 @@ static uint8_t pack_nr_rach_indication(void *msg, uint8_t **ppWritePackedMsg, ui if (!(push16(pNfapiMsg->sfn , ppWritePackedMsg, end) && push16(pNfapiMsg->slot , ppWritePackedMsg, end) && - push16(pNfapiMsg->number_of_pdus, ppWritePackedMsg, end) + push8(pNfapiMsg->number_of_pdus, ppWritePackedMsg, end) )) return 0; @@ -3748,11 +3748,11 @@ int nfapi_nr_p7_message_pack(void *pMessageBuf, void *pPackedBuf, uint32_t packe break; case NFAPI_NR_PHY_MSG_TYPE_SRS_INDICATION: - result = pack_nr_rach_indication(pMessageHeader, &pWritePackedMessage, end, config); + result = pack_nr_srs_indication(pMessageHeader, &pWritePackedMessage, end, config); break; case NFAPI_NR_PHY_MSG_TYPE_RACH_INDICATION: - result = pack_nr_srs_indication(pMessageHeader, &pWritePackedMessage, end, config); + result = pack_nr_rach_indication(pMessageHeader, &pWritePackedMessage, end, config); break; case NFAPI_NR_PHY_MSG_TYPE_DL_NODE_SYNC: diff --git a/nfapi/open-nFAPI/vnf/src/vnf_p7.c b/nfapi/open-nFAPI/vnf/src/vnf_p7.c index 2c98cb538b..e390031554 100644 --- a/nfapi/open-nFAPI/vnf/src/vnf_p7.c +++ b/nfapi/open-nFAPI/vnf/src/vnf_p7.c @@ -2214,11 +2214,11 @@ void vnf_nr_dispatch_p7_message(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vnf_p7 break; case NFAPI_NR_PHY_MSG_TYPE_SRS_INDICATION: - vnf_handle_nr_rach_indication(pRecvMsg, recvMsgLen, vnf_p7); + vnf_handle_nr_srs_indication(pRecvMsg, recvMsgLen, vnf_p7); break; case NFAPI_NR_PHY_MSG_TYPE_RACH_INDICATION: - vnf_handle_nr_srs_indication(pRecvMsg, recvMsgLen, vnf_p7); + vnf_handle_nr_rach_indication(pRecvMsg, recvMsgLen, vnf_p7); break; case NFAPI_UE_RELEASE_RESPONSE: diff --git a/nfapi/open-nFAPI/vnf/src/vnf_p7_interface.c b/nfapi/open-nFAPI/vnf/src/vnf_p7_interface.c index 2137965a7e..4878150330 100644 --- a/nfapi/open-nFAPI/vnf/src/vnf_p7_interface.c +++ b/nfapi/open-nFAPI/vnf/src/vnf_p7_interface.c @@ -153,31 +153,8 @@ int nfapi_nr_vnf_p7_start(nfapi_vnf_p7_config_t* config) //struct timespec original_pselect_timeout; struct timespec pselect_timeout; pselect_timeout.tv_sec = 100; - pselect_timeout.tv_nsec = 0; // ns in a 0.5 ms - //pselect_timeout.tv_nsec = 500000; + pselect_timeout.tv_nsec = 0; - struct timespec pselect_start; - struct timespec pselect_stop; - - -// struct timespec sf_duration; //Change to slot_duration? -// sf_duration.tv_sec = 0; -// sf_duration.tv_nsec = 0.5e6; // We want 1ms pause //We want 0.5 ms pause for NR - struct timespec slot_duration; - slot_duration.tv_sec = 0; - //slot_duration.tv_nsec = 0.5e6; - slot_duration.tv_nsec = 0.5e6; - - -// struct timespec sf_start; //Change to slot_start? - struct timespec slot_start; -// clock_gettime(CLOCK_MONOTONIC, &sf_start); - clock_gettime(CLOCK_MONOTONIC, &slot_start); - //long millisecond = slot_start.tv_nsec / 0.5e6; -// sf_start = timespec_add(sf_start, sf_duration); - slot_start = timespec_add(slot_start, slot_duration); - - NFAPI_TRACE(NFAPI_TRACE_INFO, "next slot will start at %d.%d\n", slot_start.tv_sec, slot_start.tv_nsec); struct timespec ref_time; clock_gettime(CLOCK_MONOTONIC, &ref_time); uint8_t setup_time; @@ -195,26 +172,8 @@ int nfapi_nr_vnf_p7_start(nfapi_vnf_p7_config_t* config) struct timespec curr_time; clock_gettime(CLOCK_MONOTONIC, &curr_time); setup_time = curr_time.tv_sec - ref_time.tv_sec; - - clock_gettime(CLOCK_MONOTONIC, &pselect_start); - //NFAPI_TRACE(NFAPI_TRACE_INFO, "pselect_start:%d.%d sf_start:%d.%d\n", pselect_start.tv_sec, pselect_start.tv_nsec, sf_start.tv_sec, sf_start.tv_nsec); - - 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 - pselect_timeout.tv_sec = 0; - pselect_timeout.tv_nsec = 0; - LOG_D(MAC, "Slot overrun detected \n"); - //NFAPI_TRACE(NFAPI_TRACE_INFO, "Slot 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 - pselect_timeout = timespec_sub(slot_start, pselect_start); - } - - if(setup_time > 10 && prev_slot != gNB->UL_INFO.slot){ + if(setup_time > 10 && prev_slot != gNB->UL_INFO.slot){ //Give the VNF sufficient time to setup before starting scheduling //Call the scheduler pthread_mutex_lock(&gNB->UL_INFO_mutex); @@ -226,53 +185,12 @@ int nfapi_nr_vnf_p7_start(nfapi_vnf_p7_config_t* config) } selectRetval = pselect(maxSock+1, &rfds, NULL, NULL, &pselect_timeout, NULL); - - clock_gettime(CLOCK_MONOTONIC, &pselect_stop); nfapi_vnf_p7_connection_info_t* curr = vnf_p7->p7_connections; if(selectRetval == 0) { - // pselect timed out - - // calculate the start of the next slot - - slot_start = timespec_add(slot_start, slot_duration); - //NFAPI_TRACE(NFAPI_TRACE_INFO, "next subframe will start at %d.%d\n", sf_start.tv_sec, sf_start.tv_nsec); - if (slot_start.tv_nsec > 1e9) - { - slot_start.tv_sec++; - slot_start.tv_nsec-=1e9; - } - else if (slot_start.tv_nsec < 0) - { - slot_start.tv_sec--; - slot_start.tv_nsec+=1e9; - } - - vnf_p7->slot_start_time_hr = vnf_get_current_time_hr(); - - while(curr != 0) - { - if (curr->slot == 19) - { - curr->sfn = (curr->sfn + 1) % 1024; - curr->slot=0; - } - else - { - curr->slot++; - } - //printf("Frame = %d, slot = %d in VNF main loop. \n",curr->sfn,curr->slot); - - //vnf_nr_sync(vnf_p7, curr); - - (vnf_p7->_public.sync_indication)(&(vnf_p7->_public), 1); //hardcoded sync - - curr = curr->next; - } - send_mac_slot_indications(vnf_p7); - + // pselect timed out, continue } else if(selectRetval > 0) { diff --git a/openair2/GNB_APP/gnb_app.c b/openair2/GNB_APP/gnb_app.c index 85617c4073..5104021399 100644 --- a/openair2/GNB_APP/gnb_app.c +++ b/openair2/GNB_APP/gnb_app.c @@ -219,29 +219,30 @@ void *gNB_app_task(void *args_p) //registered_gnb = 0; __attribute__((unused)) uint32_t register_gnb_pending = gNB_app_register (gnb_id_start, gnb_id_end); } -if (RC.nb_nr_inst > 0) { - if (NODE_IS_CU(RC.nrrrc[0]->node_type)) { + + if (RC.nb_nr_inst > 0) { + if (NODE_IS_CU(RC.nrrrc[0]->node_type)) { - if (itti_create_task(TASK_CU_F1, F1AP_CU_task, NULL) < 0) { - LOG_E(F1AP, "Create task for F1AP CU failed\n"); - AssertFatal(1==0,"exiting"); - } - } + if (itti_create_task(TASK_CU_F1, F1AP_CU_task, NULL) < 0) { + LOG_E(F1AP, "Create task for F1AP CU failed\n"); + AssertFatal(1==0,"exiting"); + } + } - if (NODE_IS_DU(RC.nrrrc[0]->node_type)) { + if (NODE_IS_DU(RC.nrrrc[0]->node_type)) { - if (itti_create_task(TASK_DU_F1, F1AP_DU_task, NULL) < 0) { - LOG_E(F1AP, "Create task for F1AP DU failed\n"); - AssertFatal(1==0,"exiting"); + if (itti_create_task(TASK_DU_F1, F1AP_DU_task, NULL) < 0) { + LOG_E(F1AP, "Create task for F1AP DU failed\n"); + AssertFatal(1==0,"exiting"); + } + // configure F1AP here for F1C + LOG_I(GNB_APP,"ngran_gNB_DU: Allocating ITTI message for F1AP_SETUP_REQ\n"); + msg_p = itti_alloc_new_message (TASK_GNB_APP, 0, F1AP_SETUP_REQ); + RCconfig_NR_DU_F1(msg_p, 0); + + itti_send_msg_to_task (TASK_DU_F1, GNB_MODULE_ID_TO_INSTANCE(0), msg_p); } - // configure F1AP here for F1C - LOG_I(GNB_APP,"ngran_gNB_DU: Allocating ITTI message for F1AP_SETUP_REQ\n"); - msg_p = itti_alloc_new_message (TASK_GNB_APP, 0, F1AP_SETUP_REQ); - RCconfig_NR_DU_F1(msg_p, 0); - - itti_send_msg_to_task (TASK_DU_F1, GNB_MODULE_ID_TO_INSTANCE(0), msg_p); } -} do { // Wait for a message itti_receive_msg (TASK_GNB_APP, &msg_p); diff --git a/openair2/NR_PHY_INTERFACE/NR_IF_Module.c b/openair2/NR_PHY_INTERFACE/NR_IF_Module.c index dcd469f363..58a477aa36 100644 --- a/openair2/NR_PHY_INTERFACE/NR_IF_Module.c +++ b/openair2/NR_PHY_INTERFACE/NR_IF_Module.c @@ -61,7 +61,7 @@ extern uint16_t sl_ahead; 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) { - //LOG_D(PHY,"UL_info->crc_ind.crc_indication_body.number_of_crcs:%d CRC_IND:SFN/SF:%d\n", UL_info->crc_ind.crc_indication_body.number_of_crcs, NFAPI_SFNSF2DEC(UL_info->crc_ind.sfn_sf)); + LOG_D(PHY,"UL_info->UL_info->rach_ind.number_of_pdus:%d SFN/Slot:%d.%d \n", UL_info->rach_ind.number_of_pdus, UL_info->rach_ind.sfn,UL_info->rach_ind.slot); oai_nfapi_nr_rach_indication(&UL_info->rach_ind); UL_info->rach_ind.number_of_pdus = 0; } @@ -113,14 +113,12 @@ void handle_nr_uci(NR_UL_IND_t *UL_info) break; case NFAPI_NR_UCI_FORMAT_0_1_PDU_TYPE: { - //printf("handle uci format 0_1 \n"); const nfapi_nr_uci_pucch_pdu_format_0_1_t *uci_pdu = &uci_list[i].pucch_pdu_format_0_1; handle_nr_uci_pucch_0_1(mod_id, frame, slot, uci_pdu); break; } case NFAPI_NR_UCI_FORMAT_2_3_4_PDU_TYPE: { - //printf("handle uci format 2_3_4 \n"); const nfapi_nr_uci_pucch_pdu_format_2_3_4_t *uci_pdu = &uci_list[i].pucch_pdu_format_2_3_4; handle_nr_uci_pucch_2_3_4(mod_id, frame, slot, uci_pdu); break; @@ -137,13 +135,13 @@ void handle_nr_ulsch(NR_UL_IND_t *UL_info) { if(NFAPI_MODE == NFAPI_MODE_PNF) { if (UL_info->crc_ind.number_crcs>0) { - //LOG_D(PHY,"UL_info->crc_ind.crc_indication_body.number_of_crcs:%d CRC_IND:SFN/SF:%d\n", UL_info->crc_ind.crc_indication_body.number_of_crcs, NFAPI_SFNSF2DEC(UL_info->crc_ind.sfn_sf)); + LOG_D(PHY,"UL_info->UL_info->crc_ind.number_crcs:%d CRC_IND:SFN/Slot:%d.%d\n", UL_info->crc_ind.number_crcs, UL_info->crc_ind.sfn, UL_info->crc_ind.slot); oai_nfapi_nr_crc_indication(&UL_info->crc_ind); UL_info->crc_ind.number_crcs = 0; } if (UL_info->rx_ind.number_of_pdus>0) { - //LOG_D(PHY,"UL_info->rx_ind.number_of_pdus:%d RX_IND:SFN/SF:%d\n", UL_info->rx_ind.rx_indication_body.number_of_pdus, NFAPI_SFNSF2DEC(UL_info->rx_ind.sfn_sf)); + LOG_D(PHY,"UL_info->rx_ind.number_of_pdus:%d RX_IND:SFN/Slot:%d.%d \n", UL_info->rx_ind.number_of_pdus, UL_info->rx_ind.sfn, UL_info->rx_ind.slot); oai_nfapi_nr_rx_data_indication(&UL_info->rx_ind); UL_info->rx_ind.number_of_pdus = 0; } From f74b928d8078e3e0de53410b858da28062f3659a Mon Sep 17 00:00:00 2001 From: Mahesh Date: Wed, 11 Aug 2021 13:22:16 +0530 Subject: [PATCH 89/91] Moved documentation to doc folder --- nfapi/nrNFAPI.md => doc/RUN_NR_NFAPI.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename nfapi/nrNFAPI.md => doc/RUN_NR_NFAPI.md (97%) diff --git a/nfapi/nrNFAPI.md b/doc/RUN_NR_NFAPI.md similarity index 97% rename from nfapi/nrNFAPI.md rename to doc/RUN_NR_NFAPI.md index 264c0a3b07..ea7c2590c7 100644 --- a/nfapi/nrNFAPI.md +++ b/doc/RUN_NR_NFAPI.md @@ -1,6 +1,6 @@ # Procedure to run nFAPI in 5G NR -## Conributed by 5G Testbed IISc +## Contributed by 5G Testbed IISc ### Developers: Gokul S, Mahesh A, Aniq U R From 80305493422dbe75adb922eb1e8beb0de91ef8d6 Mon Sep 17 00:00:00 2001 From: Mahesh Date: Wed, 11 Aug 2021 16:15:49 +0530 Subject: [PATCH 90/91] phy-sim build error fix --- nfapi/open-nFAPI/vnf/src/vnf_p7_interface.c | 2 -- openair1/SIMULATION/NR_PHY/dlsim.c | 7 ++++++- openair1/SIMULATION/NR_PHY/nr_dummy_functions.c | 6 ++++++ .../SIMULATION/NR_PHY/nr_dummy_functions_prach.c | 12 +++++++++--- openair1/SIMULATION/NR_PHY/prachsim.c | 5 +++++ openair1/SIMULATION/NR_PHY/ulsim.c | 5 +++++ .../NR_UE_PHY/unit_tests/src/dummy_functions.c | 5 +++++ 7 files changed, 36 insertions(+), 6 deletions(-) diff --git a/nfapi/open-nFAPI/vnf/src/vnf_p7_interface.c b/nfapi/open-nFAPI/vnf/src/vnf_p7_interface.c index 4878150330..8cebf2b468 100644 --- a/nfapi/open-nFAPI/vnf/src/vnf_p7_interface.c +++ b/nfapi/open-nFAPI/vnf/src/vnf_p7_interface.c @@ -185,8 +185,6 @@ int nfapi_nr_vnf_p7_start(nfapi_vnf_p7_config_t* config) } selectRetval = pselect(maxSock+1, &rfds, NULL, NULL, &pselect_timeout, NULL); - - nfapi_vnf_p7_connection_info_t* curr = vnf_p7->p7_connections; if(selectRetval == 0) { diff --git a/openair1/SIMULATION/NR_PHY/dlsim.c b/openair1/SIMULATION/NR_PHY/dlsim.c index b597425ddf..3f3db53e3e 100644 --- a/openair1/SIMULATION/NR_PHY/dlsim.c +++ b/openair1/SIMULATION/NR_PHY/dlsim.c @@ -227,12 +227,17 @@ int DU_send_INITIAL_UL_RRC_MESSAGE_TRANSFER(module_id_t module_idP, void processSlotTX(void *arg) {} -//nFAPI P7 dummy functions +//nFAPI P7 dummy functions to avoid linking errors int oai_nfapi_dl_tti_req(nfapi_nr_dl_tti_request_t *dl_config_req) { return(0); } int oai_nfapi_tx_data_req(nfapi_nr_tx_data_request_t *tx_data_req){ return(0); } int oai_nfapi_ul_dci_req(nfapi_nr_ul_dci_request_t *ul_dci_req){ return(0); } int oai_nfapi_ul_tti_req(nfapi_nr_ul_tti_request_t *ul_tti_req){ return(0); } +int oai_nfapi_nr_rx_data_indication(nfapi_nr_rx_data_indication_t *ind) { return(0); } +int oai_nfapi_nr_crc_indication(nfapi_nr_crc_indication_t *ind) { return(0); } +int oai_nfapi_nr_srs_indication(nfapi_nr_srs_indication_t *ind) { return(0); } +int oai_nfapi_nr_uci_indication(nfapi_nr_uci_indication_t *ind) { return(0); } +int oai_nfapi_nr_rach_indication(nfapi_nr_rach_indication_t *ind) { return(0); } // needed for some functions openair0_config_t openair0_cfg[MAX_CARDS]; diff --git a/openair1/SIMULATION/NR_PHY/nr_dummy_functions.c b/openair1/SIMULATION/NR_PHY/nr_dummy_functions.c index 24ed8a930c..e9588ea49c 100644 --- a/openair1/SIMULATION/NR_PHY/nr_dummy_functions.c +++ b/openair1/SIMULATION/NR_PHY/nr_dummy_functions.c @@ -8,6 +8,12 @@ int oai_nfapi_dl_tti_req(nfapi_nr_dl_tti_request_t *dl_config_req) { return(0); int oai_nfapi_tx_data_req(nfapi_nr_tx_data_request_t *tx_data_req){ return(0); } int oai_nfapi_ul_dci_req(nfapi_nr_ul_dci_request_t *ul_dci_req){ return(0); } int oai_nfapi_ul_tti_req(nfapi_nr_ul_tti_request_t *ul_tti_req){ return(0); } +int oai_nfapi_nr_rx_data_indication(nfapi_nr_rx_data_indication_t *ind) { return(0); } +int oai_nfapi_nr_crc_indication(nfapi_nr_crc_indication_t *ind) { return(0); } +int oai_nfapi_nr_srs_indication(nfapi_nr_srs_indication_t *ind) { return(0); } +int oai_nfapi_nr_uci_indication(nfapi_nr_uci_indication_t *ind) { return(0); } +int oai_nfapi_nr_rach_indication(nfapi_nr_rach_indication_t *ind) { return(0); } + int32_t get_uldl_offset(int nr_bandP) { return(0); } NR_IF_Module_t *NR_IF_Module_init(int Mod_id) {return(NULL);} nfapi_mode_t nfapi_mod; diff --git a/openair1/SIMULATION/NR_PHY/nr_dummy_functions_prach.c b/openair1/SIMULATION/NR_PHY/nr_dummy_functions_prach.c index a930c96a75..d02f3fa493 100644 --- a/openair1/SIMULATION/NR_PHY/nr_dummy_functions_prach.c +++ b/openair1/SIMULATION/NR_PHY/nr_dummy_functions_prach.c @@ -3,9 +3,15 @@ int oai_nfapi_tx_req(nfapi_tx_request_t *tx_req) { re int oai_nfapi_dl_config_req(nfapi_dl_config_request_t *dl_config_req) { return(0); } int oai_nfapi_ul_config_req(nfapi_ul_config_request_t *ul_config_req) { return(0); } int oai_nfapi_dl_tti_req(nfapi_nr_dl_tti_request_t *dl_config_req) { return(0); } - int oai_nfapi_tx_data_req(nfapi_nr_tx_data_request_t *tx_data_req){ return(0); } - int oai_nfapi_ul_dci_req(nfapi_nr_ul_dci_request_t *ul_dci_req){ return(0); } - int oai_nfapi_ul_tti_req(nfapi_nr_ul_tti_request_t *ul_tti_req){ return(0); } +int oai_nfapi_tx_data_req(nfapi_nr_tx_data_request_t *tx_data_req){ return(0); } +int oai_nfapi_ul_dci_req(nfapi_nr_ul_dci_request_t *ul_dci_req){ return(0); } +int oai_nfapi_ul_tti_req(nfapi_nr_ul_tti_request_t *ul_tti_req){ return(0); } +int oai_nfapi_nr_rx_data_indication(nfapi_nr_rx_data_indication_t *ind) { return(0); } +int oai_nfapi_nr_crc_indication(nfapi_nr_crc_indication_t *ind) { return(0); } +int oai_nfapi_nr_srs_indication(nfapi_nr_srs_indication_t *ind) { return(0); } +int oai_nfapi_nr_uci_indication(nfapi_nr_uci_indication_t *ind) { return(0); } +int oai_nfapi_nr_rach_indication(nfapi_nr_rach_indication_t *ind) { return(0); } + int32_t get_uldl_offset(int nr_bandP) { return(0); } NR_IF_Module_t *NR_IF_Module_init(int Mod_id) {return(NULL);} int dummy_nr_ue_dl_indication(nr_downlink_indication_t *dl_info) { return(0); } diff --git a/openair1/SIMULATION/NR_PHY/prachsim.c b/openair1/SIMULATION/NR_PHY/prachsim.c index 93bed5514f..d9542a37ad 100644 --- a/openair1/SIMULATION/NR_PHY/prachsim.c +++ b/openair1/SIMULATION/NR_PHY/prachsim.c @@ -81,6 +81,11 @@ int oai_nfapi_dl_tti_req(nfapi_nr_dl_tti_request_t *dl_config_req) { return(0); int oai_nfapi_tx_data_req(nfapi_nr_tx_data_request_t *tx_data_req){ return(0); } int oai_nfapi_ul_dci_req(nfapi_nr_ul_dci_request_t *ul_dci_req){ return(0); } int oai_nfapi_ul_tti_req(nfapi_nr_ul_tti_request_t *ul_tti_req){ return(0); } +int oai_nfapi_nr_rx_data_indication(nfapi_nr_rx_data_indication_t *ind) { return(0); } +int oai_nfapi_nr_crc_indication(nfapi_nr_crc_indication_t *ind) { return(0); } +int oai_nfapi_nr_srs_indication(nfapi_nr_srs_indication_t *ind) { return(0); } +int oai_nfapi_nr_uci_indication(nfapi_nr_uci_indication_t *ind) { return(0); } +int oai_nfapi_nr_rach_indication(nfapi_nr_rach_indication_t *ind) { return(0); } void rrc_data_ind( diff --git a/openair1/SIMULATION/NR_PHY/ulsim.c b/openair1/SIMULATION/NR_PHY/ulsim.c index 62f4420e75..705b801d7a 100644 --- a/openair1/SIMULATION/NR_PHY/ulsim.c +++ b/openair1/SIMULATION/NR_PHY/ulsim.c @@ -213,6 +213,11 @@ int oai_nfapi_dl_tti_req(nfapi_nr_dl_tti_request_t *dl_config_req) { return(0); int oai_nfapi_tx_data_req(nfapi_nr_tx_data_request_t *tx_data_req){ return(0); } int oai_nfapi_ul_dci_req(nfapi_nr_ul_dci_request_t *ul_dci_req){ return(0); } int oai_nfapi_ul_tti_req(nfapi_nr_ul_tti_request_t *ul_tti_req){ return(0); } +int oai_nfapi_nr_rx_data_indication(nfapi_nr_rx_data_indication_t *ind) { return(0); } +int oai_nfapi_nr_crc_indication(nfapi_nr_crc_indication_t *ind) { return(0); } +int oai_nfapi_nr_srs_indication(nfapi_nr_srs_indication_t *ind) { return(0); } +int oai_nfapi_nr_uci_indication(nfapi_nr_uci_indication_t *ind) { return(0); } +int oai_nfapi_nr_rach_indication(nfapi_nr_rach_indication_t *ind) { return(0); } int nr_derive_key(int alg_type, uint8_t alg_id, const uint8_t key[32], uint8_t **out) diff --git a/openair1/SIMULATION/NR_UE_PHY/unit_tests/src/dummy_functions.c b/openair1/SIMULATION/NR_UE_PHY/unit_tests/src/dummy_functions.c index 4d17fe723c..b8a5c7a780 100644 --- a/openair1/SIMULATION/NR_UE_PHY/unit_tests/src/dummy_functions.c +++ b/openair1/SIMULATION/NR_UE_PHY/unit_tests/src/dummy_functions.c @@ -146,6 +146,11 @@ int oai_nfapi_dl_tti_req(nfapi_nr_dl_tti_request_t *dl_config_req) { return(0); int oai_nfapi_tx_data_req(nfapi_nr_tx_data_request_t *tx_data_req){ return(0); } int oai_nfapi_ul_dci_req(nfapi_nr_ul_dci_request_t *ul_dci_req){ return(0); } int oai_nfapi_ul_tti_req(nfapi_nr_ul_tti_request_t *ul_tti_req){ return(0); } +int oai_nfapi_nr_rx_data_indication(nfapi_nr_rx_data_indication_t *ind) { return(0); } +int oai_nfapi_nr_crc_indication(nfapi_nr_crc_indication_t *ind) { return(0); } +int oai_nfapi_nr_srs_indication(nfapi_nr_srs_indication_t *ind) { return(0); } +int oai_nfapi_nr_uci_indication(nfapi_nr_uci_indication_t *ind) { return(0); } +int oai_nfapi_nr_rach_indication(nfapi_nr_rach_indication_t *ind) { return(0); } int oai_nfapi_dl_config_req(nfapi_dl_config_request_t *dl_config_req) { return(0); } From e2347afbb5823db93861accd09a6ab535c9a368f Mon Sep 17 00:00:00 2001 From: Raphael Defosseux Date: Wed, 11 Aug 2021 23:24:29 +0200 Subject: [PATCH 91/91] feat(ci): adding working docker-compose for 5G RF sim Signed-off-by: Raphael Defosseux --- ci-scripts/conf_files/nr-ue-sim.conf | 8 + .../5g_rfsimulator/amf-healthcheck.sh | 57 ++++ .../5g_rfsimulator/docker-compose.yaml | 293 ++++++++++++++++++ .../5g_rfsimulator/mysql-healthcheck.sh | 46 +++ .../5g_rfsimulator/nrf-healthcheck.sh | 20 ++ .../yaml_files/5g_rfsimulator/oai-smf.conf | 133 ++++++++ .../yaml_files/5g_rfsimulator/oai_db.sql | 217 +++++++++++++ .../5g_rfsimulator/smf-healthcheck.sh | 21 ++ .../5g_rfsimulator/spgwu-healthcheck.sh | 28 ++ docker/Dockerfile.gNB.rhel8.2 | 4 +- docker/Dockerfile.gNB.ubuntu18 | 4 +- docker/Dockerfile.nrUE.rhel8.2 | 29 +- docker/Dockerfile.nrUE.ubuntu18 | 39 +-- docker/scripts/generateTemplate.py | 11 + docker/scripts/gnb_entrypoint.sh | 3 +- docker/scripts/gnb_parameters.yaml | 30 +- docker/scripts/nr_ue_entrypoint.sh | 63 ++++ 17 files changed, 950 insertions(+), 56 deletions(-) create mode 100644 ci-scripts/conf_files/nr-ue-sim.conf create mode 100755 ci-scripts/yaml_files/5g_rfsimulator/amf-healthcheck.sh create mode 100644 ci-scripts/yaml_files/5g_rfsimulator/docker-compose.yaml create mode 100755 ci-scripts/yaml_files/5g_rfsimulator/mysql-healthcheck.sh create mode 100755 ci-scripts/yaml_files/5g_rfsimulator/nrf-healthcheck.sh create mode 100644 ci-scripts/yaml_files/5g_rfsimulator/oai-smf.conf create mode 100755 ci-scripts/yaml_files/5g_rfsimulator/oai_db.sql create mode 100755 ci-scripts/yaml_files/5g_rfsimulator/smf-healthcheck.sh create mode 100755 ci-scripts/yaml_files/5g_rfsimulator/spgwu-healthcheck.sh create mode 100755 docker/scripts/nr_ue_entrypoint.sh diff --git a/ci-scripts/conf_files/nr-ue-sim.conf b/ci-scripts/conf_files/nr-ue-sim.conf new file mode 100644 index 0000000000..05ac825db4 --- /dev/null +++ b/ci-scripts/conf_files/nr-ue-sim.conf @@ -0,0 +1,8 @@ +uicc0 = { + imsi = "@FULL_IMSI@"; + key = "@FULL_KEY@"; + opc= "@OPC@"; + dnn= "@DNN@"; + nssai_sst=@NSSAI_SST@; + nssai_sd=@NSSAI_SD@; +} diff --git a/ci-scripts/yaml_files/5g_rfsimulator/amf-healthcheck.sh b/ci-scripts/yaml_files/5g_rfsimulator/amf-healthcheck.sh new file mode 100755 index 0000000000..8bfdee2aac --- /dev/null +++ b/ci-scripts/yaml_files/5g_rfsimulator/amf-healthcheck.sh @@ -0,0 +1,57 @@ +#!/bin/bash +set -eo pipefail + +STATUS=0 +AMF_PORT_FOR_NGAP=38412 +AMF_PORT_FOR_N11_HTTP=80 +AMF_IP_NGAP_INTERFACE=$(ifconfig $AMF_INTERFACE_NAME_FOR_NGAP | grep inet | awk {'print $2'}) +AMF_IP_N11_INTERFACE=$(ifconfig $AMF_INTERFACE_NAME_FOR_N11 | grep inet | awk {'print $2'}) +N2_PORT_STATUS=$(netstat -Snpl | grep -o "$AMF_IP_NGAP_INTERFACE:$AMF_PORT_FOR_NGAP") +N11_PORT_STATUS=$(netstat -tnpl | grep -o "$AMF_IP_N11_INTERFACE:$AMF_PORT_FOR_N11_HTTP") +#Check if entrypoint properly configured the conf file and no parameter is unset (optional) +NB_UNREPLACED_AT=`cat /openair-amf/etc/*.conf | grep -v contact@openairinterface.org | grep -c @ || true` + +if [ $NB_UNREPLACED_AT -ne 0 ]; then + STATUS=1 + echo "Healthcheck error: configuration file is not configured properly" +fi + +if [[ -z $N2_PORT_STATUS ]]; then + STATUS=1 + echo "Healthcheck error: N2 SCTP port $AMF_PORT_FOR_NGAP is not listening" +fi + +if [[ -z $N11_PORT_STATUS ]]; then + STATUS=1 + echo "Healthcheck error: N11/SBI TCP/HTTP port $AMF_PORT_FOR_N11_HTTP is not listening" +fi + +#host="${MYSQL_SERVER}" +#user="${MYSQL_USER:-root}" +#export MYSQL_PWD="${MYSQL_PASS}" + +#args=( +# -h"$host" +# -u"$user" +# --silent +#) + +#if ! command -v mysql &> /dev/null; then +# echo "Installing mysql command" +# apt update +# apt-get -y install mysql-client +#else +# if select="$(echo 'SELECT 1' | mysql "${args[@]}")" && [ "$select" = '1' ]; then +# database_check=$(mysql -h$host -u$user -D oai_db --silent -e "SELECT * FROM users;") +# if [[ -z $database_check ]]; then +# echo "Healthcheck error: oai_db not populated" +# STATUS=1 +# fi +# STATUS=0 +# else +# echo "Healthcheck error: Mysql port inactive" +# STATUS=1 +# fi +#fi + +exit $STATUS diff --git a/ci-scripts/yaml_files/5g_rfsimulator/docker-compose.yaml b/ci-scripts/yaml_files/5g_rfsimulator/docker-compose.yaml new file mode 100644 index 0000000000..e88a5a0a76 --- /dev/null +++ b/ci-scripts/yaml_files/5g_rfsimulator/docker-compose.yaml @@ -0,0 +1,293 @@ +version: '3.8' +services: + oai-nrf: + container_name: "rfsim5g-oai-nrf" + image: oai-nrf:latest + environment: + - NRF_INTERFACE_NAME_FOR_SBI=eth0 + - NRF_INTERFACE_PORT_FOR_SBI=80 + - NRF_INTERFACE_HTTP2_PORT_FOR_SBI=9090 + - NRF_API_VERSION=v1 + - INSTANCE=0 + - PID_DIRECTORY=/var/run + networks: + public_net: + ipv4_address: 192.168.71.130 + volumes: + - ./nrf-healthcheck.sh:/openair-nrf/bin/nrf-healthcheck.sh + healthcheck: + test: /bin/bash -c "/openair-nrf/bin/nrf-healthcheck.sh" + interval: 10s + timeout: 5s + retries: 5 + mysql: + container_name: "rfsim5g-mysql" + image: mysql:5.7 + volumes: + - ./oai_db.sql:/docker-entrypoint-initdb.d/oai_db.sql + - ./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: 5 + networks: + public_net: + ipv4_address: 192.168.71.131 + oai-amf: + container_name: "rfsim5g-oai-amf" + image: oai-amf:latest + environment: + - TZ=Europe/paris + - INSTANCE=0 + - PID_DIRECTORY=/var/run + - MCC=208 + - MNC=99 + - REGION_ID=128 + - AMF_SET_ID=1 + - SERVED_GUAMI_MCC_0=208 + - SERVED_GUAMI_MNC_0=99 + - SERVED_GUAMI_REGION_ID_0=128 + - SERVED_GUAMI_AMF_SET_ID_0=1 + - SERVED_GUAMI_MCC_1=460 + - SERVED_GUAMI_MNC_1=11 + - SERVED_GUAMI_REGION_ID_1=10 + - SERVED_GUAMI_AMF_SET_ID_1=1 + - PLMN_SUPPORT_MCC=208 + - PLMN_SUPPORT_MNC=99 + - PLMN_SUPPORT_TAC=0x0001 + - SST_0=1 + - SD_0=1 + - SST_1=1 + - SD_1=12 + - AMF_INTERFACE_NAME_FOR_NGAP=eth0 + - AMF_INTERFACE_NAME_FOR_N11=eth0 + - SMF_INSTANCE_ID_0=1 + - SMF_FQDN_0=oai-smf + - SMF_IPV4_ADDR_0=0.0.0.0 + - SMF_HTTP_VERSION_0=v1 + - SELECTED_0=true + - SMF_INSTANCE_ID_1=2 + - SMF_FQDN_1=oai-smf + - SMF_IPV4_ADDR_1=0.0.0.0 + - SMF_HTTP_VERSION_1=v1 + - SELECTED_1=false + - MYSQL_SERVER=192.168.71.131 + - MYSQL_USER=root + - MYSQL_PASS=linux + - MYSQL_DB=oai_db + - OPERATOR_KEY=c42449363bbad02b66d16bc975d77cc1 + - NRF_IPV4_ADDRESS=192.168.71.130 + - NRF_PORT=80 + - NF_REGISTRATION=yes + - SMF_SELECTION=yes + - USE_FQDN_DNS=yes + - NRF_API_VERSION=v1 + - NRF_FQDN=oai-nrf + - AUSF_IPV4_ADDRESS=127.0.0.1 + - AUSF_PORT=80 + - AUSF_API_VERSION=v1 + depends_on: + - oai-nrf + volumes: + - ./amf-healthcheck.sh:/openair-amf/bin/amf-healthcheck.sh + healthcheck: + test: /bin/bash -c "/openair-amf/bin/amf-healthcheck.sh" + interval: 10s + timeout: 15s + retries: 5 + networks: + public_net: + ipv4_address: 192.168.71.132 + oai-smf: + container_name: "rfsim5g-oai-smf" + image: oai-smf:latest + entrypoint: /bin/bash -c "/openair-smf/bin/oai_smf -c /openair-smf/bin/oai-smf.conf -o" + environment: + - TZ=Europe/Paris + - INSTANCE=0 + - PID_DIRECTORY=/var/run + - SMF_INTERFACE_NAME_FOR_N4=eth0 + - SMF_INTERFACE_NAME_FOR_SBI=eth0 + - SMF_INTERFACE_PORT_FOR_SBI=80 + - SMF_INTERFACE_HTTP2_PORT_FOR_SBI=9090 + - SMF_API_VERSION=v1 + - DEFAULT_DNS_IPV4_ADDRESS=192.168.18.129 + - DEFAULT_DNS_SEC_IPV4_ADDRESS=4.4.4.4 + - AMF_IPV4_ADDRESS=0.0.0.0 + - AMF_PORT=80 + - AMF_API_VERSION=v1 + - AMF_FQDN=oai-amf + - UDM_IPV4_ADDRESS=127.0.0.1 + - UDM_PORT=80 + - UDM_API_VERSION=v1 + - UDM_FQDN=localhost + - UPF_IPV4_ADDRESS=192.168.71.134 + - UPF_FQDN_0=oai-spgwu + - NRF_IPV4_ADDRESS=192.168.71.130 + - NRF_PORT=80 + - NRF_API_VERSION=v1 + - NRF_FQDN=oai-nrf + - REGISTER_NRF=yes + - DISCOVER_UPF=yes + - USE_FQDN_DNS=yes + depends_on: + - oai-nrf + volumes: + - ./smf-healthcheck.sh:/openair-smf/bin/smf-healthcheck.sh + - ./oai-smf.conf:/openair-smf/bin/oai-smf.conf + healthcheck: + test: /bin/bash -c "/openair-smf/bin/smf-healthcheck.sh" + interval: 10s + timeout: 5s + retries: 5 + networks: + public_net: + ipv4_address: 192.168.71.133 + oai-spgwu: + container_name: "rfsim5g-oai-spgwu" + image: oai-spgwu-tiny:latest + environment: + - TZ=Europe/Paris + - PID_DIRECTORY=/var/run + - SGW_INTERFACE_NAME_FOR_S1U_S12_S4_UP=eth0 + - SGW_INTERFACE_NAME_FOR_SX=eth0 + - PGW_INTERFACE_NAME_FOR_SGI=eth0 + - NETWORK_UE_NAT_OPTION=yes + - NETWORK_UE_IP=12.1.1.0/24 + - SPGWC0_IP_ADDRESS=192.168.71.133 + - BYPASS_UL_PFCP_RULES=no + - MCC=208 + - MNC=99 + - MNC03=099 + - TAC=1 + - GTP_EXTENSION_HEADER_PRESENT=yes + - GW_ID=1 + - REALM=openairinterface.org + - ENABLE_5G_FEATURES=yes + - REGISTER_NRF=yes + - USE_FQDN_NRF=yes + - UPF_FQDN_5G=oai-spgwu + - NRF_IPV4_ADDRESS=192.168.71.130 + - NRF_PORT=80 + - NRF_API_VERSION=v1 + - NRF_FQDN=oai-nrf + - NSSAI_SST_0=1 + - NSSAI_SD_0=1 + - DNN_0=oai + depends_on: + - oai-nrf + cap_add: + - NET_ADMIN + - SYS_ADMIN + cap_drop: + - ALL + privileged: true + volumes: + - ./spgwu-healthcheck.sh:/openair-spgwu-tiny/bin/spgwu-healthcheck.sh + healthcheck: + test: /bin/bash -c "/openair-spgwu-tiny/bin/spgwu-healthcheck.sh" + interval: 10s + timeout: 5s + retries: 5 + networks: + public_net: + ipv4_address: 192.168.71.134 + traffic_net: + ipv4_address: 192.168.72.134 + oai-ext-dn: + image: ubuntu:bionic + privileged: true + container_name: rfsim5g-oai-ext-dn + entrypoint: /bin/bash -c \ + "apt update; apt install -y iptables iproute2 iperf iputils-ping;"\ + "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-spgwu + 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: oai-gnb:int-w32 + privileged: true + container_name: rfsim5g-oai-gnb + environment: + RFSIMULATOR: server + USE_SA_TDD_MONO: 'yes' + GNB_NAME: gnb-rfsim + TAC: 1 + MCC: '208' + MNC: '99' + MNC_LENGTH: 2 + NSSAI_SST: 1 + NSSAI_SD0: 1 + NSSAI_SD1: 112233 + AMF_IP_ADDRESS: 192.168.71.132 + GNB_NGA_IF_NAME: eth0 + GNB_NGA_IP_ADDRESS: 192.168.71.136 + GNB_NGU_IF_NAME: eth0 + GNB_NGU_IP_ADDRESS: 192.168.71.136 + USE_ADDITIONAL_OPTIONS: --sa -E --rfsim + depends_on: + - oai-ext-dn + networks: + public_net: + ipv4_address: 192.168.71.136 + healthcheck: + test: /bin/bash -c "pgrep nr-softmodem" + interval: 10s + timeout: 5s + retries: 5 + oai-nr-ue: + image: oai-nr-ue:int-w32 + privileged: true + container_name: rfsim5g-oai-nr-ue + environment: + RFSIMULATOR: 192.168.71.136 + FULL_IMSI: '208990100001100' + FULL_KEY: 'fec86ba6eb707ed08905757b1bb44b8f' + OPC: 'C42449363BBAD02B66D16BC975D77CC1' + DNN: oai + NSSAI_SST: 1 + NSSAI_SD: 1 + USE_ADDITIONAL_OPTIONS: -E --sa --rfsim -r 106 --numerology 1 -C 3619200000 --nokrnmod + depends_on: + - oai-gnb + networks: + public_net: + ipv4_address: 192.168.71.137 + 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-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/mysql-healthcheck.sh b/ci-scripts/yaml_files/5g_rfsimulator/mysql-healthcheck.sh new file mode 100755 index 0000000000..c92efb9f00 --- /dev/null +++ b/ci-scripts/yaml_files/5g_rfsimulator/mysql-healthcheck.sh @@ -0,0 +1,46 @@ +#!/bin/bash +set -eo pipefail + +if [ "$MYSQL_ROOT_PASSWORD" ] && [ -z "$MYSQL_USER" ] && [ -z "$MYSQL_PASSWORD" ]; then + echo >&2 'Healthcheck error: cannot determine root password (and MYSQL_USER and MYSQL_PASSWORD were not set)' + exit 0 +fi + +host="$(hostname --ip-address || echo '127.0.0.1')" +user="${MYSQL_USER:-root}" +export MYSQL_PWD="${MYSQL_PASSWORD:-$MYSQL_ROOT_PASSWORD}" + +args=( + # force mysql to not use the local "mysqld.sock" (test "external" connectivity) + -h"$host" + -u"$user" + --silent +) + +STATUS=0 +if command -v mysqladmin &> /dev/null; then + if mysqladmin "${args[@]}" ping > /dev/null; then + database_check=$(mysql -u$user -D oai_db --silent -e "SELECT * FROM users;") + if [[ -z $database_check ]]; then + echo "Healthcheck error: oai_db not populated" + STATUS=1 + fi + STATUS=0 + else + echo "Healthcheck error: Mysql port inactive" + STATUS=1 + fi +else + if select="$(echo 'SELECT 1' | mysql "${args[@]}")" && [ "$select" = '1' ]; then + database_check=$(mysql -u$user -D oai_db --silent -e "SELECT * FROM users;") + if [[ -z $database_check ]]; then + echo "Healthcheck error: oai_db not populated" + STATUS=1 + fi + STATUS=0 + else + echo "Healthcheck error: Mysql port inactive" + STATUS=1 + fi +fi +exit $STATUS diff --git a/ci-scripts/yaml_files/5g_rfsimulator/nrf-healthcheck.sh b/ci-scripts/yaml_files/5g_rfsimulator/nrf-healthcheck.sh new file mode 100755 index 0000000000..3479c092e8 --- /dev/null +++ b/ci-scripts/yaml_files/5g_rfsimulator/nrf-healthcheck.sh @@ -0,0 +1,20 @@ +#!/bin/bash +set -eo pipefail + +STATUS=0 +NRF_IP_SBI_INTERFACE=$(ifconfig $NRF_INTERFACE_NAME_FOR_SBI | grep inet | awk {'print $2'}) +NRF_SBI_PORT_STATUS=$(netstat -tnpl | grep -o "$NRF_IP_SBI_INTERFACE:$NRF_INTERFACE_PORT_FOR_SBI") +#Check if entrypoint properly configured the conf file and no parameter is unset(optional) +NB_UNREPLACED_AT=`cat /openair-nrf/etc/*.conf | grep -v contact@openairinterface.org | grep -c @ || true` + +if [ $NB_UNREPLACED_AT -ne 0 ]; then + STATUS=1 + echo "Healthcheck error: UNHEALTHY configuration file is not configured properly" +fi + +if [[ -z $NRF_SBI_PORT_STATUS ]]; then + STATUS=1 + echo "Healthcheck error: UNHEALTHY SBI TCP/HTTP port $NRF_INTERFACE_PORT_FOR_SBI is not listening." +fi + +exit $STATUS \ No newline at end of file diff --git a/ci-scripts/yaml_files/5g_rfsimulator/oai-smf.conf b/ci-scripts/yaml_files/5g_rfsimulator/oai-smf.conf new file mode 100644 index 0000000000..0c83ab8be9 --- /dev/null +++ b/ci-scripts/yaml_files/5g_rfsimulator/oai-smf.conf @@ -0,0 +1,133 @@ +################################################################################ +# 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 +################################################################################ + +SMF = +{ + FQDN = "oai-smf-svc"; + INSTANCE = 0; # 0 is the default + PID_DIRECTORY = "/var/run"; # /var/run is the default + + INTERFACES : + { + N4 : + { + # SMF binded interface for N4 communication (UPF) + INTERFACE_NAME = "eth0"; # YOUR NETWORK CONFIG HERE + IPV4_ADDRESS = "read"; + }; + + SBI : + { + # SMF binded interface for SBI interface (e.g., communication with AMF, UDM) + INTERFACE_NAME = "eth0"; # YOUR NETWORK CONFIG HERE + IPV4_ADDRESS = "read"; + PORT = 80; # YOUR NETWORK CONFIG HERE (default: 80) + HTTP2_PORT = 9090; # YOUR NETWORK CONFIG HERE + API_VERSION = "v1"; # YOUR SMF API VERSION CONFIG HERE + }; + + }; + + + # Pool of UE assigned IP addresses + # Do not make IP pools overlap + # first IPv4 address X.Y.Z.1 is reserved for GTP network device on UPF + IP_ADDRESS_POOL : + { + IPV4_LIST = ( + {RANGE = "12.1.1.2 - 12.1.1.128";}, # STRING, IPv4 RANGE IP_start - IP_end, YOUR NETWORK CONFIG HERE. + {RANGE = "12.1.1.129 - 12.1.1.224";}, # STRING, IPv4 RANGE IP_start - IP_end, YOUR NETWORK CONFIG HERE. + {RANGE = "10.10.10.2 - 10.10.10.253";} # STRING, IPv4 RANGE IP_start - IP_end, YOUR NETWORK CONFIG HERE. + + ); + IPV6_LIST = ( + {PREFIX = "2001:1:2::/64";}, # STRING, IPv6 prefix, YOUR NETWORK CONFIG HERE. + {PREFIX = "3001:1:2::/64";}, # STRING, IPv6 prefix, YOUR NETWORK CONFIG HERE. + {PREFIX = "4001:1:2::/64";} # STRING, IPv6 prefix, YOUR NETWORK CONFIG HERE. + ); + }; + + DNN_LIST = ( + # IPV4_POOL, IPV6_POOL are index in IPV4_LIST, IPV6_LIST, PDU_SESSION_TYPE choice in {IPv4, IPv6, IPv4v6} + {DNN_NI = "default"; PDU_SESSION_TYPE = "IPv4"; IPV4_POOL = 2; IPV6_POOL = -1}, + {DNN_NI = "carrier.com"; PDU_SESSION_TYPE = "IPv4"; IPV4_POOL = 1; IPV6_POOL = -1}, + {DNN_NI = "oai"; PDU_SESSION_TYPE = "IPv4"; IPV4_POOL = 0; IPV6_POOL = -1} + ); + + # DNS address communicated to UEs + DEFAULT_DNS_IPV4_ADDRESS = "192.168.18.129"; # YOUR DNS CONFIG HERE + DEFAULT_DNS_SEC_IPV4_ADDRESS = "192.168.18.129"; # YOUR DNS CONFIG HERE + DEFAULT_DNS_IPV6_ADDRESS = "2001:4860:4860::8888"; # YOUR DNS CONFIG HERE + DEFAULT_DNS_SEC_IPV6_ADDRESS = "2001:4860:4860::8844"; # YOUR DNS CONFIG HERE + + SUPPORT_FEATURES: + { + # STRING, {"yes", "no"}, + REGISTER_NRF = "yes"; # Set to yes if SMF resgisters to an NRF + DISCOVER_UPF = "yes"; # Set to yes to enable UPF discovery and selection + FORCE_PUSH_PROTOCOL_CONFIGURATION_OPTIONS = "no"; # Non standard feature, normally should be set to "no", + # but you may need to set to yes for UE that do not explicitly request a PDN address through NAS signalling + USE_LOCAL_SUBSCRIPTION_INFO = "yes"; # Set to yes if SMF uses local subscription information instead of from an UDM + USE_FQDN_DNS = "yes"; # Set to yes if AMF/UDM/NRF/UPF will relying on a DNS to resolve FQDN + } + + AMF : + { + IPV4_ADDRESS = "0.0.0.0"; # YOUR AMF CONFIG HERE + PORT = 80; # YOUR AMF CONFIG HERE (default: 80) + API_VERSION = "v1"; # YOUR AMF API VERSION FOR SBI CONFIG HERE + FQDN = "oai-amf" # YOUR AMF FQDN CONFIG HERE + }; + + UDM : + { + IPV4_ADDRESS = "127.0.0.1"; # YOUR UDM CONFIG HERE + PORT = 80; # YOUR UDM CONFIG HERE (default: 80) + API_VERSION = "v1"; # YOUR UDM API VERSION FOR SBI CONFIG HERE + FQDN = "localhost" # YOUR UDM FQDN CONFIG HERE + }; + + NRF : + { + IPV4_ADDRESS = "192.168.71.130"; # YOUR NRF CONFIG HERE + PORT = 80; # YOUR NRF CONFIG HERE (default: 80) + API_VERSION = "v1"; # YOUR NRF API VERSION FOR SBI CONFIG HERE + FQDN = "oai-nrf" # YOUR NRF FQDN CONFIG HERE + }; + + UPF_LIST = ( + {IPV4_ADDRESS = "192.168.71.134" ; FQDN = "oai-spgwu"} # YOUR UPF CONFIG HERE + ); + + LOCAL_CONFIGURATION : + { + SESSION_MANAGEMENT_SUBSCRIPTION_LIST = ( + { NSSAI_SST = 222, NSSAI_SD = "123", DNN = "default", DEFAULT_SESSION_TYPE = "IPV4", DEFAULT_SSC_MODE = 1, + QOS_PROFILE_5QI = 7, QOS_PROFILE_PRIORITY_LEVEL = 1, QOS_PROFILE_ARP_PRIORITY_LEVEL = 1, QOS_PROFILE_ARP_PREEMPTCAP = "NOT_PREEMPT", + QOS_PROFILE_ARP_PREEMPTVULN = "NOT_PREEMPTABLE", SESSION_AMBR_UL = "20Mbps", SESSION_AMBR_DL = "22Mbps"}, + { NSSAI_SST = 1; NSSAI_SD = "1", DNN = "oai", DEFAULT_SESSION_TYPE = "IPV4", DEFAULT_SSC_MODE = 1, + QOS_PROFILE_5QI = 6, QOS_PROFILE_PRIORITY_LEVEL = 1, QOS_PROFILE_ARP_PRIORITY_LEVEL = 1, QOS_PROFILE_ARP_PREEMPTCAP = "NOT_PREEMPT", + QOS_PROFILE_ARP_PREEMPTVULN = "NOT_PREEMPTABLE", SESSION_AMBR_UL = "20Mbps", SESSION_AMBR_DL = "22Mbps"} + ); + }; + +}; + diff --git a/ci-scripts/yaml_files/5g_rfsimulator/oai_db.sql b/ci-scripts/yaml_files/5g_rfsimulator/oai_db.sql new file mode 100755 index 0000000000..fbd7907a71 --- /dev/null +++ b/ci-scripts/yaml_files/5g_rfsimulator/oai_db.sql @@ -0,0 +1,217 @@ +-- MySQL dump 10.13 Distrib 5.5.46, for debian-linux-gnu (x86_64) +-- +-- Host: localhost Database: oai_db +-- ------------------------------------------------------ +-- Server version 5.5.46-0ubuntu0.14.04.2 + +/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; +/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; +/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; +/*!40101 SET NAMES utf8 */; +/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */; +/*!40103 SET TIME_ZONE='+00:00' */; +/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; +/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; +/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; +/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; + +-- +-- Table structure for table `apn` +-- + +DROP TABLE IF EXISTS `apn`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `apn` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `apn-name` varchar(60) NOT NULL, + `pdn-type` enum('IPv4','IPv6','IPv4v6','IPv4_or_IPv6') NOT NULL, + PRIMARY KEY (`id`), + UNIQUE KEY `apn-name` (`apn-name`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `apn` +-- + +LOCK TABLES `apn` WRITE; +/*!40000 ALTER TABLE `apn` DISABLE KEYS */; +/*!40000 ALTER TABLE `apn` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `mmeidentity` +-- + +DROP TABLE IF EXISTS `mmeidentity`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `mmeidentity` ( + `idmmeidentity` int(11) NOT NULL AUTO_INCREMENT, + `mmehost` varchar(255) DEFAULT NULL, + `mmerealm` varchar(200) DEFAULT NULL, + `UE-Reachability` tinyint(1) NOT NULL COMMENT 'Indicates whether the MME supports UE Reachability Notifcation', + PRIMARY KEY (`idmmeidentity`) +) ENGINE=MyISAM AUTO_INCREMENT=46 DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `mmeidentity` +-- + +LOCK TABLES `mmeidentity` WRITE; +/*!40000 ALTER TABLE `mmeidentity` DISABLE KEYS */; +INSERT INTO `mmeidentity` VALUES (2,'mme2.openair4G.eur','openair4G.eur',0),(1,'nano.openair4G.eur','openair4G.eur',0),(5,'abeille.openair4G.eur','openair4G.eur',0),(4,'yang.openair4G.eur','openair4G.eur',0),(3,'mme3.openair4G.eur','openair4G.eur',0),(6,'calisson.openair4G.eur','openair4G.eur',0); +/*!40000 ALTER TABLE `mmeidentity` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `pdn` +-- + +DROP TABLE IF EXISTS `pdn`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `pdn` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `apn` varchar(60) NOT NULL, + `pdn_type` enum('IPv4','IPv6','IPv4v6','IPv4_or_IPv6') NOT NULL DEFAULT 'IPv4', + `pdn_ipv4` varchar(15) DEFAULT '0.0.0.0', + `pdn_ipv6` varchar(45) CHARACTER SET latin1 COLLATE latin1_general_ci DEFAULT '0:0:0:0:0:0:0:0', + `aggregate_ambr_ul` int(10) unsigned DEFAULT '50000000', + `aggregate_ambr_dl` int(10) unsigned DEFAULT '100000000', + `pgw_id` int(11) NOT NULL, + `users_imsi` varchar(15) NOT NULL, + `qci` tinyint(3) unsigned NOT NULL DEFAULT '9', + `priority_level` tinyint(3) unsigned NOT NULL DEFAULT '15', + `pre_emp_cap` enum('ENABLED','DISABLED') DEFAULT 'DISABLED', + `pre_emp_vul` enum('ENABLED','DISABLED') DEFAULT 'DISABLED', + `LIPA-Permissions` enum('LIPA-prohibited','LIPA-only','LIPA-conditional') NOT NULL DEFAULT 'LIPA-only', + PRIMARY KEY (`id`,`pgw_id`,`users_imsi`), + KEY `fk_pdn_pgw1_idx` (`pgw_id`), + KEY `fk_pdn_users1_idx` (`users_imsi`) +) ENGINE=MyISAM AUTO_INCREMENT=60 DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `pdn` +-- + +LOCK TABLES `pdn` WRITE; +/*!40000 ALTER TABLE `pdn` DISABLE KEYS */; +INSERT INTO `pdn` VALUES (1,'oai.ipv4','IPv4','0.0.0.0','0:0:0:0:0:0:0:0',50000000,100000000,3,'208930000000001',9,15,'DISABLED','ENABLED','LIPA-only'),(41,'oai.ipv4','IPv4','0.0.0.0','0:0:0:0:0:0:0:0',50000000,100000000,3,'20834123456789',9,15,'DISABLED','ENABLED','LIPA-only'),(40,'oai.ipv4','IPv4','0.0.0.0','0:0:0:0:0:0:0:0',50000000,100000000,3,'20810000001234',9,15,'DISABLED','ENABLED','LIPA-only'),(42,'oai.ipv4','IPv4','0.0.0.0','0:0:0:0:0:0:0:0',50000000,100000000,3,'31002890832150',9,15,'DISABLED','ENABLED','LIPA-only'),(16,'oai.ipv4','IPv4','0.0.0.0','0:0:0:0:0:0:0:0',50000000,100000000,3,'208950000000002',9,15,'DISABLED','ENABLED','LIPA-only'),(43,'oai.ipv4','IPv4','0.0.0.0','0:0:0:0:0:0:0:0',50000000,100000000,3,'001010123456789',9,15,'DISABLED','ENABLED','LIPA-only'),(2,'oai.ipv4','IPv4','0.0.0.0','0:0:0:0:0:0:0:0',50000000,100000000,3,'208930000000002',9,15,'DISABLED','ENABLED','LIPA-only'),(3,'oai.ipv4','IPv4','0.0.0.0','0:0:0:0:0:0:0:0',50000000,100000000,3,'208930000000003',9,15,'DISABLED','ENABLED','LIPA-only'),(4,'oai.ipv4','IPv4','0.0.0.0','0:0:0:0:0:0:0:0',50000000,100000000,3,'208930000000004',9,15,'DISABLED','ENABLED','LIPA-only'),(5,'oai.ipv4','IPv4','0.0.0.0','0:0:0:0:0:0:0:0',50000000,100000000,3,'208930000000005',9,15,'DISABLED','ENABLED','LIPA-only'),(6,'oai.ipv4','IPv4','0.0.0.0','0:0:0:0:0:0:0:0',50000000,100000000,3,'208930000000006',9,15,'DISABLED','ENABLED','LIPA-only'),(7,'oai.ipv4','IPv4','0.0.0.0','0:0:0:0:0:0:0:0',50000000,100000000,3,'208930000000007',9,15,'DISABLED','ENABLED','LIPA-only'),(8,'oai.ipv4','IPv4','0.0.0.0','0:0:0:0:0:0:0:0',50000000,100000000,3,'208940000000001',9,15,'DISABLED','ENABLED','LIPA-only'),(9,'oai.ipv4','IPv4','0.0.0.0','0:0:0:0:0:0:0:0',50000000,100000000,3,'208940000000002',9,15,'DISABLED','ENABLED','LIPA-only'),(10,'oai.ipv4','IPv4','0.0.0.0','0:0:0:0:0:0:0:0',50000000,100000000,3,'208940000000003',9,15,'DISABLED','ENABLED','LIPA-only'),(11,'oai.ipv4','IPv4','0.0.0.0','0:0:0:0:0:0:0:0',50000000,100000000,3,'208940000000004',9,15,'DISABLED','ENABLED','LIPA-only'),(12,'oai.ipv4','IPv4','0.0.0.0','0:0:0:0:0:0:0:0',50000000,100000000,3,'208940000000005',9,15,'DISABLED','ENABLED','LIPA-only'),(13,'oai.ipv4','IPv4','0.0.0.0','0:0:0:0:0:0:0:0',50000000,100000000,3,'208940000000006',9,15,'DISABLED','ENABLED','LIPA-only'),(14,'oai.ipv4','IPv4','0.0.0.0','0:0:0:0:0:0:0:0',50000000,100000000,3,'208940000000007',9,15,'DISABLED','ENABLED','LIPA-only'),(15,'oai.ipv4','IPv4','0.0.0.0','0:0:0:0:0:0:0:0',50000000,100000000,3,'208950000000001',9,15,'DISABLED','ENABLED','LIPA-only'),(17,'oai.ipv4','IPv4','0.0.0.0','0:0:0:0:0:0:0:0',50000000,100000000,3,'208950000000003',9,15,'DISABLED','ENABLED','LIPA-only'),(18,'oai.ipv4','IPv4','0.0.0.0','0:0:0:0:0:0:0:0',50000000,100000000,3,'208950000000004',9,15,'DISABLED','ENABLED','LIPA-only'),(19,'oai.ipv4','IPv4','0.0.0.0','0:0:0:0:0:0:0:0',50000000,100000000,3,'208950000000005',9,15,'DISABLED','ENABLED','LIPA-only'),(20,'oai.ipv4','IPv4','0.0.0.0','0:0:0:0:0:0:0:0',50000000,100000000,3,'208950000000006',9,15,'DISABLED','ENABLED','LIPA-only'),(21,'oai.ipv4','IPv4','0.0.0.0','0:0:0:0:0:0:0:0',50000000,100000000,3,'208950000000007',9,15,'DISABLED','ENABLED','LIPA-only'),(22,'oai.ipv4','IPv4','0.0.0.0','0:0:0:0:0:0:0:0',50000000,100000000,3,'208920100001100',9,15,'DISABLED','ENABLED','LIPA-only'),(23,'oai.ipv4','IPv4','0.0.0.0','0:0:0:0:0:0:0:0',50000000,100000000,3,'208920100001101',9,15,'DISABLED','ENABLED','LIPA-only'),(24,'oai.ipv4','IPv4','0.0.0.0','0:0:0:0:0:0:0:0',50000000,100000000,3,'208920100001102',9,15,'DISABLED','ENABLED','LIPA-only'),(25,'oai.ipv4','IPv4','0.0.0.0','0:0:0:0:0:0:0:0',50000000,100000000,3,'208920100001103',9,15,'DISABLED','ENABLED','LIPA-only'),(26,'oai.ipv4','IPv4','0.0.0.0','0:0:0:0:0:0:0:0',50000000,100000000,3,'208920100001104',9,15,'DISABLED','ENABLED','LIPA-only'),(27,'oai.ipv4','IPv4','0.0.0.0','0:0:0:0:0:0:0:0',50000000,100000000,3,'208920100001105',9,15,'DISABLED','ENABLED','LIPA-only'),(28,'oai.ipv4','IPv4','0.0.0.0','0:0:0:0:0:0:0:0',50000000,100000000,3,'208920100001106',9,15,'DISABLED','ENABLED','LIPA-only'),(29,'oai.ipv4','IPv4','0.0.0.0','0:0:0:0:0:0:0:0',50000000,100000000,3,'208920100001107',9,15,'DISABLED','ENABLED','LIPA-only'),(30,'oai.ipv4','IPv4','0.0.0.0','0:0:0:0:0:0:0:0',50000000,100000000,3,'208920100001108',9,15,'DISABLED','ENABLED','LIPA-only'),(31,'oai.ipv4','IPv4','0.0.0.0','0:0:0:0:0:0:0:0',50000000,100000000,3,'208920100001109',9,15,'DISABLED','ENABLED','LIPA-only'),(32,'oai.ipv4','IPv4','0.0.0.0','0:0:0:0:0:0:0:0',50000000,100000000,3,'208920100001110',9,15,'DISABLED','ENABLED','LIPA-only'),(33,'oai.ipv4','IPv4','0.0.0.0','0:0:0:0:0:0:0:0',50000000,100000000,3,'208930100001111',9,15,'DISABLED','ENABLED','LIPA-only'),(34,'oai.ipv4','IPv4','0.0.0.0','0:0:0:0:0:0:0:0',50000000,100000000,3,'208930100001112',9,15,'DISABLED','ENABLED','LIPA-only'),(35,'oai.ipv4','IPv4','0.0.0.0','0:0:0:0:0:0:0:0',50000000,100000000,3,'208930100001113',9,15,'DISABLED','ENABLED','LIPA-only'),(44,'operator','IPv4','0.0.0.0','0:0:0:0:0:0:0:0',50000000,100000000,3,'208930100001113',9,15,'DISABLED','ENABLED','LIPA-only'),(45,'operator','IPv4','0.0.0.0','0:0:0:0:0:0:0:0',50000000,100000000,3,'208930100001112',9,15,'DISABLED','ENABLED','LIPA-only'),(46,'operator','IPv4','0.0.0.0','0:0:0:0:0:0:0:0',50000000,100000000,3,'208930100001111',9,15,'DISABLED','ENABLED','LIPA-only'),(47,'operator','IPv4','0.0.0.0','0:0:0:0:0:0:0:0',50000000,100000000,3,'208950000000002',9,15,'DISABLED','ENABLED','LIPA-only'),(48,'oai.ipv4','IPv4','0.0.0.0','0:0:0:0:0:0:0:0',50000000,100000000,3,'208950000000008',9,15,'DISABLED','ENABLED','LIPA-only'),(49,'oai.ipv4','IPv4','0.0.0.0','0:0:0:0:0:0:0:0',50000000,100000000,3,'208950000000009',9,15,'DISABLED','ENABLED','LIPA-only'),(50,'oai.ipv4','IPv4','0.0.0.0','0:0:0:0:0:0:0:0',50000000,100000000,3,'208950000000010',9,15,'DISABLED','ENABLED','LIPA-only'),(51,'oai.ipv4','IPv4','0.0.0.0','0:0:0:0:0:0:0:0',50000000,100000000,3,'208950000000011',9,15,'DISABLED','ENABLED','LIPA-only'),(52,'oai.ipv4','IPv4','0.0.0.0','0:0:0:0:0:0:0:0',50000000,100000000,3,'208950000000012',9,15,'DISABLED','ENABLED','LIPA-only'),(53,'oai.ipv4','IPv4','0.0.0.0','0:0:0:0:0:0:0:0',50000000,100000000,3,'208950000000013',9,15,'DISABLED','ENABLED','LIPA-only'),(54,'oai.ipv4','IPv4','0.0.0.0','0:0:0:0:0:0:0:0',50000000,100000000,3,'208950000000014',9,15,'DISABLED','ENABLED','LIPA-only'),(55,'oai.ipv4','IPv4','0.0.0.0','0:0:0:0:0:0:0:0',50000000,100000000,3,'208950000000015',9,15,'DISABLED','ENABLED','LIPA-only'),(56,'oai.ipv4','IPv4','0.0.0.0','0:0:0:0:0:0:0:0',50000000,100000000,3,'208920100001118',9,15,'DISABLED','ENABLED','LIPA-only'),(57,'oai.ipv4','IPv4','0.0.0.0','0:0:0:0:0:0:0:0',50000000,100000000,3,'208920100001121',9,15,'DISABLED','ENABLED','LIPA-only'),(58,'oai.ipv4','IPv4','0.0.0.0','0:0:0:0:0:0:0:0',50000000,100000000,3,'208920100001120',9,15,'DISABLED','ENABLED','LIPA-only'),(59,'oai.ipv4','IPv4','0.0.0.0','0:0:0:0:0:0:0:0',50000000,100000000,3,'208920100001119',9,15,'DISABLED','ENABLED','LIPA-only'); +/*!40000 ALTER TABLE `pdn` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `pgw` +-- + +DROP TABLE IF EXISTS `pgw`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `pgw` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `ipv4` varchar(15) NOT NULL, + `ipv6` varchar(39) NOT NULL, + PRIMARY KEY (`id`), + UNIQUE KEY `ipv4` (`ipv4`), + UNIQUE KEY `ipv6` (`ipv6`) +) ENGINE=MyISAM AUTO_INCREMENT=4 DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `pgw` +-- + +LOCK TABLES `pgw` WRITE; +/*!40000 ALTER TABLE `pgw` DISABLE KEYS */; +INSERT INTO `pgw` VALUES (1,'127.0.0.1','0:0:0:0:0:0:0:1'),(2,'192.168.56.101',''),(3,'10.0.0.2','0'); +/*!40000 ALTER TABLE `pgw` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `terminal-info` +-- + +DROP TABLE IF EXISTS `terminal-info`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `terminal-info` ( + `imei` varchar(15) NOT NULL, + `sv` varchar(2) NOT NULL, + UNIQUE KEY `imei` (`imei`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `terminal-info` +-- + +LOCK TABLES `terminal-info` WRITE; +/*!40000 ALTER TABLE `terminal-info` DISABLE KEYS */; +/*!40000 ALTER TABLE `terminal-info` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `users` +-- + +DROP TABLE IF EXISTS `users`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `users` ( + `imsi` varchar(15) NOT NULL COMMENT 'IMSI is the main reference key.', + `msisdn` varchar(46) DEFAULT NULL COMMENT 'The basic MSISDN of the UE (Presence of MSISDN is optional).', + `imei` varchar(15) DEFAULT NULL COMMENT 'International Mobile Equipment Identity', + `imei_sv` varchar(2) DEFAULT NULL COMMENT 'International Mobile Equipment Identity Software Version Number', + `ms_ps_status` enum('PURGED','NOT_PURGED') DEFAULT 'PURGED' COMMENT 'Indicates that ESM and EMM status are purged from MME', + `rau_tau_timer` int(10) unsigned DEFAULT '120', + `ue_ambr_ul` bigint(20) unsigned DEFAULT '50000000' COMMENT 'The Maximum Aggregated uplink MBRs to be shared across all Non-GBR bearers according to the subscription of the user.', + `ue_ambr_dl` bigint(20) unsigned DEFAULT '100000000' COMMENT 'The Maximum Aggregated downlink MBRs to be shared across all Non-GBR bearers according to the subscription of the user.', + `access_restriction` int(10) unsigned DEFAULT '60' COMMENT 'Indicates the access restriction subscription information. 3GPP TS.29272 #7.3.31', + `mme_cap` int(10) unsigned zerofill DEFAULT NULL COMMENT 'Indicates the capabilities of the MME with respect to core functionality e.g. regional access restrictions.', + `mmeidentity_idmmeidentity` int(11) NOT NULL DEFAULT '0', + `key` varbinary(16) NOT NULL DEFAULT '0' COMMENT 'UE security key', + `RFSP-Index` smallint(5) unsigned NOT NULL DEFAULT '1' COMMENT 'An index to specific RRM configuration in the E-UTRAN. Possible values from 1 to 256', + `urrp_mme` tinyint(1) NOT NULL DEFAULT '0' COMMENT 'UE Reachability Request Parameter indicating that UE activity notification from MME has been requested by the HSS.', + `sqn` bigint(20) unsigned zerofill NOT NULL, + `rand` varbinary(16) NOT NULL, + `OPc` varbinary(16) DEFAULT NULL COMMENT 'Can be computed by HSS', + PRIMARY KEY (`imsi`,`mmeidentity_idmmeidentity`), + KEY `fk_users_mmeidentity_idx1` (`mmeidentity_idmmeidentity`) +) ENGINE=MyISAM DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `users` +-- + +LOCK TABLES `users` WRITE; +/*!40000 ALTER TABLE `users` DISABLE KEYS */; +INSERT INTO `users` VALUES ('20834123456789','380561234567','35609204079300',NULL,'PURGED',50,40000000,100000000,47,0000000000,1,'+�E��ų\0�,IH��H',0,0,00000000000000000096,'Px�X \Z1��x��','^��K�����FeU���'),('20810000001234','33611123456','35609204079299',NULL,'PURGED',120,40000000,100000000,47,0000000000,1,'��G?/�Д���� |hb',1,0,00000281454575616225,'\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0','�4�s@���z��~�'),('31002890832150','33638060059','35611302209414',NULL,'PURGED',120,40000000,100000000,47,0000000000,1,'��G?/�Д���� |hb',1,0,00000000000000012416,'`�F�݆��D��ϛ���','�4�s@���z��~�'),('001010123456789','33600101789','35609204079298',NULL,'PURGED',120,50000000,100000000,47,0000000000,1,'\0 \n \r',1,0,00000000000000000351,'\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0','L�*\\�����^��]� '),('208930000000001','33638030001','35609204079301',NULL,'PURGED',120,50000000,100000000,47,0000000000,1,'��G?/�Д���� |hb',1,0,00000000000000006103,'��wq��gzW�Ё��Z]','�4�s@���z��~�'),('208950000000002','33638050002','35609204079502',NULL,'PURGED',120,50000000,100000000,47,0000000000,1,'��G?/�Д���� |hb',1,0,00000000000000020471,'\0 \n \r','�4�s@���z��~�'),('208950000000003','33638050003','35609204079503',NULL,'PURGED',120,50000000,100000000,47,0000000000,1,'��G?/�Д���� |hb',1,0,00000000000000012343,'\0 \n \r','�4�s@���z��~�'),('208950000000004','33638050004','35609204079504',NULL,'PURGED',120,50000000,100000000,47,0000000000,1,'��G?/�Д���� |hb',1,0,00000000000000012215,'56f0261d9d051063','�4�s@���z��~�'),('208950000000005','33638050005','35609204079505',NULL,'PURGED',120,50000000,100000000,47,0000000000,1,'��G?/�Д���� |hb',1,0,00000000000000012215,'56f0261d9d051063','�4�s@���z��~�'),('208950000000001','33638050001','35609204079501',NULL,'PURGED',120,50000000,100000000,47,0000000000,1,'��G?/�Д���� |hb',1,0,00000000000000006103,'��wq��gzW�Ё��Z]','�4�s@���z��~�'),('208950000000006','33638050006','35609204079506',NULL,'PURGED',120,50000000,100000000,47,0000000000,1,'��G?/�Д���� |hb',1,0,00000000000000012215,'56f0261d9d051063','�4�s@���z��~�'),('208950000000007','33638050007','35609204079507',NULL,'PURGED',120,50000000,100000000,47,0000000000,1,'��G?/�Д���� |hb',1,0,00000000000000012215,'56f0261d9d051063','�4�s@���z��~�'),('208930000000002','33638030002','35609204079302',NULL,'PURGED',120,50000000,100000000,47,0000000000,1,'��G?/�Д���� |hb',1,0,00000000000000006103,'��wq��gzW�Ё��Z]','�4�s@���z��~�'),('208930000000003','33638030003','35609204079303',NULL,'PURGED',120,50000000,100000000,47,0000000000,1,'��G?/�Д���� |hb',1,0,00000000000000006103,'��wq��gzW�Ё��Z]','�4�s@���z��~�'),('208930000000004','33638030004','35609204079304',NULL,'PURGED',120,50000000,100000000,47,0000000000,1,'��G?/�Д���� |hb',1,0,00000000000000006103,'��wq��gzW�Ё��Z]','�4�s@���z��~�'),('208930000000005','33638030005','35609204079305',NULL,'PURGED',120,50000000,100000000,47,0000000000,1,'��G?/�Д���� |hb',1,0,00000000000000006103,'��wq��gzW�Ё��Z]','�4�s@���z��~�'),('208930000000006','33638030006','35609204079306',NULL,'PURGED',120,50000000,100000000,47,0000000000,1,'��G?/�Д���� |hb',1,0,00000000000000006103,'��wq��gzW�Ё��Z]','�4�s@���z��~�'),('208930000000007','33638030007','35609204079307',NULL,'PURGED',120,50000000,100000000,47,0000000000,1,'��G?/�Д���� |hb',1,0,00000000000000006103,'��wq��gzW�Ё��Z]','�4�s@���z��~�'),('208940000000007','33638040007','35609204079407',NULL,'PURGED',120,50000000,100000000,47,0000000000,1,'��G?/�Д���� |hb',1,0,00000000000000006103,'��wq��gzW�Ё��Z]','�4�s@���z��~�'),('208940000000006','33638040006','35609204079406',NULL,'PURGED',120,50000000,100000000,47,0000000000,1,'��G?/�Д���� |hb',1,0,00000000000000006103,'��wq��gzW�Ё��Z]','�4�s@���z��~�'),('208940000000005','33638040005','35609204079405',NULL,'PURGED',120,50000000,100000000,47,0000000000,1,'��G?/�Д���� |hb',1,0,00000000000000006103,'��wq��gzW�Ё��Z]','�4�s@���z��~�'),('208940000000004','33638040004','35609204079404',NULL,'PURGED',120,50000000,100000000,47,0000000000,1,'��G?/�Д���� |hb',1,0,00000000000000006103,'��wq��gzW�Ё��Z]','�4�s@���z��~�'),('208940000000003','33638040003','35609204079403',NULL,'PURGED',120,50000000,100000000,47,0000000000,1,'��G?/�Д���� |hb',1,0,00000000000000006103,'��wq��gzW�Ё��Z]','�4�s@���z��~�'),('208940000000002','33638040002','35609204079402',NULL,'PURGED',120,50000000,100000000,47,0000000000,1,'��G?/�Д���� |hb',1,0,00000000000000006103,'��wq��gzW�Ё��Z]','�4�s@���z��~�'),('208940000000001','33638040001','35609204079401',NULL,'PURGED',120,50000000,100000000,47,0000000000,1,'��G?/�Д���� |hb',1,0,00000000000000006103,'��wq��gzW�Ё��Z]','�4�s@���z��~�'),('208920100001100','33638020001','35609204079201',NULL,'PURGED',120,50000000,100000000,47,0000000000,1,'��G?/�Д���� |hb',1,0,00000000000000006103,'ebd07771ace8677a','�4�s@���z��~�'),('208920100001101','33638020001','35609204079201',NULL,'NOT_PURGED',120,50000000,100000000,47,0000000000,1,'��k��p~Љu{�K�',1,0,00000281044204937234,'\0 \n \r','�$I6;��+f�k�u�|�'),('208920100001102','33638020002','35609204079202',NULL,'PURGED',120,50000000,100000000,47,0000000000,1,'��G?/�Д���� |hb',1,0,00000000000000006103,'ebd07771ace8677a','�4�s@���z��~�'),('208920100001103','33638020003','35609204079203',NULL,'PURGED',120,50000000,100000000,47,0000000000,1,'��G?/�Д���� |hb',1,0,00000000000000006103,'ebd07771ace8677a','�4�s@���z��~�'),('208920100001104','33638020004','35609204079204',NULL,'PURGED',120,50000000,100000000,47,0000000000,1,'��G?/�Д���� |hb',1,0,00000000000000006103,'ebd07771ace8677a','�4�s@���z��~�'),('208920100001105','33638020005','35609204079205',NULL,'PURGED',120,50000000,100000000,47,0000000000,1,'��G?/�Д���� |hb',1,0,00000000000000006103,'ebd07771ace8677a','�4�s@���z��~�'),('208920100001106','33638020006','35609204079206',NULL,'PURGED',120,50000000,100000000,47,0000000000,1,'��k��p~Љu{�K�',1,0,00000000000000006103,'ebd07771ace8677a','�$I6;��+f�k�u�|�'),('208920100001107','33638020007','35609204079207',NULL,'PURGED',120,50000000,100000000,47,0000000000,1,'��G?/�Д���� |hb',1,0,00000000000000006103,'ebd07771ace8677a','�4�s@���z��~�'),('208920100001108','33638020008','35609204079208',NULL,'PURGED',120,50000000,100000000,47,0000000000,1,'��G?/�Д���� |hb',1,0,00000000000000006103,'ebd07771ace8677a','�4�s@���z��~�'),('208920100001109','33638020009','35609204079209',NULL,'PURGED',120,50000000,100000000,47,0000000000,1,'��G?/�Д���� |hb',1,0,00000000000000006103,'ebd07771ace8677a','�4�s@���z��~�'),('208920100001110','33638020010','35609204079210',NULL,'PURGED',120,50000000,100000000,47,0000000000,1,'��G?/�Д���� |hb',1,0,00000000000000006103,'ebd07771ace8677a','�4�s@���z��~�'),('208930100001111','33638030011','35609304079211',NULL,'PURGED',120,50000000,100000000,47,0000000000,1,'��G?/�Д���� |hb',1,0,00000000000000006103,'ebd07771ace8677a','�4�s@���z��~�'),('208930100001112','33638030012','35609304079212',NULL,'PURGED',120,50000000,100000000,47,0000000000,1,'��G?/�Д���� |hb',1,0,00000000000000006103,'ebd07771ace8677a','�4�s@���z��~�'),('208930100001113','33638030013','35609304079213',NULL,'PURGED',120,50000000,100000000,47,0000000000,1,'��G?/�Д���� |hb',1,0,00000000000000006263,'�SNܒ�Iv��e�6','�4�s@���z��~�'),('208950000000008','33638050008','35609204079508',NULL,'PURGED',120,50000000,100000000,47,0000000000,1,'��G?/�Д���� |hb',1,0,00000000000000012215,'56f0261d9d051063','�4�s@���z��~�'),('208950000000009','33638050009','35609204079509',NULL,'PURGED',120,50000000,100000000,47,0000000000,1,'��G?/�Д���� |hb',1,0,00000000000000012215,'56f0261d9d051063','�4�s@���z��~�'),('208950000000010','33638050010','35609204079510',NULL,'PURGED',120,50000000,100000000,47,0000000000,1,'��G?/�Д���� |hb',1,0,00000000000000012215,'56f0261d9d051063','�4�s@���z��~�'),('208950000000011','33638050011','35609204079511',NULL,'PURGED',120,50000000,100000000,47,0000000000,1,'��G?/�Д���� |hb',1,0,00000000000000012215,'56f0261d9d051063','�4�s@���z��~�'),('208950000000012','33638050012','35609204079512',NULL,'PURGED',120,50000000,100000000,47,0000000000,1,'��G?/�Д���� |hb',1,0,00000000000000012215,'56f0261d9d051063','�4�s@���z��~�'),('208950000000013','33638050013','35609204079513',NULL,'PURGED',120,50000000,100000000,47,0000000000,1,'��G?/�Д���� |hb',1,0,00000000000000012215,'56f0261d9d051063','�4�s@���z��~�'),('208950000000014','33638050014','35609204079514',NULL,'PURGED',120,50000000,100000000,47,0000000000,1,'��G?/�Д���� |hb',1,0,00000000000000012215,'56f0261d9d051063','�4�s@���z��~�'),('208950000000015','33638050015','35609204079515',NULL,'PURGED',120,50000000,100000000,47,0000000000,1,'��G?/�Д���� |hb',1,0,00000000000000000000,'3536663032363164','�4�s@���z��~�'),('208920100001118','33638020010','35609204079210',NULL,'NOT_PURGED',120,50000000,100000000,47,0000000000,1,'��k��p~Љu{�K�',1,0,00000281044204934762,'~?03�u-%�ey�y�','�$I6;��+f�k�u�|�'),('208920100001121','33638020010','35609204079210',NULL,'NOT_PURGED',120,50000000,100000000,47,0000000000,1,'��k��p~Љu{�K�',1,0,00000281044204935293,'&��@xg�]���\n��Vp','�$I6;��+f�k�u�|�'),('208920100001119','33638020010','35609204079210',NULL,'NOT_PURGED',120,50000000,100000000,47,0000000000,1,'��k��p~Љu{�K�',1,0,00000281044204935293,'269482407867805d','�$I6;��+f�k�u�|�'),('208920100001120','33638020010','35609204079210',NULL,'NOT_PURGED',120,50000000,100000000,47,0000000000,1,'��k��p~Љu{�K�',1,0,00000281044204935293,'3236393438323430','�$I6;��+f�k�u�|�'); +INSERT INTO `users` VALUES ('208990100001100','1','55000000000000',NULL,'PURGED',50,40000000,100000000,47,0000000000,1,0xfec86ba6eb707ed08905757b1bb44b8f,0,0,0x40,'ebd07771ace8677a',0xc42449363bbad02b66d16bc975d77cc1); +INSERT INTO `users` VALUES ('208950000000031','380561234567','55000000000001',NULL,'PURGED',50,40000000,100000000,47,0000000000,1,0x0C0A34601D4F07677303652C0462535B,0,0,0x40,'ebd07771ace8677a',0x63bfa50ee6523365ff14c1f45f88737d); +INSERT INTO `users` VALUES ('208950000000032','380561234567','55000000000001',NULL,'PURGED',50,40000000,100000000,47,0000000000,1,0x0C0A34601D4F07677303652C0462535B,0,0,0x40,'ebd07771ace8677a',0x63bfa50ee6523365ff14c1f45f88737d); +INSERT INTO `users` VALUES ('208950000000033','380561234567','55000000000001',NULL,'PURGED',50,40000000,100000000,47,0000000000,1,0x0C0A34601D4F07677303652C0462535B,0,0,0x40,'ebd07771ace8677a',0x63bfa50ee6523365ff14c1f45f88737d); +INSERT INTO `users` VALUES ('208950000000034','380561234567','55000000000001',NULL,'PURGED',50,40000000,100000000,47,0000000000,1,0x0C0A34601D4F07677303652C0462535B,0,0,0x40,'ebd07771ace8677a',0x63bfa50ee6523365ff14c1f45f88737d); +INSERT INTO `users` VALUES ('208950000000035','380561234567','55000000000001',NULL,'PURGED',50,40000000,100000000,47,0000000000,1,0x0C0A34601D4F07677303652C0462535B,0,0,0x40,'ebd07771ace8677a',0x63bfa50ee6523365ff14c1f45f88737d); +INSERT INTO `users` VALUES ('208950000000036','380561234567','55000000000001',NULL,'PURGED',50,40000000,100000000,47,0000000000,1,0x0C0A34601D4F07677303652C0462535B,0,0,0x40,'ebd07771ace8677a',0x63bfa50ee6523365ff14c1f45f88737d); +INSERT INTO `users` VALUES ('208950000000037','380561234567','55000000000001',NULL,'PURGED',50,40000000,100000000,47,0000000000,1,0x0C0A34601D4F07677303652C0462535B,0,0,0x40,'ebd07771ace8677a',0x63bfa50ee6523365ff14c1f45f88737d); +INSERT INTO `users` VALUES ('208950000000038','380561234567','55000000000001',NULL,'PURGED',50,40000000,100000000,47,0000000000,1,0x0C0A34601D4F07677303652C0462535B,0,0,0x40,'ebd07771ace8677a',0x63bfa50ee6523365ff14c1f45f88737d); +INSERT INTO `users` VALUES ('208950000000039','380561234567','55000000000001',NULL,'PURGED',50,40000000,100000000,47,0000000000,1,0x0C0A34601D4F07677303652C0462535B,0,0,0x40,'ebd07771ace8677a',0x63bfa50ee6523365ff14c1f45f88737d); +INSERT INTO `users` VALUES ('208950000000040','380561234567','55000000000001',NULL,'PURGED',50,40000000,100000000,47,0000000000,1,0x0C0A34601D4F07677303652C0462535B,0,0,0x40,'ebd07771ace8677a',0x63bfa50ee6523365ff14c1f45f88737d); +/*!40000 ALTER TABLE `users` ENABLE KEYS */; +UNLOCK TABLES; +/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */; + +/*!40101 SET SQL_MODE=@OLD_SQL_MODE */; +/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */; +/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */; +/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; +/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; +/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; +/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; + +-- Dump completed on 2016-06-28 11:41:40 diff --git a/ci-scripts/yaml_files/5g_rfsimulator/smf-healthcheck.sh b/ci-scripts/yaml_files/5g_rfsimulator/smf-healthcheck.sh new file mode 100755 index 0000000000..d9ff7608e8 --- /dev/null +++ b/ci-scripts/yaml_files/5g_rfsimulator/smf-healthcheck.sh @@ -0,0 +1,21 @@ +#!/bin/bash +set -eo pipefail + +STATUS=0 +SMF_IP_SBI_INTERFACE=$(ifconfig $SMF_INTERFACE_NAME_FOR_SBI | grep inet | awk {'print $2'}) +SMF_SBI_PORT_STATUS=$(netstat -tnpl | grep -o "$SMF_IP_SBI_INTERFACE:$SMF_INTERFACE_PORT_FOR_SBI") + +#Check if entrypoint properly configured the conf file and no parameter is unset(optional) +#NB_UNREPLACED_AT=`cat /openair-smf/etc/*.conf | grep -v contact@openairinterface.org | grep -c @ || true` + +#if [ $NB_UNREPLACED_AT -ne 0 ]; then +# STATUS=-1 +# echo "Healthcheck error: UNHEALTHY configuration file is not configured properly" +#fi +# +if [[ -z $SMF_SBI_PORT_STATUS ]]; then + STATUS=-1 + echo "Healthcheck error: UNHEALTHY SBI TCP/HTTP port $SMF_INTERFACE_PORT_FOR_SBI is not listening." +fi + +exit $STATUS diff --git a/ci-scripts/yaml_files/5g_rfsimulator/spgwu-healthcheck.sh b/ci-scripts/yaml_files/5g_rfsimulator/spgwu-healthcheck.sh new file mode 100755 index 0000000000..0e3b67ee7e --- /dev/null +++ b/ci-scripts/yaml_files/5g_rfsimulator/spgwu-healthcheck.sh @@ -0,0 +1,28 @@ +#!/bin/bash +set -eo pipefail + +STATUS=0 +SGW_PORT_FOR_S1U_S12_S4_UP=2152 +SGW_PORT_FOR_SX=8805 +SGW_IP_S1U_INTERFACE=$(ifconfig $SGW_INTERFACE_NAME_FOR_S1U_S12_S4_UP | grep inet | awk {'print $2'}) +SGW_IP_SX_INTERFACE=$(ifconfig $SGW_INTERFACE_NAME_FOR_SX | grep inet | awk {'print $2'}) +S1U_S12_S4_UP_PORT_STATUS=$(netstat -unpl | grep -o "$SGW_IP_S1U_INTERFACE:$SGW_PORT_FOR_S1U_S12_S4_UP") +SX_PORT_STATUS=$(netstat -unpl | grep -o "$SGW_IP_SX_INTERFACE:$SGW_PORT_FOR_SX") +#Check if entrypoint properly configured the conf file and no parameter is unset (optional) +NB_UNREPLACED_AT=`cat /openair-spgwu/etc/*.conf | grep -v contact@openairinterface.org | grep -c @ || true` +if [ $NB_UNREPLACED_AT -ne 0 ]; then + STATUS=1 + echo "Healthcheck error: UNHEALTHY configuration file is not configured properly" +fi + +if [[ -z $S1U_S12_S4_UP_PORT_STATUS ]]; then + STATUS=1 + echo "Healthcheck error: UNHEALTHY S1U port $SGW_PORT_FOR_S1U_S12_S4_UP is not listening." +fi + +if [[ -z $SX_PORT_STATUS ]]; then + STATUS=1 + echo "Healthcheck error: UNHEALTHY SX port $SGW_PORT_FOR_SX is not listening." +fi + +exit $STATUS \ No newline at end of file diff --git a/docker/Dockerfile.gNB.rhel8.2 b/docker/Dockerfile.gNB.rhel8.2 index a81de04cbe..57a59a1f21 100644 --- a/docker/Dockerfile.gNB.rhel8.2 +++ b/docker/Dockerfile.gNB.rhel8.2 @@ -25,7 +25,7 @@ # #--------------------------------------------------------------------- -FROM ran-build:latest AS gnb-build +FROM ran-build:latest AS gnb-build RUN rm -Rf /oai-ran WORKDIR /oai-ran @@ -113,4 +113,4 @@ WORKDIR /opt/oai-gnb #EXPOSE 50001/udp # IF5 / ECPRI (data) ENTRYPOINT ["/opt/oai-gnb/bin/entrypoint.sh"] -CMD ["/opt/oai-gnb/bin/nr-softmodem", "-O", "/opt/oai-gnb/etc/gnb.conf"] +CMD ["/opt/oai-gnb/bin/nr-softmodem.Rel15", "-O", "/opt/oai-gnb/etc/gnb.conf"] diff --git a/docker/Dockerfile.gNB.ubuntu18 b/docker/Dockerfile.gNB.ubuntu18 index 2fb569b74b..b5aff9ff52 100644 --- a/docker/Dockerfile.gNB.ubuntu18 +++ b/docker/Dockerfile.gNB.ubuntu18 @@ -25,7 +25,7 @@ # #--------------------------------------------------------------------- -FROM ran-build:latest AS gnb-build +FROM ran-build:latest AS gnb-build RUN rm -Rf /oai-ran WORKDIR /oai-ran @@ -110,4 +110,4 @@ WORKDIR /opt/oai-gnb #EXPOSE 50001/udp # IF5 / ECPRI (data) ENTRYPOINT ["/opt/oai-gnb/bin/entrypoint.sh"] -CMD ["/opt/oai-gnb/bin/nr-softmodem", "-O", "/opt/oai-gnb/etc/gnb.conf"] +CMD ["/opt/oai-gnb/bin/nr-softmodem.Rel15", "-O", "/opt/oai-gnb/etc/gnb.conf"] diff --git a/docker/Dockerfile.nrUE.rhel8.2 b/docker/Dockerfile.nrUE.rhel8.2 index c8bea16801..f036c11483 100644 --- a/docker/Dockerfile.nrUE.rhel8.2 +++ b/docker/Dockerfile.nrUE.rhel8.2 @@ -37,19 +37,15 @@ RUN /bin/sh oaienv && \ mkdir -p log && \ ./build_oai --nrUE --ninja -w USRP --verbose-ci -# debug -#RUN ldconfig -v -#RUN ldd /oai-ran/targets/bin/nr-uesoftmodem.Rel15 -#RUN ls -lst /oai-ran/targets/bin -#RUN ls -lst /oai-ran/cmake_targets/ran_build/build/*.so - #start from scratch for target executable FROM registry.access.redhat.com/ubi8/ubi:latest as oai-nr-ue +ENV TZ=Europe/Paris RUN yum update -y && \ yum install -y --enablerepo="ubi-8-codeready-builder" \ lksctp-tools \ procps-ng \ + tzdata \ nettle \ net-tools \ iputils \ @@ -62,6 +58,10 @@ RUN yum update -y && \ WORKDIR /opt/oai-nr-ue/bin COPY --from=nr-ue-build /oai-ran/targets/bin/nr-uesoftmodem.Rel15 . +COPY --from=nr-ue-build /oai-ran/docker/scripts/nr_ue_entrypoint.sh entrypoint.sh + +WORKDIR /opt/oai-nr-ue/etc +COPY --from=nr-ue-build /oai-ran/ci-scripts/conf_files/nr-ue-sim.conf . WORKDIR /usr/local/lib/ COPY --from=nr-ue-build /oai-ran/targets/bin/liboai_eth_transpro.so.Rel15 . @@ -99,24 +99,11 @@ COPY --from=nr-ue-build /lib64/libboost_timer.so.1.66.0 /lib64 COPY --from=nr-ue-build /usr/local/lib64/libuhd.so.4.0.0 /usr/local/lib64 RUN ldconfig -#RUN ldd /opt/oai-nr-ue/bin/nr-uesoftmodem.Rel15 -#RUN ldd /usr/local/lib/liboai_eth_transpro.so.Rel15 -#RUN ldd /usr/local/lib/libtcp_bridge_oai.so.Rel15 -#RUN ldd /usr/local/lib/librfsimulator.so.Rel15 -#RUN ldd /usr/local/lib/liboai_usrpdevif.so.Rel15 -#RUN ldd /usr/local/lib/libcoding.so -#RUN ldd /usr/local/lib/libparams_libconfig.so -#RUN ldd /usr/local/lib/libdfts.so -#RUN ldd /usr/local/lib/libldpc.so -#RUN ldd /usr/local/lib/libldpc_optim.so -#RUN ldd /usr/local/lib/libldpc_optim8seg.so -#RUN ldd /usr/local/lib/libldpc_orig.so # Copy the relevant configuration files for eNB WORKDIR /opt/oai-nr-ue/etc COPY --from=nr-ue-build /oai-ran/ci-scripts/conf_files/ue.* . WORKDIR /opt/oai-nr-ue -#CMD ["/opt/oai-nr-ue/bin/nr-uesoftmodem", "-O", "/opt/oai-nr-ue/etc/enb.conf"] -#ENTRYPOINT ["/opt/oai-nr-ue/bin/entrypoint.sh"] -CMD ["sleep", "infinity"] +CMD ["/opt/oai-nr-ue/bin/nr-uesoftmodem.Rel15", "-O", "/opt/oai-nr-ue/etc/nr-ue-sim.conf"] +ENTRYPOINT ["/opt/oai-nr-ue/bin/entrypoint.sh"] diff --git a/docker/Dockerfile.nrUE.ubuntu18 b/docker/Dockerfile.nrUE.ubuntu18 index ee2160d579..fc30af7286 100644 --- a/docker/Dockerfile.nrUE.ubuntu18 +++ b/docker/Dockerfile.nrUE.ubuntu18 @@ -25,7 +25,7 @@ # #--------------------------------------------------------------------- -FROM ran-build:latest AS nr-ue-build +FROM ran-build:latest AS nr-ue-build RUN rm -Rf /oai-ran WORKDIR /oai-ran @@ -37,17 +37,10 @@ RUN /bin/sh oaienv && \ mkdir -p log && \ ./build_oai --nrUE --ninja -w USRP --verbose-ci -# debug -#RUN ldconfig -v -#RUN ldd /oai-ran/targets/bin/nr-uesoftmodem.Rel15 -#RUN ls -lst /oai-ran/targets/bin -#RUN ls -lst /oai-ran/cmake_targets/ran_build/build/*.so - #start from scratch for target executable FROM ubuntu:bionic as oai-nr-ue ENV DEBIAN_FRONTEND=noninteractive -ENV TZ=Europe -RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone +ENV TZ=Europe/Paris RUN apt-get update && \ DEBIAN_FRONTEND=noninteractive apt-get upgrade --yes && \ @@ -55,6 +48,7 @@ RUN apt-get update && \ software-properties-common \ libsctp1 \ procps \ + tzdata \ libnettle6 \ liblapacke \ libatlas3-base \ @@ -63,6 +57,7 @@ RUN apt-get update && \ net-tools \ iputils-ping \ iproute2 \ + iperf \ libyaml-0-2 && \ # Install UHD driver from ettus ppa # At time of writing, it is 3.14 @@ -77,6 +72,10 @@ RUN apt-get update && \ WORKDIR /opt/oai-nr-ue/bin COPY --from=nr-ue-build /oai-ran/targets/bin/nr-uesoftmodem.Rel15 . +COPY --from=nr-ue-build /oai-ran/docker/scripts/nr_ue_entrypoint.sh entrypoint.sh + +WORKDIR /opt/oai-nr-ue/etc +COPY --from=nr-ue-build /oai-ran/ci-scripts/conf_files/nr-ue-sim.conf . WORKDIR /usr/local/lib/ COPY --from=nr-ue-build /oai-ran/targets/bin/liboai_eth_transpro.so.Rel15 . @@ -97,25 +96,7 @@ RUN /bin/bash -c "ln -s /usr/local/lib/librfsimulator.so.Rel15 /usr/local/lib/li COPY --from=nr-ue-build /usr/local/lib/libprotobuf-c.so.1 . RUN ldconfig -#debug -#RUN ldd /opt/oai-nr-ue/bin/nr-uesoftmodem.Rel15 -#RUN ldd /usr/local/lib/liboai_eth_transpro.so.Rel15 -#RUN ldd /usr/local/lib/libtcp_bridge_oai.so.Rel15 -#RUN ldd /usr/local/lib/librfsimulator.so.Rel15 -#RUN ldd /usr/local/lib/liboai_usrpdevif.so.Rel15 -#RUN ldd /usr/local/lib/libcoding.so -#RUN ldd /usr/local/lib/libparams_libconfig.so -#RUN ldd /usr/local/lib/libdfts.so -#RUN ldd /usr/local/lib/libldpc.so -#RUN ldd /usr/local/lib/libldpc_optim.so -#RUN ldd /usr/local/lib/libldpc_optim8seg.so -#RUN ldd /usr/local/lib/libldpc_orig.so - -# Copy the relevant configuration files for eNB -WORKDIR /opt/oai-nr-ue/etc -COPY --from=nr-ue-build /oai-ran/ci-scripts/conf_files/ue.* . WORKDIR /opt/oai-nr-ue -#CMD ["/opt/oai-nr-ue/bin/nr-uesoftmodem", "-O", "/opt/oai-nr-ue/etc/enb.conf"] -#ENTRYPOINT ["/opt/oai-nr-ue/bin/entrypoint.sh"] -CMD ["sleep", "infinity"] +CMD ["/opt/oai-nr-ue/bin/nr-uesoftmodem.Rel15", "-O", "/opt/oai-nr-ue/etc/nr-ue-sim.conf"] +ENTRYPOINT ["/opt/oai-nr-ue/bin/entrypoint.sh"] diff --git a/docker/scripts/generateTemplate.py b/docker/scripts/generateTemplate.py index 9c45d5d43c..cc4b72a703 100644 --- a/docker/scripts/generateTemplate.py +++ b/docker/scripts/generateTemplate.py @@ -54,6 +54,7 @@ def main(): "rcc.band7.tm1.if4p5.lo.25PRB": f'{data[0]["paths"]["dest_dir"]}/{outputfilename}', "rcc.band40.tm1.25PRB": f'{data[0]["paths"]["dest_dir"]}/{outputfilename}', "gnb.band78.tm1.fr1.106PRB.usrpb210.conf": f'{data[0]["paths"]["dest_dir"]}/{outputfilename}', + "gnb.band78.sa.fr1.106PRB.usrpn310.conf": f'{data[0]["paths"]["dest_dir"]}/{outputfilename}', "ue.nfapi": f'{data[0]["paths"]["dest_dir"]}/{outputfilename}', "ue_sim_ci": f'{data[0]["paths"]["dest_dir"]}/{outputfilename}' } @@ -72,11 +73,21 @@ def main(): if re.search(r'EHPLMN_LIST', line): outputfile.write(line) continue + if re.search(r'sd = 0x1;', line): + templine = re.sub(r'sd = 0x1;', 'sd = 0x@NSSAI_SD0@;', line) + outputfile.write(templine) + continue + if re.search(r'sd = 0x112233;', line): + templine = re.sub(r'sd = 0x112233;', 'sd = 0x@NSSAI_SD1@;', line) + outputfile.write(templine) + continue for key in config["config"]: if line.find(key["key"]) >= 0: count += 1 if re.search(r'preference', line): templine = line + elif re.search(r'mnc_length', line) and key["key"] == "mnc": + continue elif re.search(r'plmn_list', line): templine = re.sub(r'[0-9]+', '""', line) templine = re.sub(r'\"\"', key["env"]["mcc"], templine, 1) diff --git a/docker/scripts/gnb_entrypoint.sh b/docker/scripts/gnb_entrypoint.sh index 09af2753bc..6d3d63629f 100755 --- a/docker/scripts/gnb_entrypoint.sh +++ b/docker/scripts/gnb_entrypoint.sh @@ -6,7 +6,8 @@ PREFIX=/opt/oai-gnb ENABLE_X2=${ENABLE_X2:-yes} # Based another env var, pick one template to use -if [[ -v USE_TDD_MONO ]]; then ln -s $PREFIX/etc/gnb.tdd.conf $PREFIX/etc/gnb.conf; fi +if [[ -v USE_NSA_TDD_MONO ]]; then ln -s $PREFIX/etc/gnb.nsa.tdd.conf $PREFIX/etc/gnb.conf; fi +if [[ -v USE_SA_TDD_MONO ]]; then ln -s $PREFIX/etc/gnb.sa.tdd.conf $PREFIX/etc/gnb.conf; fi # Only this template will be manipulated CONFIG_FILES=`ls $PREFIX/etc/gnb.conf || true` diff --git a/docker/scripts/gnb_parameters.yaml b/docker/scripts/gnb_parameters.yaml index 1992aecff5..a13d0d3677 100644 --- a/docker/scripts/gnb_parameters.yaml +++ b/docker/scripts/gnb_parameters.yaml @@ -26,7 +26,7 @@ - configurations: - filePrefix: gnb.band78.tm1.fr1.106PRB.usrpb210.conf - outputfilename: "gnb.tdd.conf" + outputfilename: "gnb.nsa.tdd.conf" config: - key: Active_gNBs env: "@GNB_NAME@" @@ -62,3 +62,31 @@ - key: FLEXRAN_IPV4_ADDRESS env: "@FLEXRAN_IPV4_ADDRESS@" + - filePrefix: gnb.band78.sa.fr1.106PRB.usrpn310.conf + outputfilename: "gnb.sa.tdd.conf" + config: + - key: Active_gNBs + env: "@GNB_NAME@" + - key: gNB_name + env: "@GNB_NAME@" + - key: mcc + env: "@MCC@" + - key: mnc + env: "@MNC@" + - key: mnc_length + env: "@MNC_LENGTH@" + - key: tracking_area_code + env: "@TAC@" + - key: sst + env: "@NSSAI_SST@" + - key: ipv4 + env: "@AMF_IP_ADDRESS@" + - key: GNB_INTERFACE_NAME_FOR_NG_AMF + env: "@GNB_NGA_IF_NAME@" + - key: GNB_IPV4_ADDRESS_FOR_NG_AMF + env: "@GNB_NGA_IP_ADDRESS@" + - key: GNB_INTERFACE_NAME_FOR_NGU + env: "@GNB_NGU_IF_NAME@" + - key: GNB_IPV4_ADDRESS_FOR_NGU + env: "@GNB_NGU_IP_ADDRESS@" + diff --git a/docker/scripts/nr_ue_entrypoint.sh b/docker/scripts/nr_ue_entrypoint.sh new file mode 100755 index 0000000000..691258b8fa --- /dev/null +++ b/docker/scripts/nr_ue_entrypoint.sh @@ -0,0 +1,63 @@ +#!/bin/bash + +set -euo pipefail + +PREFIX=/opt/oai-nr-ue + +# Based another env var, pick one template to use +#if [[ -v USE_NFAPI ]]; then ln -s $PREFIX/etc/ue.nfapi.conf $PREFIX/etc/ue.conf; fi + +# Only this template will be manipulated and the USIM one! +CONFIG_FILES=`ls $PREFIX/etc/ue.conf $PREFIX/etc/nr-ue-sim.conf || true` + +for c in ${CONFIG_FILES}; do + # grep variable names (format: ${VAR}) from template to be rendered + VARS=$(grep -oP '@[a-zA-Z0-9_]+@' ${c} | sort | uniq | xargs) + + # create sed expressions for substituting each occurrence of ${VAR} + # with the value of the environment variable "VAR" + EXPRESSIONS="" + for v in ${VARS}; do + NEW_VAR=`echo $v | sed -e "s#@##g"` + if [[ "${!NEW_VAR}x" == "x" ]]; then + echo "Error: Environment variable '${NEW_VAR}' is not set." \ + "Config file '$(basename $c)' requires all of $VARS." + exit 1 + fi + EXPRESSIONS="${EXPRESSIONS};s|${v}|${!NEW_VAR}|g" + done + EXPRESSIONS="${EXPRESSIONS#';'}" + + # render template and inline replace config file + sed -i "${EXPRESSIONS}" ${c} +done + +# Load the USRP binaries +if [[ -v USE_B2XX ]]; then + /usr/lib/uhd/utils/uhd_images_downloader.py -t b2xx +elif [[ -v USE_X3XX ]]; then + /usr/lib/uhd/utils/uhd_images_downloader.py -t x3xx +elif [[ -v USE_N3XX ]]; then + /usr/lib/uhd/utils/uhd_images_downloader.py -t n3xx +fi + +# in case we have conf file, append +new_args=() +while [[ $# -gt 0 ]]; do + new_args+=("$1") + shift +done + +echo "==================================" +echo "== Starting NR UE soft modem" +if [[ -v USE_ADDITIONAL_OPTIONS ]]; then + echo "Additional option(s): ${USE_ADDITIONAL_OPTIONS}" + for word in ${USE_ADDITIONAL_OPTIONS}; do + new_args+=("$word") + done + echo "${new_args[@]}" + exec "${new_args[@]}" +else + echo "${new_args[@]}" + exec "${new_args[@]}" +fi