From a5b30c07bcfc673b13430676bdef86b6228d77df Mon Sep 17 00:00:00 2001 From: laurent Date: Wed, 12 Jun 2019 16:45:52 +0200 Subject: [PATCH 01/32] add channel sim --- cmake_targets/CMakeLists.txt | 29 ++- common/config/config_userapi.c | 2 +- common/utils/minimal_stub.c | 4 + common/utils/simple_executable.h | 37 +++ targets/ARCH/COMMON/common_lib.c | 28 +-- targets/ARCH/COMMON/common_lib.h | 34 ++- targets/ARCH/rfsimulator/README.md | 76 +++++-- targets/ARCH/rfsimulator/simulator.c | 304 +++++++++++++++++++------ targets/ARCH/rfsimulator/stored_node.c | 142 ++++++++++++ targets/RT/USER/lte-softmodem-common.c | 1 + targets/RT/USER/lte-softmodem.h | 3 +- targets/RT/USER/lte-uesoftmodem.c | 3 +- 12 files changed, 550 insertions(+), 113 deletions(-) create mode 100644 common/utils/minimal_stub.c create mode 100644 common/utils/simple_executable.h create mode 100644 targets/ARCH/rfsimulator/stored_node.c diff --git a/cmake_targets/CMakeLists.txt b/cmake_targets/CMakeLists.txt index 5c9ab6d99d..50acfc4ce6 100644 --- a/cmake_targets/CMakeLists.txt +++ b/cmake_targets/CMakeLists.txt @@ -519,6 +519,9 @@ add_list1_option(NB_ANTENNAS_RX "2" "Number of antennas in reception" "1" "2" "4 add_list1_option(NB_ANTENNAS_TX "4" "Number of antennas in transmission" "1" "2" "4") add_list2_option(RF_BOARD "EXMIMO" "RF head type" "None" "EXMIMO" "OAI_USRP" "OAI_BLADERF" "CPRIGW" "OAI_LMSSDR" "OAI_SIMU") +if (NOT ${RF_BOARD} STREQUAL "None") + add_definitions(-DMANAGED_RF=1) +endif() add_list2_option(TRANSP_PRO "None" "Transport protocol type" "None" "ETHERNET") @@ -627,8 +630,6 @@ set(HWLIB_TCP_BRIDGE_OAI_SOURCE add_library(tcp_bridge_oai MODULE ${HWLIB_TCP_BRIDGE_OAI_SOURCE} ) set_target_properties(tcp_bridge_oai PROPERTIES COMPILE_FLAGS "-fvisibility=hidden") -add_library(rfsimulator MODULE ${OPENAIR_TARGETS}/ARCH/rfsimulator/simulator.c) - ########################################################## include_directories ("${OPENAIR_TARGETS}/ARCH/COMMON") @@ -2010,6 +2011,11 @@ add_library(uescope MODULE ${XFORMS_SOURCE} ${XFORMS_SOURCE_SOFTMODEM} ${XFORMS_ target_link_libraries(enbscope ${XFORMS_LIBRARIES}) target_link_libraries(uescope ${XFORMS_LIBRARIES}) +add_library(rfsimulator MODULE + ${OPENAIR_TARGETS}/ARCH/rfsimulator/simulator.c + ) +target_link_libraries(rfsimulator SIMU ${ATLAS_LIBRARIES}) + set(CMAKE_MODULE_PATH "${OPENAIR_DIR}/cmake_targets/tools/MODULES" "${CMAKE_MODULE_PATH}") #include T directory even if the T is off because T macros are in the code @@ -2053,6 +2059,25 @@ add_definitions(-DASN1_MINIMUM_VERSION=924) ################################# # add executables for operation ################################# +add_library(minimal_lib + ${OPENAIR_DIR}/common/utils/backtrace.c + ${OPENAIR_DIR}/common/utils/LOG/log.c + ${OPENAIR_DIR}/common/config/config_userapi.c + ${OPENAIR_DIR}/common/config/config_load_configmodule.c + ${OPENAIR_DIR}/common/config/config_cmdline.c + ${OPENAIR_DIR}/common/utils/minimal_stub.c + ${T_SOURCE} + ) +target_link_libraries(minimal_lib pthread dl ${T_LIB}) + +add_executable(replay_node + ${OPENAIR_TARGETS}/ARCH/rfsimulator/stored_node.c + ) +target_link_libraries (replay_node minimal_lib) + +add_executable(measurement_display + ${OPENAIR_DIR}/common/utils/threadPool/measurement_display.c) +target_link_libraries (measurement_display minimal_lib) # lte-softmodem is both eNB and UE implementation ################################################### diff --git a/common/config/config_userapi.c b/common/config/config_userapi.c index 66d3078d33..65e7a6dcc2 100644 --- a/common/config/config_userapi.c +++ b/common/config/config_userapi.c @@ -450,7 +450,7 @@ int config_setdefault_double(paramdef_t *cfgoptions, char *prefix) { config_check_valptr(cfgoptions, (char **)&(cfgoptions->dblptr),sizeof(double)); if( ((cfgoptions->paramflags & PARAMFLAG_MANDATORY) == 0)) { - *(cfgoptions->u64ptr)=cfgoptions->defdblval; + *(cfgoptions->dblptr)=cfgoptions->defdblval; status=1; printf_params("[CONFIG] %s set to default value %lf\n",cfgoptions->optname , *(cfgoptions->dblptr)); } diff --git a/common/utils/minimal_stub.c b/common/utils/minimal_stub.c new file mode 100644 index 0000000000..86454fe53f --- /dev/null +++ b/common/utils/minimal_stub.c @@ -0,0 +1,4 @@ +int T_stdout; + +void exit_function(const char *file, const char *function, const int line, const char *s) { +} diff --git a/common/utils/simple_executable.h b/common/utils/simple_executable.h new file mode 100644 index 0000000000..98b75012df --- /dev/null +++ b/common/utils/simple_executable.h @@ -0,0 +1,37 @@ +#ifndef __SIMPLE_EXE_H__ +#define __SIMPLE_EXE_H__ +#ifndef __USE_GNU +#define __USE_GNU +#endif +#ifndef _GNU_SOURCE +#define _GNU_SOURCE +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "common_lib.h" + +#ifdef T + #undef T + #define T(...) +#endif + +#endif diff --git a/targets/ARCH/COMMON/common_lib.c b/targets/ARCH/COMMON/common_lib.c index 3f81816aa1..c1685e11ec 100644 --- a/targets/ARCH/COMMON/common_lib.c +++ b/targets/ARCH/COMMON/common_lib.c @@ -42,35 +42,35 @@ int set_device(openair0_device *device) { switch (device->type) { case EXMIMO_DEV: - printf("[%s] has loaded EXPRESS MIMO device.\n",((device->host_type == RAU_HOST) ? "RAU": "RRU")); + LOG_I(HW,"[%s] has loaded EXPRESS MIMO device.\n",((device->host_type == RAU_HOST) ? "RAU": "RRU")); break; case USRP_B200_DEV: - printf("[%s] has loaded USRP B200 device.\n",((device->host_type == RAU_HOST) ? "RAU": "RRU")); + LOG_I(HW,"[%s] has loaded USRP B200 device.\n",((device->host_type == RAU_HOST) ? "RAU": "RRU")); break; case USRP_X300_DEV: - printf("[%s] has loaded USRP X300 device.\n",((device->host_type == RAU_HOST) ? "RAU": "RRU")); + LOG_I(HW,"[%s] has loaded USRP X300 device.\n",((device->host_type == RAU_HOST) ? "RAU": "RRU")); break; case BLADERF_DEV: - printf("[%s] has loaded BLADERF device.\n",((device->host_type == RAU_HOST) ? "RAU": "RRU")); + LOG_I(HW,"[%s] has loaded BLADERF device.\n",((device->host_type == RAU_HOST) ? "RAU": "RRU")); break; case LMSSDR_DEV: - printf("[%s] has loaded LMSSDR device.\n",((device->host_type == RAU_HOST) ? "RAU": "RRU")); + LOG_I(HW,"[%s] has loaded LMSSDR device.\n",((device->host_type == RAU_HOST) ? "RAU": "RRU")); break; case IRIS_DEV: - printf("[%s] has loaded Iris device.\n",((device->host_type == RAU_HOST) ? "RAU": "RRU")); + LOG_I(HW,"[%s] has loaded Iris device.\n",((device->host_type == RAU_HOST) ? "RAU": "RRU")); break; case NONE_DEV: - printf("[%s] has not loaded a HW device.\n",((device->host_type == RAU_HOST) ? "RAU": "RRU")); + LOG_I(HW,"[%s] has not loaded a HW device.\n",((device->host_type == RAU_HOST) ? "RAU": "RRU")); break; default: - printf("[%s] invalid HW device.\n",((device->host_type == RAU_HOST) ? "RAU": "RRU")); + LOG_E(HW,"[%s] invalid HW device.\n",((device->host_type == RAU_HOST) ? "RAU": "RRU")); return -1; } @@ -80,17 +80,17 @@ int set_device(openair0_device *device) { int set_transport(openair0_device *device) { switch (device->transp_type) { case ETHERNET_TP: - printf("[%s] has loaded ETHERNET trasport protocol.\n",((device->host_type == RAU_HOST) ? "RAU": "RRU")); + LOG_I(HW,"[%s] has loaded ETHERNET trasport protocol.\n",((device->host_type == RAU_HOST) ? "RAU": "RRU")); return 0; break; case NONE_TP: - printf("[%s] has not loaded a transport protocol.\n",((device->host_type == RAU_HOST) ? "RAU": "RRU")); + LOG_I(HW,"[%s] has not loaded a transport protocol.\n",((device->host_type == RAU_HOST) ? "RAU": "RRU")); return 0; break; default: - printf("[%s] invalid transport protocol.\n",((device->host_type == RAU_HOST) ? "RAU": "RRU")); + LOG_E(HW,"[%s] invalid transport protocol.\n",((device->host_type == RAU_HOST) ? "RAU": "RRU")); return -1; break; } @@ -119,7 +119,7 @@ int load_lib(openair0_device *device, openair0_config_t *openair0_cfg, eth_param ret=load_module_shlib(libname,shlib_fdesc,1,NULL); if (ret < 0) { - fprintf(stderr,"Library %s couldn't be loaded\n",libname); + LOG_E(HW,"Library %s couldn't be loaded\n",libname); } else { ret=((devfunc_t)shlib_fdesc[0].fptr)(device,openair0_cfg,cfg); } @@ -135,7 +135,7 @@ int openair0_device_load(openair0_device *device, openair0_config_t *openair0_cf if ( rc >= 0) { if ( set_device(device) < 0) { - fprintf(stderr, "%s %d:Unsupported radio head\n",__FILE__, __LINE__); + LOG_E(HW, "%s %d:Unsupported radio head\n",__FILE__, __LINE__); return -1; } } @@ -149,7 +149,7 @@ int openair0_transport_load(openair0_device *device, openair0_config_t *openair0 if ( rc >= 0) { if ( set_transport(device) < 0) { - fprintf(stderr, "%s %d:Unsupported transport protocol\n",__FILE__, __LINE__); + LOG_E(HW, "%s %d:Unsupported transport protocol\n",__FILE__, __LINE__); return -1; } } diff --git a/targets/ARCH/COMMON/common_lib.h b/targets/ARCH/COMMON/common_lib.h index 0af6fa9c5e..aca332ac48 100644 --- a/targets/ARCH/COMMON/common_lib.h +++ b/targets/ARCH/COMMON/common_lib.h @@ -34,6 +34,7 @@ #define COMMON_LIB_H #include #include +#include /* name of shared library implementing the radio front end */ #define OAI_RF_LIBNAME "oai_device" @@ -83,9 +84,6 @@ typedef enum { */ /*!\brief RF device types */ -#ifdef OCP_FRAMEWORK -#include -#else typedef enum { MIN_RF_DEV_TYPE = 0, /*!\brief device is ExpressMIMO */ @@ -102,10 +100,13 @@ typedef enum { IRIS_DEV, /*!\brief device is NONE*/ NONE_DEV, + /*!\brief device is ADRV9371_ZC706 */ + ADRV9371_ZC706_DEV, + /*!\brief device is UEDv2 */ + UEDv2_DEV, MAX_RF_DEV_TYPE } dev_type_t; -#endif /*!\brief transport protocol types */ @@ -384,6 +385,31 @@ struct openair0_device_t { typedef int(*oai_device_initfunc_t)(openair0_device *device, openair0_config_t *openair0_cfg); /* type of transport init function, implemented in shared lib */ typedef int(*oai_transport_initfunc_t)(openair0_device *device, openair0_config_t *openair0_cfg, eth_params_t *eth_params); +#define UE_MAGICDL_FDD 0xA5A5A5A5A5A5A5A5 // UE DL FDD record +#define UE_MAGICUL_FDD 0x5A5A5A5A5A5A5A5A // UE UL FDD record +#define UE_MAGICDL_TDD 0xA6A6A6A6A6A6A6A6 // UE DL TDD record +#define UE_MAGICUL_TDD 0x6A6A6A6A6A6A6A6A // UE UL TDD record + +#define ENB_MAGICDL_FDD 0xB5B5B5B5B5B5B5B5 // eNB DL FDD record +#define ENB_MAGICUL_FDD 0x5B5B5B5B5B5B5B5B // eNB UL FDD record +#define ENB_MAGICDL_TDD 0xB6B6B6B6B6B6B6B6 // eNB DL TDD record +#define ENB_MAGICUL_TDD 0x6B6B6B6B6B6B6B6B // eNB UL TDD record + +#define OPTION_LZ4 0x00000001 // LZ4 compression (option_value is set to compressed size) + +#define sample_t struct complex16 // 2*16 bits complex number + +typedef struct { + uint64_t magic; // Magic value (see defines above) + uint32_t size; // Number of samples per antenna to follow this header + uint32_t nbAnt; // Total number of antennas following this header + // Samples per antenna follow this header, + // i.e. nbAnt = 2 => this header+samples_antenna_0+samples_antenna_1 + // data following this header in bytes is nbAnt*size*sizeof(sample_t) + uint64_t timestamp; // Timestamp value of first sample + uint32_t option_value; // Option value + uint32_t option_flag; // Option flag +} samplesBlockHeader_t; #ifdef __cplusplus extern "C" diff --git a/targets/ARCH/rfsimulator/README.md b/targets/ARCH/rfsimulator/README.md index ebe7d72ee0..68b820ff9a 100644 --- a/targets/ARCH/rfsimulator/README.md +++ b/targets/ARCH/rfsimulator/README.md @@ -1,14 +1,26 @@ -## General - +#General This is a RF simulator that allows to test OAI without a RF board. It replaces a actual RF board driver. As much as possible, it works like a RF board, but not in realtime: it can run faster than realtime if there is enough CPU or slower (it is CPU bound instead of real time RF sampling bound) -## build +#build - No specific build is required, use the [oai softmodem build procedure](../../../doc/BUILD.md) +## From build_oai +You can build it the same way, and together with actual RF driver +Example: +```bash +./build_oai --ue-nas-use-tun --UE --eNB -w SIMU +``` +It is also possible to build actual RF and use choose on each run: +```bash +./build_oai --ue-nas-use-tun --UE --eNB -w USRP --rfsimulator +``` +Will build both the eNB (lte-softmodem) and the UE (lte-uesoftmodem) +We recommend to use the option --ue-nas-use-tun that is much simpler to use than the OAI kernel driver. + +## Add the rfsimulator after initial build After any regular build, you can compile the driver ```bash cd /build @@ -18,35 +30,21 @@ Then, you can use it freely # Usage Setting the env variable RFSIMULATOR enables the RF board simulator -It should the set to "enb" in the eNB +It should the set to "server" in the eNB or gNB ## 4G case For the UE, it should be set to the IP address of the eNB example: - ```bash -sudo RFSIMULATOR=192.168.2.200 ./lte-uesoftmodem -C 2685000000 -r 50 --rfsim +sudo RFSIMULATOR=192.168.2.200 ./lte-uesoftmodem -C 2685000000 -r 50 ``` -For the eNodeB, use a valid configuration file setup for USRP board tests and start the softmodem as usual, but adding the `--rfsim` option. - - - -```bash -sudo RFSIMULATOR=enb ./lte-softmodem -O --rfsim -``` - - - Except this, the UE and the eNB can be used as it the RF is real If you reach 'RA not active' on UE, be careful to generate a valid SIM ```bash $OPENAIR_DIR/targets/bin/conf2uedata -c $OPENAIR_DIR/openair3/NAS/TOOLS/ue_eurecom_test_sfr.conf -o . ``` -This simulator can also be used with the `--noS1` option, in this case you must run the eNodeB and the UE on different PCs. - ## 5G case - After regular build, add the simulation driver (don't use ./build_oai -w SIMU until we merge 4G and 5G branches) ```bash @@ -55,7 +53,7 @@ make rfsimulator ``` ### Launch gNB in one window ```bash -sudo RFSIMULATOR=enb ./nr-softmodem -O ../../../targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.106PRB.usrpn300.conf --parallel-config PARALLEL_SINGLE_THREAD +sudo RFSIMULATOR=server ./nr-softmodem -O ../../../targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.106PRB.usrpn300.conf --parallel-config PARALLEL_SINGLE_THREAD ``` ### Launch UE in another window ```bash @@ -64,8 +62,40 @@ sudo RFSIMULATOR=127.0.0.1 ./nr-uesoftmodem --numerology 1 -r 106 -C 3510000000 Of course, set the gNB machine IP address if the UE and the gNB are not on the same machine In UE, you can add "-d" to get the softscope -## Caveacts +### store and replay -Still issues in power control: txgain, rxgain are not used +You can store emitted I/Q samples: +If you set the environment variable: saveIQfile to a file name +The simulator will write all IQ samples into this file +Then, you can replay with the executable "replay_node" + +First compile it, as the other binaries +``` +make replay_node +``` +You can use this binary as I/Q data source to feed whatever UE or NB with recorded I/Q samples. + +The file format is successive blocks of a header followed by the I/Q array. +If you have existing stored I/Q, you can adpat the tool "replay_node" to convert your format to the rfsimulator format. + +The format intend to be compatible with the OAI store/replay feature on USRP + +### Channel simulation +The RF channel simulator is called. +In current version all channel paramters are hard coded in the call to: +``` +new_channel_desc_scm(bridge->tx_num_channels,bridge->rx_num_channels, + AWGN, + bridge->sample_rate, + bridge->tx_bw, + 0.0, // forgetting_factor + 0, // maybe used for TA + 0); // path_loss in dB +``` +Only the input noise can be changed on command line with -s parameter. +With path loss = 0 set "-s 5" to see a little noise + +#Caveacts +Still issues in power control: txgain, rxgain are not used \ No newline at end of file diff --git a/targets/ARCH/rfsimulator/simulator.c b/targets/ARCH/rfsimulator/simulator.c index a17327b03e..e81e958184 100644 --- a/targets/ARCH/rfsimulator/simulator.c +++ b/targets/ARCH/rfsimulator/simulator.c @@ -3,6 +3,12 @@ copyleft: OpenAirInterface Software Alliance and it's licence */ +/* + * Open issues and limitations + * The read and write should be called in the same thread, that is not new USRP UHD design + * When the opposite side switch from passive reading to active R+Write, the synchro is not fully deterministic + */ + #include #include #include @@ -21,63 +27,175 @@ #include "common_lib.h" #include #include "openair1/PHY/defs_UE.h" +#include #define PORT 4043 //TCP port for this simulator #define CirSize 3072000 // 100ms is enough -#define sample_t uint32_t // 2*16 bits complex number #define sampleToByte(a,b) ((a)*(b)*sizeof(sample_t)) #define byteToSample(a,b) ((a)/(sizeof(sample_t)*(b))) -#define MAGICeNB 0xA5A5A5A5A5A5A5A5 -#define MAGICUE 0x5A5A5A5A5A5A5A5A -typedef struct { - uint64_t magic; - uint32_t size; - uint32_t nbAnt; - uint64_t timestamp; -} transferHeader; +#define MAX_SIMULATION_CONNECTED_NODES 5 +#define GENERATE_CHANNEL 10 //each frame in DL + +// Fixme: datamodel, external variables in .h files, ... +#include +extern double snr_dB; +extern RAN_CONTEXT_t RC; +// + +pthread_mutex_t Sockmutex; typedef struct buffer_s { int conn_sock; bool alreadyRead; uint64_t lastReceivedTS; bool headerMode; - transferHeader th; + samplesBlockHeader_t th; char *transferPtr; uint64_t remainToTransfer; char *circularBufEnd; sample_t *circularBuf; + channel_desc_t *channel_model; } buffer_t; typedef struct { int listen_sock, epollfd; uint64_t nextTimestamp; uint64_t typeStamp; - uint64_t initialAhead; char *ip; + int saveIQfile; buffer_t buf[FD_SETSIZE]; + int rx_num_channels; + int tx_num_channels; + double sample_rate; + double tx_bw; } rfsimulator_state_t; +/* + Legacy study: + The parameters are: + gain&loss (decay, signal power, ...) + either a fixed gain in dB, a target power in dBm or ACG (automatic control gain) to a target average + => don't redo the AGC, as it was used in UE case, that must have a AGC inside the UE + will be better to handle the "set_gain()" called by UE to apply it's gain (enable test of UE power loop) + lin_amp = pow(10.0,.05*txpwr_dBm)/sqrt(nb_tx_antennas); + a lot of operations in legacy, grouped in one simulation signal decay: txgain*decay*rxgain + + multi_path (auto convolution, ISI, ...) + either we regenerate the channel (call again random_channel(desc,0)), or we keep it over subframes + legacy: we regenerate each sub frame in UL, and each frame only in DL +*/ +void rxAddInput( struct complex16 *input_sig, struct complex16 *after_channel_sig, + int rxAnt, + channel_desc_t *channelDesc, + int nbSamples, + uint64_t TS + ) { + // channelDesc->path_loss_dB should contain the total path gain + // so, in actual RF: tx gain + path loss + rx gain (+antenna gain, ...) + // UE and NB gain control to be added + // Fixme: not sure when it is "volts" so dB is 20*log10(...) or "power", so dB is 10*log10(...) + const double pathLossLinear = pow(10,channelDesc->path_loss_dB/20.0); + // Energy in one sample to calibrate input noise + //Fixme: modified the N0W computation, not understand the origin value + const double KT=1.38e-23*290; //Boltzman*temperature + // sampling rate is linked to acquisition band (the input pass band filter) + const double noise_figure_watt = KT*channelDesc->sampling_rate; + // Fixme: how to convert a noise in Watt into a 12 bits value out of the RF ADC ? + // the parameter "-s" is declared as SNR, but the input power is not well defined + // −132.24 dBm is a LTE subcarrier noise, that was used in origin code (15KHz BW thermal noise) + const double rxGain= 132.24 - snr_dB; + // sqrt(4*noise_figure_watt) is the thermal noise factor (volts) + // fixme: the last constant is pure trial results to make decent noise + const double noise_per_sample = sqrt(4*noise_figure_watt) * pow(10,rxGain/20) *10; + // Fixme: we don't fill the offset length samples at begining ? + // anyway, in today code, channel_offset=0 + const int dd = abs(channelDesc->channel_offset); + const int nbTx=channelDesc->nb_tx; + + for (int i=0; i<((int)nbSamples-dd); i++) { + struct complex16 *out_ptr=after_channel_sig+dd+i; + struct complex rx_tmp= {0}; + + for (int txAnt=0; txAnt < nbTx; txAnt++) { + const struct complex *channelModel= channelDesc->ch[rxAnt+(txAnt*channelDesc->nb_rx)]; + + //const struct complex *channelModelEnd=channelModel+channelDesc->channel_length; + for (int l = 0; l<(int)channelDesc->channel_length; l++) { + // let's assume TS+i >= l + // fixme: the rfsimulator current structure is interleaved antennas + // this has been designed to not have to wait a full block transmission + // but it is not very usefull + // it would be better to split out each antenna in a separate flow + // that will allow to mix ru antennas freely + struct complex16 tx16=input_sig[((TS+i-l)*nbTx+txAnt)%CirSize]; + rx_tmp.x += tx16.r * channelModel[l].x - tx16.i * channelModel[l].y; + rx_tmp.y += tx16.i * channelModel[l].x + tx16.r * channelModel[l].y; + } //l + } + + out_ptr->r += round(rx_tmp.x*pathLossLinear + noise_per_sample*gaussdouble(0.0,1.0)); + printf("in: %d, out %d= %f*%f + %f*%f\n", + input_sig[((TS+i)*nbTx)%CirSize].r, out_ptr->r , rx_tmp.x, + pathLossLinear, noise_per_sample,gaussdouble(0.0,1.0)); + out_ptr->i += round(rx_tmp.y*pathLossLinear + noise_per_sample*gaussdouble(0.0,1.0)); + out_ptr++; + } + + if ( (TS*nbTx)%CirSize+nbSamples <= CirSize ) + // Cast to a wrong type for compatibility ! + LOG_D(HW,"Input power %f, output power: %f, channel path loss %f, noise coeff: %f \n", + 10*log10((double)signal_energy((int32_t *)&input_sig[(TS*nbTx)%CirSize], nbSamples)), + 10*log10((double)signal_energy((int32_t *)after_channel_sig, nbSamples)), + channelDesc->path_loss_dB, + 10*log10(noise_per_sample)); +} + void allocCirBuf(rfsimulator_state_t *bridge, int sock) { buffer_t *ptr=&bridge->buf[sock]; AssertFatal ( (ptr->circularBuf=(sample_t *) malloc(sampleToByte(CirSize,1))) != NULL, ""); ptr->circularBufEnd=((char *)ptr->circularBuf)+sampleToByte(CirSize,1); ptr->conn_sock=sock; + ptr->alreadyRead=false; + ptr->lastReceivedTS=0; ptr->headerMode=true; ptr->transferPtr=(char *)&ptr->th; - ptr->remainToTransfer=sizeof(transferHeader); + ptr->remainToTransfer=sizeof(samplesBlockHeader_t); int sendbuff=1000*1000*10; AssertFatal ( setsockopt(sock, SOL_SOCKET, SO_SNDBUF, &sendbuff, sizeof(sendbuff)) == 0, ""); struct epoll_event ev= {0}; ev.events = EPOLLIN | EPOLLRDHUP; ev.data.fd = sock; AssertFatal(epoll_ctl(bridge->epollfd, EPOLL_CTL_ADD, sock, &ev) != -1, ""); + // create channel simulation model for this mode reception + // snr_dB is pure global, coming from configuration paramter "-s" + // Fixme: referenceSignalPower should come from the right place + // but the datamodel is inconsistant + // legacy: RC.ru[ru_id]->frame_parms.pdsch_config_common.referenceSignalPower + // (must not come from ru[]->frame_parms as it doesn't belong to ru !!!) + // Legacy sets it as: + // ptr->channel_model->path_loss_dB = -132.24 + snr_dB - RC.ru[0]->frame_parms->pdsch_config_common.referenceSignalPower; + // we use directly the paramter passed on the command line ("-s") + // the value channel_model->path_loss_dB seems only a storage place (new_channel_desc_scm() only copy the passed value) + // Legacy changes directlty the variable channel_model->path_loss_dB place to place + // while calling new_channel_desc_scm() with path losses = 0 + ptr->channel_model=new_channel_desc_scm(bridge->tx_num_channels,bridge->rx_num_channels, + AWGN, + bridge->sample_rate, + bridge->tx_bw, + 0.0, // forgetting_factor + 0, // maybe used for TA + 0); // path_loss in dB + random_channel(ptr->channel_model,false); } void removeCirBuf(rfsimulator_state_t *bridge, int sock) { AssertFatal( epoll_ctl(bridge->epollfd, EPOLL_CTL_DEL, sock, NULL) != -1, ""); close(sock); free(bridge->buf[sock].circularBuf); + // Fixme: no free_channel_desc_scm(bridge->buf[sock].channel_model) implemented + // a lot of mem leaks + free(bridge->buf[sock].channel_model); memset(&bridge->buf[sock], 0, sizeof(buffer_t)); bridge->buf[sock].conn_sock=-1; } @@ -87,12 +205,11 @@ void socketError(rfsimulator_state_t *bridge, int sock) { LOG_W(HW,"Lost socket \n"); removeCirBuf(bridge, sock); - if (bridge->typeStamp==MAGICUE) + if (bridge->typeStamp==UE_MAGICDL_FDD) exit(1); } } - #define helpTxt "\ \x1b[31m\ rfsimulator: error: you have to run one UE and one eNB\n\ @@ -117,11 +234,18 @@ void setblocking(int sock, enum blocking_t active) { AssertFatal(fcntl(sock, F_SETFL, opts) >= 0, ""); } -static bool flushInput(rfsimulator_state_t *t); +static bool flushInput(rfsimulator_state_t *t, int timeout); -void fullwrite(int fd, void *_buf, int count, rfsimulator_state_t *t) { +void fullwrite(int fd, void *_buf, ssize_t count, rfsimulator_state_t *t) { + if (t->saveIQfile != -1) { + if (write(t->saveIQfile, _buf, count) != count ) + LOG_E(HW,"write in save iq file failed (%s)\n",strerror(errno)); + } + + AssertFatal(fd>=0 && _buf && count >0 && t, + "Bug: %d/%p/%zd/%p", fd, _buf, count, t); char *buf = _buf; - int l; + ssize_t l; setblocking(fd, notBlocking); while (count) { @@ -132,7 +256,9 @@ void fullwrite(int fd, void *_buf, int count, rfsimulator_state_t *t) { continue; if(errno==EAGAIN) { - flushInput(t); + // The opposite side is saturated + // we read incoming sockets meawhile waiting + flushInput(t, 5); continue; } else return; @@ -145,7 +271,7 @@ void fullwrite(int fd, void *_buf, int count, rfsimulator_state_t *t) { int server_start(openair0_device *device) { rfsimulator_state_t *t = (rfsimulator_state_t *) device->priv; - t->typeStamp=MAGICeNB; + t->typeStamp=ENB_MAGICDL_FDD; AssertFatal((t->listen_sock = socket(AF_INET, SOCK_STREAM, 0)) >= 0, ""); int enable = 1; AssertFatal(setsockopt(t->listen_sock, SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(int)) == 0, ""); @@ -168,7 +294,7 @@ sin_addr: int start_ue(openair0_device *device) { rfsimulator_state_t *t = device->priv; - t->typeStamp=MAGICUE; + t->typeStamp=UE_MAGICDL_FDD; int sock; AssertFatal((sock = socket(AF_INET, SOCK_STREAM, 0)) >= 0, ""); struct sockaddr_in addr = { @@ -200,14 +326,16 @@ sin_addr: return 0; } +uint64_t lastW=-1; int rfsimulator_write(openair0_device *device, openair0_timestamp timestamp, void **samplesVoid, int nsamps, int nbAnt, int flags) { rfsimulator_state_t *t = device->priv; + LOG_D(HW,"sending %d samples at time: %ld\n", nsamps, timestamp); for (int i=0; ibuf[i]; if (ptr->conn_sock >= 0 ) { - transferHeader header= {t->typeStamp, nsamps, nbAnt, timestamp}; + samplesBlockHeader_t header= {t->typeStamp, nsamps, nbAnt, timestamp}; fullwrite(ptr->conn_sock,&header, sizeof(header), t); sample_t tmpSamples[nsamps][nbAnt]; @@ -223,21 +351,27 @@ int rfsimulator_write(openair0_device *device, openair0_timestamp timestamp, voi } } + lastW=timestamp; LOG_D(HW,"sent %d samples at time: %ld->%ld, energy in first antenna: %d\n", nsamps, timestamp, timestamp+nsamps, signal_energy(samplesVoid[0], nsamps) ); + // Let's verify we don't have incoming data + // This is mandatory when the opposite side don't transmit + // This is mandatory when the opposite side don't transmit + flushInput(t, 0); + pthread_mutex_unlock(&Sockmutex); return nsamps; } -static bool flushInput(rfsimulator_state_t *t) { +static bool flushInput(rfsimulator_state_t *t, int timeout) { // Process all incoming events on sockets // store the data in lists struct epoll_event events[FD_SETSIZE]= {0}; - int nfds = epoll_wait(t->epollfd, events, FD_SETSIZE, 200); + int nfds = epoll_wait(t->epollfd, events, FD_SETSIZE, timeout); if ( nfds==-1 ) { - if ( errno==EINTR || errno==EAGAIN ) + if ( errno==EINTR || errno==EAGAIN ) { return false; - else + } else AssertFatal(false,"error in epoll_wait\n"); } @@ -263,7 +397,7 @@ static bool flushInput(rfsimulator_state_t *t) { continue; } - int blockSz; + ssize_t blockSz; if ( b->headerMode) blockSz=b->remainToTransfer; @@ -272,7 +406,7 @@ static bool flushInput(rfsimulator_state_t *t) { b->remainToTransfer : b->circularBufEnd - 1 - b->transferPtr ; - int sz=recv(fd, b->transferPtr, blockSz, MSG_DONTWAIT); + ssize_t sz=recv(fd, b->transferPtr, blockSz, MSG_DONTWAIT); if ( sz < 0 ) { if ( errno != EAGAIN ) { @@ -282,6 +416,7 @@ static bool flushInput(rfsimulator_state_t *t) { } else if ( sz == 0 ) continue; + LOG_D(HW, "Socket rcv %zd bytes\n", sz); AssertFatal((b->remainToTransfer-=sz) >= 0, ""); b->transferPtr+=sz; @@ -290,39 +425,44 @@ static bool flushInput(rfsimulator_state_t *t) { // check the header and start block transfer if ( b->headerMode==true && b->remainToTransfer==0) { - AssertFatal( (t->typeStamp == MAGICUE && b->th.magic==MAGICeNB) || - (t->typeStamp == MAGICeNB && b->th.magic==MAGICUE), "Socket Error in protocol"); + AssertFatal( (t->typeStamp == UE_MAGICDL_FDD && b->th.magic==ENB_MAGICDL_FDD) || + (t->typeStamp == ENB_MAGICDL_FDD && b->th.magic==UE_MAGICDL_FDD), "Socket Error in protocol"); b->headerMode=false; b->alreadyRead=true; if ( b->lastReceivedTS != b->th.timestamp) { int nbAnt= b->th.nbAnt; - for (uint64_t index=b->lastReceivedTS; index < b->th.timestamp; index++ ) - for (int a=0; a < nbAnt; a++) - b->circularBuf[(index*nbAnt+a)%CirSize]=0; + for (uint64_t index=b->lastReceivedTS; index < b->th.timestamp; index++ ) { + for (int a=0; a < nbAnt; a++) { + b->circularBuf[(index*nbAnt+a)%CirSize].r=0; + b->circularBuf[(index*nbAnt+a)%CirSize].i=0; + } + } LOG_W(HW,"gap of: %ld in reception\n", b->th.timestamp-b->lastReceivedTS ); } b->lastReceivedTS=b->th.timestamp; + AssertFatal(lastW == -1 || ( abs((double)lastW-b->lastReceivedTS) < (double)CirSize), + "Tx/Rx shift too large Tx:%lu, Rx:%lu\n", lastW, b->lastReceivedTS); b->transferPtr=(char *)&b->circularBuf[b->lastReceivedTS%CirSize]; b->remainToTransfer=sampleToByte(b->th.size, b->th.nbAnt); } if ( b->headerMode==false ) { + LOG_D(HW,"Set b->lastReceivedTS %ld\n", b->lastReceivedTS); b->lastReceivedTS=b->th.timestamp+b->th.size-byteToSample(b->remainToTransfer,b->th.nbAnt); + // First block in UE, resync with the eNB current TS + if ( t->nextTimestamp == 0 ) + t->nextTimestamp=b->lastReceivedTS-b->th.size; + if ( b->remainToTransfer==0) { LOG_D(HW,"Completed block reception: %ld\n", b->lastReceivedTS); - - // First block in UE, resync with the eNB current TS - if ( t->nextTimestamp == 0 ) - t->nextTimestamp=b->lastReceivedTS-b->th.size; - b->headerMode=true; b->transferPtr=(char *)&b->th; - b->remainToTransfer=sizeof(transferHeader); + b->remainToTransfer=sizeof(samplesBlockHeader_t); b->th.magic=-1; } } @@ -334,10 +474,10 @@ static bool flushInput(rfsimulator_state_t *t) { int rfsimulator_read(openair0_device *device, openair0_timestamp *ptimestamp, void **samplesVoid, int nsamps, int nbAnt) { if (nbAnt != 1) { - LOG_E(HW, "rfsimulator: only 1 antenna tested\n"); - exit(1); + LOG_W(HW, "rfsimulator: only 1 antenna tested\n"); } + pthread_mutex_lock(&Sockmutex); rfsimulator_state_t *t = device->priv; LOG_D(HW, "Enter rfsimulator_read, expect %d samples, will release at TS: %ld\n", nsamps, t->nextTimestamp+nsamps); // deliver data from received data @@ -350,13 +490,14 @@ int rfsimulator_read(openair0_device *device, openair0_timestamp *ptimestamp, vo if ( first_sock == FD_SETSIZE ) { // no connected device (we are eNB, no UE is connected) - if (!flushInput(t)) { + if (!flushInput(t, 10)) { for (int x=0; x < nbAnt; x++) memset(samplesVoid[x],0,sampleToByte(nsamps,1)); t->nextTimestamp+=nsamps; LOG_W(HW,"Generated void samples for Rx: %ld\n", t->nextTimestamp); *ptimestamp = t->nextTimestamp-nsamps; + pthread_mutex_unlock(&Sockmutex); return nsamps; } } else { @@ -365,20 +506,21 @@ int rfsimulator_read(openair0_device *device, openair0_timestamp *ptimestamp, vo do { have_to_wait=false; - for ( int sock=0; sockbuf[sock].circularBuf && - t->buf[sock].alreadyRead && //>= t->initialAhead && - (t->nextTimestamp+nsamps) > t->buf[sock].lastReceivedTS ) { - have_to_wait=true; - break; - } + for ( int sock=0; sockbuf[sock].circularBuf && t->buf[sock].alreadyRead ) + if ( t->buf[sock].lastReceivedTS == 0 || + (t->nextTimestamp+nsamps) > t->buf[sock].lastReceivedTS ) { + have_to_wait=true; + break; + } + } if (have_to_wait) /*printf("Waiting on socket, current last ts: %ld, expected at least : %ld\n", ptr->lastReceivedTS, t->nextTimestamp+nsamps); */ - flushInput(t); + flushInput(t, 3); } while (have_to_wait); } @@ -386,17 +528,25 @@ int rfsimulator_read(openair0_device *device, openair0_timestamp *ptimestamp, vo for (int a=0; abuf[sock]; if ( ptr->circularBuf && ptr->alreadyRead ) { - for (int a=0; acircularBuf[((t->nextTimestamp+i)*nbAnt+a)%CirSize]<<1; - } + //fixme: when do we regenerate + // it seems legacy behavior is: never in UL, each frame in DL + if (reGenerateChannel) + random_channel(ptr->channel_model,0); + + for (int a=0; acircularBuf, (struct complex16 *) samplesVoid[a], + a, + ptr->channel_model, + nsamps, + t->nextTimestamp + ); } } @@ -406,10 +556,9 @@ int rfsimulator_read(openair0_device *device, openair0_timestamp *ptimestamp, vo nsamps, *ptimestamp, t->nextTimestamp, signal_energy(samplesVoid[0], nsamps)); + pthread_mutex_unlock(&Sockmutex); return nsamps; } - - int rfsimulator_request(openair0_device *device, void *msg, ssize_t msg_len) { abort(); return 0; @@ -434,11 +583,11 @@ int rfsimulator_set_freq(openair0_device *device, openair0_config_t *openair0_cf int rfsimulator_set_gains(openair0_device *device, openair0_config_t *openair0_cfg) { return 0; } - - __attribute__((__visibility__("default"))) int device_init(openair0_device *device, openair0_config_t *openair0_cfg) { - //set_log(HW,OAILOG_DEBUG); + // to change the log level, use this on command line + // --log_config.hw_log_level debug + // (for phy layer, replace "hw" by "phy" rfsimulator_state_t *rfsimulator = (rfsimulator_state_t *)calloc(sizeof(rfsimulator_state_t),1); if ((rfsimulator->ip=getenv("RFSIMULATOR")) == NULL ) { @@ -446,11 +595,28 @@ int device_init(openair0_device *device, openair0_config_t *openair0_cfg) { exit(1); } - rfsimulator->typeStamp = strncasecmp(rfsimulator->ip,"enb",3) == 0 ? - MAGICeNB: - MAGICUE; - LOG_I(HW,"rfsimulator: running as %s\n", rfsimulator-> typeStamp == MAGICeNB ? "eNB" : "UE"); - device->trx_start_func = rfsimulator->typeStamp == MAGICeNB ? + pthread_mutex_init(&Sockmutex, NULL); + + if ( strncasecmp(rfsimulator->ip,"enb",3) == 0 || + strncasecmp(rfsimulator->ip,"server",3) == 0 ) + rfsimulator->typeStamp = ENB_MAGICDL_FDD; + else + rfsimulator->typeStamp = UE_MAGICDL_FDD; + + LOG_I(HW,"rfsimulator: running as %s\n", rfsimulator-> typeStamp == ENB_MAGICDL_FDD ? "(eg)NB" : "UE"); + char *saveF; + + if ((saveF=getenv("saveIQfile")) != NULL) { + rfsimulator->saveIQfile=open(saveF,O_APPEND| O_CREAT|O_TRUNC | O_WRONLY, 0666); + + if ( rfsimulator->saveIQfile != -1 ) + LOG_I(HW,"rfsimulator: will save written IQ samples in %s\n", saveF); + else + LOG_E(HW, "can't open %s for IQ saving (%s)\n", saveF, strerror(errno)); + } else + rfsimulator->saveIQfile = -1; + + device->trx_start_func = rfsimulator->typeStamp == ENB_MAGICDL_FDD ? server_start : start_ue; device->trx_get_stats_func = rfsimulator_get_stats; @@ -470,6 +636,12 @@ int device_init(openair0_device *device, openair0_config_t *openair0_cfg) { rfsimulator->buf[i].conn_sock=-1; AssertFatal((rfsimulator->epollfd = epoll_create1(0)) != -1,""); - rfsimulator->initialAhead=openair0_cfg[0].sample_rate/1000; // One sub frame + // initialize channel simulation + rfsimulator->tx_num_channels=openair0_cfg->tx_num_channels; + rfsimulator->rx_num_channels=openair0_cfg->rx_num_channels; + rfsimulator->sample_rate=openair0_cfg->sample_rate; + rfsimulator->tx_bw=openair0_cfg->tx_bw; + randominit(0); + set_taus_seed(0); return 0; } diff --git a/targets/ARCH/rfsimulator/stored_node.c b/targets/ARCH/rfsimulator/stored_node.c new file mode 100644 index 0000000000..888b5f6de0 --- /dev/null +++ b/targets/ARCH/rfsimulator/stored_node.c @@ -0,0 +1,142 @@ +/* + Author: Laurent THOMAS, Open Cells + copyleft: OpenAirInterface Software Alliance and it's licence +*/ + +#include + + +void fullwrite(int fd, void *_buf, int count) { + char *buf = _buf; + int l; + + while (count) { + l = write(fd, buf, count); + + if (l <= 0) { + if (errno==EINTR) + continue; + + if(errno==EAGAIN) { + continue; + } else { + AssertFatal(false,"Lost socket\n"); + } + } else { + count -= l; + buf += l; + } + } +} + +int server_start(short port) { + int listen_sock; + AssertFatal((listen_sock = socket(AF_INET, SOCK_STREAM, 0)) >= 0, ""); + int enable = 1; + AssertFatal(setsockopt(listen_sock, SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(int)) == 0, ""); + struct sockaddr_in addr = { +sin_family: + AF_INET, +sin_port: + htons(port), +sin_addr: + { s_addr: INADDR_ANY } + }; + bind(listen_sock, (struct sockaddr *)&addr, sizeof(addr)); + AssertFatal(listen(listen_sock, 5) == 0, ""); + return accept(listen_sock,NULL,NULL); +} + +int client_start(char *IP, short port) { + int sock; + AssertFatal((sock = socket(AF_INET, SOCK_STREAM, 0)) >= 0, ""); + struct sockaddr_in addr = { +sin_family: + AF_INET, +sin_port: + htons(port), +sin_addr: + { s_addr: INADDR_ANY } + }; + addr.sin_addr.s_addr = inet_addr(IP); + bool connected=false; + + while(!connected) { + LOG_I(HW,"rfsimulator: trying to connect to %s:%d\n", IP, port); + + if (connect(sock, (struct sockaddr *)&addr, sizeof(addr)) == 0) { + LOG_I(HW,"rfsimulator: connection established\n"); + connected=true; + } + + perror("simulated node"); + sleep(1); + } + + return sock; +} + +enum blocking_t { + notBlocking, + blocking +}; + +void setblocking(int sock, enum blocking_t active) { + int opts; + AssertFatal( (opts = fcntl(sock, F_GETFL)) >= 0,""); + + if (active==blocking) + opts = opts & ~O_NONBLOCK; + else + opts = opts | O_NONBLOCK; + + AssertFatal(fcntl(sock, F_SETFL, opts) >= 0, ""); +} + +int main(int argc, char *argv[]) { + if(argc != 4) { + printf("Need parameters: source file, server or destination IP, TCP port\n"); + exit(1); + } + + int fd; + AssertFatal((fd=open(argv[1],O_RDONLY)) != -1, "file: %s", argv[1]); + off_t fileSize=lseek(fd, 0, SEEK_END); + int serviceSock; + + if (strcmp(argv[2],"server")==0) { + serviceSock=server_start(atoi(argv[3])); + } else { + client_start(argv[2],atoi(argv[3])); + } + + samplesBlockHeader_t header; + int bufSize=100000; + void *buff=malloc(bufSize); + + while (1) { + //Rewind the file to loop on the samples + if ( lseek(fd, 0, SEEK_CUR) >= fileSize ) + lseek(fd, 0, SEEK_SET); + + // Read one block and send it + setblocking(serviceSock, blocking); + AssertFatal(read(fd,&header,sizeof(header)), ""); + fullwrite(serviceSock, &header, sizeof(header)); + int dataSize=sizeof(sample_t)*header.size*header.nbAnt; + + if (dataSize>bufSize) + buff=realloc(buff,dataSize); + + AssertFatal(read(fd,buff,dataSize) == dataSize, ""); + fullwrite(serviceSock, buff, dataSize); + // Purge incoming samples + setblocking(serviceSock, notBlocking); + + while(recv(serviceSock,buff, bufSize, MSG_DONTWAIT) > 0) { + } + } + + return 0; +} + diff --git a/targets/RT/USER/lte-softmodem-common.c b/targets/RT/USER/lte-softmodem-common.c index f152e7c83d..3413d6322c 100644 --- a/targets/RT/USER/lte-softmodem-common.c +++ b/targets/RT/USER/lte-softmodem-common.c @@ -37,6 +37,7 @@ static softmodem_params_t softmodem_params; char *parallel_config=NULL; char *worker_config=NULL; +double snr_dB=25; uint64_t get_softmodem_optmask(void) { return softmodem_params.optmask; diff --git a/targets/RT/USER/lte-softmodem.h b/targets/RT/USER/lte-softmodem.h index e25cbed0b7..f44dd39d4d 100644 --- a/targets/RT/USER/lte-softmodem.h +++ b/targets/RT/USER/lte-softmodem.h @@ -150,7 +150,6 @@ {"usrp-clksrc", CONFIG_HLP_USRP_CLK_SRC,0, strptr:(char **)&usrp_clksrc, defstrval:"internal", TYPE_STRING, 0}, \ {"mmapped-dma", CONFIG_HLP_DMAMAP, PARAMFLAG_BOOL, uptr:&mmapped_dma, defintval:0, TYPE_INT, 0}, \ {"clock", CONFIG_HLP_CLK, 0, uptr:&clock_source, defintval:0, TYPE_UINT, 0}, \ - {"s" , CONFIG_HLP_SNR, 0, iptr:&snr_dB, defintval:25, TYPE_INT, 0}, \ {"T" , CONFIG_HLP_TDD, PARAMFLAG_BOOL, iptr:&tddflag, defintval:0, TYPE_INT, 0}, \ {"A", CONFIG_HLP_TADV, 0, iptr:&(timingadv), defintval:0, TYPE_INT, 0} \ } @@ -197,6 +196,7 @@ {"d" , CONFIG_HLP_SOFTS, PARAMFLAG_BOOL, uptr:(uint32_t *)&do_forms, defintval:0, TYPE_INT8, 0}, \ {"q" , CONFIG_HLP_STMON, PARAMFLAG_BOOL, iptr:&opp_enabled, defintval:0, TYPE_INT, 0}, \ {"S" , CONFIG_HLP_MSLOTS, PARAMFLAG_BOOL, u8ptr:&exit_missed_slots, defintval:1, TYPE_UINT8, 0}, \ + {"s" , CONFIG_HLP_SNR, 0, dblptr:&snr_dB, defdblval:25, TYPE_DOUBLE, 0}, \ {"numerology" , CONFIG_HLP_NUMEROLOGY, PARAMFLAG_BOOL, iptr:&NUMEROLOGY, defintval:0, TYPE_INT, 0}, \ {"parallel-config", CONFIG_HLP_PARALLEL_CMD,0, strptr:(char **)¶llel_config, defstrval:NULL, TYPE_STRING, 0}, \ {"worker-config", CONFIG_HLP_WORKER_CMD, 0, strptr:(char **)&worker_config, defstrval:NULL, TYPE_STRING, 0}, \ @@ -277,6 +277,7 @@ uint64_t get_pdcp_optmask(void); extern pthread_cond_t sync_cond; extern pthread_mutex_t sync_mutex; extern int sync_var; +extern double snr_dB; extern uint32_t downlink_frequency[MAX_NUM_CCs][4]; diff --git a/targets/RT/USER/lte-uesoftmodem.c b/targets/RT/USER/lte-uesoftmodem.c index 74380913dd..dd9eee7077 100644 --- a/targets/RT/USER/lte-uesoftmodem.c +++ b/targets/RT/USER/lte-uesoftmodem.c @@ -131,7 +131,6 @@ int32_t uplink_frequency_offset[MAX_NUM_CCs][4]; int UE_scan = 1; int UE_scan_carrier = 0; -int snr_dB=25; runmode_t mode = normal_txrx; @@ -810,7 +809,7 @@ int main( int argc, char **argv ) { //p_exmimo_config->framing.tdd_config = TXRXSWITCH_TESTRX; if (IS_SOFTMODEM_SIML1 ) { - init_ocm((double)snr_dB,0); + init_ocm(snr_dB,0); PHY_vars_UE_g[0][0]->no_timing_correction = 1; } From 9ec157d9e1983c81d2e82f6b7762ec2d9d63bf10 Mon Sep 17 00:00:00 2001 From: Konstantinos Alexandris Date: Mon, 8 Apr 2019 15:19:13 +0200 Subject: [PATCH 02/32] Add neighbouring cells (cgi,plmn), clean-up a bit current RRC CM --- .../CONTROL_MODULES/RRC/flexran_agent_rrc.c | 166 ++++++++---------- openair2/ENB_APP/flexran_agent_ran_api.c | 118 ++++++++++--- openair2/ENB_APP/flexran_agent_ran_api.h | 28 ++- 3 files changed, 189 insertions(+), 123 deletions(-) diff --git a/openair2/ENB_APP/CONTROL_MODULES/RRC/flexran_agent_rrc.c b/openair2/ENB_APP/CONTROL_MODULES/RRC/flexran_agent_rrc.c index fc8a9ba337..14f3360fc0 100644 --- a/openair2/ENB_APP/CONTROL_MODULES/RRC/flexran_agent_rrc.c +++ b/openair2/ENB_APP/CONTROL_MODULES/RRC/flexran_agent_rrc.c @@ -19,7 +19,7 @@ * contact@openairinterface.org */ -/*! \file flexran_agent_mac.c +/*! \file flexran_agent_rrc.c * \brief FlexRAN agent Control Module RRC * \author shahab SHARIAT BAGHERI * \date 2017 @@ -381,7 +381,7 @@ int flexran_agent_rrc_stats_reply(mid_t mod_id, /* Check flag for creation of buffer status report */ if (report_config->ue_report_type[i].ue_report_flags & PROTOCOL__FLEX_UE_STATS_TYPE__FLUST_RRC_MEASUREMENTS) { - /*Source Cell*/ + /*Source cell EUTRA Measurements*/ Protocol__FlexRrcMeasurements *rrc_measurements; rrc_measurements = malloc(sizeof(Protocol__FlexRrcMeasurements)); if (rrc_measurements == NULL) @@ -397,7 +397,7 @@ int flexran_agent_rrc_stats_reply(mid_t mod_id, rrc_measurements->pcell_rsrq = flexran_get_rrc_pcell_rsrq(mod_id, rnti); rrc_measurements->has_pcell_rsrq = 1 ; - /* Target Cell, Neghibouring*/ + /* Neighbouring cells EUTRA Measurements*/ Protocol__FlexNeighCellsMeasurements *neigh_meas; neigh_meas = malloc(sizeof(Protocol__FlexNeighCellsMeasurements)); if (neigh_meas == NULL) { @@ -406,13 +406,12 @@ int flexran_agent_rrc_stats_reply(mid_t mod_id, goto error; } protocol__flex_neigh_cells_measurements__init(neigh_meas); - neigh_meas->n_eutra_meas = flexran_get_rrc_num_ncell(mod_id, rnti); Protocol__FlexEutraMeasurements **eutra_meas = NULL; - if (neigh_meas->n_eutra_meas > 0){ + if (neigh_meas->n_eutra_meas > 0) { eutra_meas = malloc(sizeof(Protocol__FlexEutraMeasurements) * neigh_meas->n_eutra_meas); if (eutra_meas == NULL) { @@ -422,117 +421,103 @@ int flexran_agent_rrc_stats_reply(mid_t mod_id, goto error; } - for (int j = 0; j < neigh_meas->n_eutra_meas; j++ ){ + for (int j = 0; j < neigh_meas->n_eutra_meas; j++ ) { + eutra_meas[j] = malloc(sizeof(Protocol__FlexEutraMeasurements)); + if (eutra_meas[j] == NULL) { + for (int k = 0 ; k < j ; k++) + free(eutra_meas[k]); + free(eutra_meas); + free(neigh_meas); + free(rrc_measurements); + rrc_measurements = NULL; + goto error; + } + protocol__flex_eutra_measurements__init(eutra_meas[j]); - eutra_meas[j] = malloc(sizeof(Protocol__FlexEutraMeasurements)); - if (eutra_meas[j] == NULL) { - for (int k = 0 ; k < j ; k++) { - free(eutra_meas[k]); - } - free(eutra_meas); - free(neigh_meas); - free(rrc_measurements); - rrc_measurements = NULL; - goto error; - } + /* Fill in the physical cell identifier. */ + eutra_meas[j]->phys_cell_id = flexran_get_rrc_neigh_phy_cell_id(mod_id, rnti, j); + eutra_meas[j]->has_phys_cell_id = 1; - protocol__flex_eutra_measurements__init(eutra_meas[j]); + /* Initialize CGI measurements. */ + Protocol__FlexEutraCgiMeasurements *cgi_meas; + cgi_meas = malloc(sizeof(Protocol__FlexEutraCgiMeasurements)); - eutra_meas[j]->phys_cell_id = flexran_get_rrc_neigh_phy_cell_id(mod_id, rnti, j); - eutra_meas[j]->has_phys_cell_id = 1; + protocol__flex_eutra_cgi_measurements__init(cgi_meas); + /* EUTRA Cell Global Identity (CGI) */ + Protocol__FlexCellGlobalEutraId *cgi; + cgi = malloc(sizeof(Protocol__FlexCellGlobalEutraId)); - /*TODO: Extend for CGI and PLMNID*/ + protocol__flex_cell_global_eutra_id__init(cgi); - Protocol__FlexEutraRefSignalMeas *meas_result; - meas_result = malloc(sizeof(Protocol__FlexEutraRefSignalMeas)); + cgi->cell_id = flexran_get_rrc_neigh_cgi_cell_id(mod_id, rnti, eutra_meas[j]->phys_cell_id); + cgi->has_cell_id = 1; - protocol__flex_eutra_ref_signal_meas__init(meas_result); + cgi_meas->tracking_area_code = flexran_get_rrc_neigh_cgi_tac(mod_id, rnti, eutra_meas[j]->phys_cell_id); + cgi_meas->has_tracking_area_code = 1; - meas_result->rsrp = flexran_get_rrc_neigh_rsrp(mod_id, rnti, eutra_meas[j]->phys_cell_id); - meas_result->has_rsrp = 1; + /* PLMN for neighbouring cell */ + Protocol__FlexPlmnIdentity *plmn_id; + plmn_id = malloc(sizeof(Protocol__FlexPlmnIdentity)); - meas_result->rsrq = flexran_get_rrc_neigh_rsrq(mod_id, rnti, eutra_meas[j]->phys_cell_id); - meas_result->has_rsrq = 1; + protocol__flex_plmn_identity__init(plmn_id); - eutra_meas[j]->meas_result = meas_result; - - } + plmn_id->mcc = 0; + for (int m = 0; m < flexran_get_rrc_neigh_cgi_num_mcc(mod_id, rnti, eutra_meas[j]->phys_cell_id); m++) { + plmn_id->mcc += flexran_get_rrc_neigh_cgi_mcc(mod_id, rnti, eutra_meas[j]->phys_cell_id, m); + } - neigh_meas->eutra_meas = eutra_meas; + plmn_id->mnc = 0; + for (int m = 0; m < flexran_get_rrc_neigh_cgi_num_mnc(mod_id, rnti, eutra_meas[j]->phys_cell_id); m++) { + plmn_id->mnc += flexran_get_rrc_neigh_cgi_mnc(mod_id, rnti, eutra_meas[j]->phys_cell_id, m); + } - rrc_measurements->neigh_meas = neigh_meas; - + /*RSRP/RSRQ of the neighbouring cell */ + Protocol__FlexEutraRefSignalMeas *meas_result; + meas_result = malloc(sizeof(Protocol__FlexEutraRefSignalMeas)); + + protocol__flex_eutra_ref_signal_meas__init(meas_result); + + meas_result->rsrp = flexran_get_rrc_neigh_rsrp(mod_id, rnti, eutra_meas[j]->phys_cell_id); + meas_result->has_rsrp = 1; + + meas_result->rsrq = flexran_get_rrc_neigh_rsrq(mod_id, rnti, eutra_meas[j]->phys_cell_id); + meas_result->has_rsrq = 1; + + eutra_meas[j]->cgi_meas = cgi_meas; + eutra_meas[j]->meas_result = meas_result; + } + + neigh_meas->eutra_meas = eutra_meas; + + rrc_measurements->neigh_meas = neigh_meas; } else { free(neigh_meas); } - ue_report[i]->rrc_measurements = rrc_measurements; - ue_report[i]->flags |= PROTOCOL__FLEX_UE_STATS_TYPE__FLUST_RRC_MEASUREMENTS; - + ue_report[i]->rrc_measurements = rrc_measurements; + ue_report[i]->flags |= PROTOCOL__FLEX_UE_STATS_TYPE__FLUST_RRC_MEASUREMENTS; } - - } - + } } - /* To be considered for RRC signaling of cell*/ - // if (report_config->nr_cc > 0) { - - - // // Fill in the Cell reports - // for (i = 0; i < report_config->nr_cc; i++) { - - - // /* Check flag for creation of noise and interference report */ - // if(report_config->cc_report_type[i].cc_report_flags & PROTOCOL__FLEX_CELL_STATS_TYPE__FLCST_NOISE_INTERFERENCE) { - // // TODO: Fill in the actual noise and interference report for this cell - // Protocol__FlexNoiseInterferenceReport *ni_report; - // ni_report = malloc(sizeof(Protocol__FlexNoiseInterferenceReport)); - // if(ni_report == NULL) - // goto error; - // protocol__flex_noise_interference_report__init(ni_report); - // // Current frame and subframe number - // ni_report->sfn_sf = flexran_get_sfn_sf(enb_id); - // ni_report->has_sfn_sf = 1; - // //TODO:Received interference power in dbm - // ni_report->rip = 0; - // ni_report->has_rip = 1; - // //TODO:Thermal noise power in dbm - // ni_report->tnp = 0; - // ni_report->has_tnp = 1; - - // ni_report->p0_nominal_pucch = flexran_get_p0_nominal_pucch(enb_id, 0); - // ni_report->has_p0_nominal_pucch = 1; - // cell_report[i]->noise_inter_report = ni_report; - // cell_report[i]->flags |= PROTOCOL__FLEX_CELL_STATS_TYPE__FLCST_NOISE_INTERFERENCE; - // } - // } - - - - - // } - return 0; error: - for (int i = 0; i < report_config->nr_ue; i++){ - - if (ue_report[i]->rrc_measurements && ue_report[i]->rrc_measurements->neigh_meas != NULL){ - for (int j = 0; j < ue_report[i]->rrc_measurements->neigh_meas->n_eutra_meas; j++){ - - free(ue_report[i]->rrc_measurements->neigh_meas->eutra_meas[j]); - } - free(ue_report[i]->rrc_measurements->neigh_meas); + for (int i = 0; i < report_config->nr_ue; i++) { + if (ue_report[i]->rrc_measurements && ue_report[i]->rrc_measurements->neigh_meas != NULL) { + for (int j = 0; j < ue_report[i]->rrc_measurements->neigh_meas->n_eutra_meas; j++) { + free(ue_report[i]->rrc_measurements->neigh_meas->eutra_meas[j]); } + free(ue_report[i]->rrc_measurements->neigh_meas); + } } if (cell_report != NULL) - free(cell_report); + free(cell_report); if (ue_report != NULL) - free(ue_report); + free(ue_report); return -1; } @@ -540,8 +525,9 @@ int flexran_agent_rrc_stats_reply(mid_t mod_id, int flexran_agent_rrc_destroy_stats_reply(Protocol__FlexStatsReply *reply) { for (int i = 0; i < reply->n_ue_report; i++){ - if (reply->ue_report[i]->rrc_measurements && reply->ue_report[i]->rrc_measurements->neigh_meas){ - for (int j = 0; j < reply->ue_report[i]->rrc_measurements->neigh_meas->n_eutra_meas; j++){ + if (reply->ue_report[i]->rrc_measurements && reply->ue_report[i]->rrc_measurements->neigh_meas) { + for (int j = 0; j < reply->ue_report[i]->rrc_measurements->neigh_meas->n_eutra_meas; j++) { + free(reply->ue_report[i]->rrc_measurements->neigh_meas->eutra_meas[j]->cgi_meas); free(reply->ue_report[i]->rrc_measurements->neigh_meas->eutra_meas[j]->meas_result); free(reply->ue_report[i]->rrc_measurements->neigh_meas->eutra_meas[j]); } diff --git a/openair2/ENB_APP/flexran_agent_ran_api.c b/openair2/ENB_APP/flexran_agent_ran_api.c index 500f4f1f3a..687fad690a 100644 --- a/openair2/ENB_APP/flexran_agent_ran_api.c +++ b/openair2/ENB_APP/flexran_agent_ran_api.c @@ -1435,8 +1435,7 @@ uint32_t flexran_get_pdcp_rx_oo(mid_t mod_id, uint16_t uid, lcid_t lcid) /******************** RRC *****************************/ -LTE_MeasId_t flexran_get_rrc_pcell_measid(mid_t mod_id, rnti_t rnti) -{ +LTE_MeasId_t flexran_get_rrc_pcell_measid(mid_t mod_id, rnti_t rnti) { if (!rrc_is_present(mod_id)) return -1; struct rrc_eNB_ue_context_s* ue_context_p = rrc_eNB_get_ue_context(RC.rrc[mod_id], rnti); if (!ue_context_p) return -1; @@ -1444,27 +1443,32 @@ LTE_MeasId_t flexran_get_rrc_pcell_measid(mid_t mod_id, rnti_t rnti) return ue_context_p->ue_context.measResults->measId; } -float flexran_get_rrc_pcell_rsrp(mid_t mod_id, rnti_t rnti) -{ +float flexran_get_rrc_pcell_rsrp(mid_t mod_id, rnti_t rnti) { if (!rrc_is_present(mod_id)) return -1; struct rrc_eNB_ue_context_s* ue_context_p = rrc_eNB_get_ue_context(RC.rrc[mod_id], rnti); if (!ue_context_p) return -1; if (!ue_context_p->ue_context.measResults) return -1; - return RSRP_meas_mapping[ue_context_p->ue_context.measResults->measResultPCell.rsrpResult]; + #if (LTE_RRC_VERSION >= MAKE_VERSION(10, 0, 0)) + return RSRP_meas_mapping[ue_context_p->ue_context.measResults->measResultPCell.rsrpResult]; + #else + return RSRP_meas_mapping[ue_context_p->ue_context.measResults->measResultServCell.rsrpResult]; + #endif } -float flexran_get_rrc_pcell_rsrq(mid_t mod_id, rnti_t rnti) -{ +float flexran_get_rrc_pcell_rsrq(mid_t mod_id, rnti_t rnti) { if (!rrc_is_present(mod_id)) return -1; struct rrc_eNB_ue_context_s* ue_context_p = rrc_eNB_get_ue_context(RC.rrc[mod_id], rnti); if (!ue_context_p) return -1; if (!ue_context_p->ue_context.measResults) return -1; - return RSRQ_meas_mapping[ue_context_p->ue_context.measResults->measResultPCell.rsrqResult]; + #if (LTE_RRC_VERSION >= MAKE_VERSION(10, 0, 0)) + return RSRQ_meas_mapping[ue_context_p->ue_context.measResults->measResultPCell.rsrqResult]; + #else + return RSRQ_meas_mapping[ue_context_p->ue_context.measResults->measResultServCell.rsrqResult]; + #endif } /*Number of neighbouring cells for specific UE*/ -int flexran_get_rrc_num_ncell(mid_t mod_id, rnti_t rnti) -{ +int flexran_get_rrc_num_ncell(mid_t mod_id, rnti_t rnti) { if (!rrc_is_present(mod_id)) return 0; struct rrc_eNB_ue_context_s* ue_context_p = rrc_eNB_get_ue_context(RC.rrc[mod_id], rnti); if (!ue_context_p) return 0; @@ -1474,8 +1478,7 @@ int flexran_get_rrc_num_ncell(mid_t mod_id, rnti_t rnti) return ue_context_p->ue_context.measResults->measResultNeighCells->choice.measResultListEUTRA.list.count; } -long flexran_get_rrc_neigh_phy_cell_id(mid_t mod_id, rnti_t rnti, long cell_id) -{ +long flexran_get_rrc_neigh_phy_cell_id(mid_t mod_id, rnti_t rnti, long cell_id) { if (!rrc_is_present(mod_id)) return -1; struct rrc_eNB_ue_context_s* ue_context_p = rrc_eNB_get_ue_context(RC.rrc[mod_id], rnti); if (!ue_context_p) return -1; @@ -1486,8 +1489,80 @@ long flexran_get_rrc_neigh_phy_cell_id(mid_t mod_id, rnti_t rnti, long cell_id) return ue_context_p->ue_context.measResults->measResultNeighCells->choice.measResultListEUTRA.list.array[cell_id]->physCellId; } -float flexran_get_rrc_neigh_rsrp(mid_t mod_id, rnti_t rnti, long cell_id) -{ +uint32_t flexran_get_rrc_neigh_cgi_cell_id(mid_t mod_id, rnti_t rnti, long cell_id) { + if (!rrc_is_present(mod_id)) return -1; + struct rrc_eNB_ue_context_s* ue_context_p = rrc_eNB_get_ue_context(RC.rrc[mod_id], rnti); + if (!ue_context_p) return -1; + if (!ue_context_p->ue_context.measResults) return -1; + if (!ue_context_p->ue_context.measResults->measResultNeighCells) return -1; + if (ue_context_p->ue_context.measResults->measResultNeighCells->present != LTE_MeasResults__measResultNeighCells_PR_measResultListEUTRA) return -1; + if (!ue_context_p->ue_context.measResults->measResultNeighCells->choice.measResultListEUTRA.list.array[cell_id]) return -1; + uint8_t *cId = ue_context_p->ue_context.measResults->measResultNeighCells->choice.measResultListEUTRA.list.array[cell_id]->cgi_Info->cellGlobalId.cellIdentity.buf; + return ((cId[0] << 20) + (cId[1] << 12) + (cId[2] << 4) + (cId[3] >> 4)); +} + + +uint32_t flexran_get_rrc_neigh_cgi_tac(mid_t mod_id, rnti_t rnti, long cell_id) { + if (!rrc_is_present(mod_id)) return -1; + struct rrc_eNB_ue_context_s* ue_context_p = rrc_eNB_get_ue_context(RC.rrc[mod_id], rnti); + if (!ue_context_p) return -1; + if (!ue_context_p->ue_context.measResults) return -1; + if (!ue_context_p->ue_context.measResults->measResultNeighCells) return -1; + if (ue_context_p->ue_context.measResults->measResultNeighCells->present != LTE_MeasResults__measResultNeighCells_PR_measResultListEUTRA) return -1; + if (!ue_context_p->ue_context.measResults->measResultNeighCells->choice.measResultListEUTRA.list.array[cell_id]) return -1; + uint8_t *tac = ue_context_p->ue_context.measResults->measResultNeighCells->choice.measResultListEUTRA.list.array[cell_id]->cgi_Info->trackingAreaCode.buf; + return (tac[0] << 8) + (tac[1]); +} + +uint32_t flexran_get_rrc_neigh_cgi_num_mnc(mid_t mod_id, rnti_t rnti, long cell_id) { + if (!rrc_is_present(mod_id)) return -1; + struct rrc_eNB_ue_context_s* ue_context_p = rrc_eNB_get_ue_context(RC.rrc[mod_id], rnti); + if (!ue_context_p) return -1; + if (!ue_context_p->ue_context.measResults) return -1; + if (!ue_context_p->ue_context.measResults->measResultNeighCells) return -1; + if (ue_context_p->ue_context.measResults->measResultNeighCells->present != LTE_MeasResults__measResultNeighCells_PR_measResultListEUTRA) return -1; + if (!ue_context_p->ue_context.measResults->measResultNeighCells->choice.measResultListEUTRA.list.array[cell_id]) return -1; + return ue_context_p->ue_context.measResults->measResultNeighCells->choice.measResultListEUTRA.list.array[cell_id]->cgi_Info->cellGlobalId.plmn_Identity.mnc.list.count; +} + +uint32_t flexran_get_rrc_neigh_cgi_num_mcc(mid_t mod_id, rnti_t rnti, long cell_id) { + if (!rrc_is_present(mod_id)) return -1; + struct rrc_eNB_ue_context_s* ue_context_p = rrc_eNB_get_ue_context(RC.rrc[mod_id], rnti); + if (!ue_context_p) return -1; + if (!ue_context_p->ue_context.measResults) return -1; + if (!ue_context_p->ue_context.measResults->measResultNeighCells) return -1; + if (ue_context_p->ue_context.measResults->measResultNeighCells->present != LTE_MeasResults__measResultNeighCells_PR_measResultListEUTRA) return -1; + if (!ue_context_p->ue_context.measResults->measResultNeighCells->choice.measResultListEUTRA.list.array[cell_id]) return -1; + return ue_context_p->ue_context.measResults->measResultNeighCells->choice.measResultListEUTRA.list.array[cell_id]->cgi_Info->cellGlobalId.plmn_Identity.mcc->list.count; +} + +uint32_t flexran_get_rrc_neigh_cgi_mnc(mid_t mod_id, rnti_t rnti, long cell_id, int mnc_id) { + if (!rrc_is_present(mod_id)) return -1; + struct rrc_eNB_ue_context_s* ue_context_p = rrc_eNB_get_ue_context(RC.rrc[mod_id], rnti); + if (!ue_context_p) return -1; + if (!ue_context_p->ue_context.measResults) return -1; + if (!ue_context_p->ue_context.measResults->measResultNeighCells) return -1; + if (ue_context_p->ue_context.measResults->measResultNeighCells->present != LTE_MeasResults__measResultNeighCells_PR_measResultListEUTRA) return -1; + if (!ue_context_p->ue_context.measResults->measResultNeighCells->choice.measResultListEUTRA.list.array[cell_id]) return -1; + int num_mnc = ue_context_p->ue_context.measResults->measResultNeighCells->choice.measResultListEUTRA.list.array[cell_id]->cgi_Info->cellGlobalId.plmn_Identity.mnc.list.count; + return *(ue_context_p->ue_context.measResults->measResultNeighCells->choice.measResultListEUTRA.list.array[cell_id]->cgi_Info->cellGlobalId.plmn_Identity.mnc.list.array[mnc_id]) * + ((uint32_t) pow(10, num_mnc - mnc_id - 1)); +} + +uint32_t flexran_get_rrc_neigh_cgi_mcc(mid_t mod_id, rnti_t rnti, long cell_id, int mcc_id) { + if (!rrc_is_present(mod_id)) return -1; + struct rrc_eNB_ue_context_s* ue_context_p = rrc_eNB_get_ue_context(RC.rrc[mod_id], rnti); + if (!ue_context_p) return -1; + if (!ue_context_p->ue_context.measResults) return -1; + if (!ue_context_p->ue_context.measResults->measResultNeighCells) return -1; + if (ue_context_p->ue_context.measResults->measResultNeighCells->present != LTE_MeasResults__measResultNeighCells_PR_measResultListEUTRA) return -1; + if (!ue_context_p->ue_context.measResults->measResultNeighCells->choice.measResultListEUTRA.list.array[cell_id]) return -1; + int num_mcc = ue_context_p->ue_context.measResults->measResultNeighCells->choice.measResultListEUTRA.list.array[cell_id]->cgi_Info->cellGlobalId.plmn_Identity.mcc->list.count; + return *(ue_context_p->ue_context.measResults->measResultNeighCells->choice.measResultListEUTRA.list.array[cell_id]->cgi_Info->cellGlobalId.plmn_Identity.mcc->list.array[mcc_id]) * + ((uint32_t) pow(10, num_mcc - mcc_id - 1)); +} + +float flexran_get_rrc_neigh_rsrp(mid_t mod_id, rnti_t rnti, long cell_id) { if (!rrc_is_present(mod_id)) return -1; struct rrc_eNB_ue_context_s* ue_context_p = rrc_eNB_get_ue_context(RC.rrc[mod_id], rnti); if (!ue_context_p) return -1; @@ -1499,8 +1574,7 @@ float flexran_get_rrc_neigh_rsrp(mid_t mod_id, rnti_t rnti, long cell_id) return RSRP_meas_mapping[*(ue_context_p->ue_context.measResults->measResultNeighCells->choice.measResultListEUTRA.list.array[cell_id]->measResult.rsrpResult)]; } -float flexran_get_rrc_neigh_rsrq(mid_t mod_id, rnti_t rnti, long cell_id) -{ +float flexran_get_rrc_neigh_rsrq(mid_t mod_id, rnti_t rnti, long cell_id) { if (!rrc_is_present(mod_id)) return -1; struct rrc_eNB_ue_context_s* ue_context_p = rrc_eNB_get_ue_context(RC.rrc[mod_id], rnti); if (!ue_context_p) return -1; @@ -1511,26 +1585,22 @@ float flexran_get_rrc_neigh_rsrq(mid_t mod_id, rnti_t rnti, long cell_id) return RSRQ_meas_mapping[*(ue_context_p->ue_context.measResults->measResultNeighCells->choice.measResultListEUTRA.list.array[cell_id]->measResult.rsrqResult)]; } -uint8_t flexran_get_rrc_num_plmn_ids(mid_t mod_id) -{ +uint8_t flexran_get_rrc_num_plmn_ids(mid_t mod_id) { if (!rrc_is_present(mod_id)) return 0; return RC.rrc[mod_id]->configuration.num_plmn; } -uint16_t flexran_get_rrc_mcc(mid_t mod_id, uint8_t index) -{ +uint16_t flexran_get_rrc_mcc(mid_t mod_id, uint8_t index) { if (!rrc_is_present(mod_id)) return 0; return RC.rrc[mod_id]->configuration.mcc[index]; } -uint16_t flexran_get_rrc_mnc(mid_t mod_id, uint8_t index) -{ +uint16_t flexran_get_rrc_mnc(mid_t mod_id, uint8_t index) { if (!rrc_is_present(mod_id)) return 0; return RC.rrc[mod_id]->configuration.mnc[index]; } -uint8_t flexran_get_rrc_mnc_digit_length(mid_t mod_id, uint8_t index) -{ +uint8_t flexran_get_rrc_mnc_digit_length(mid_t mod_id, uint8_t index) { if (!rrc_is_present(mod_id)) return 0; return RC.rrc[mod_id]->configuration.mnc_digit_length[index]; } diff --git a/openair2/ENB_APP/flexran_agent_ran_api.h b/openair2/ENB_APP/flexran_agent_ran_api.h index a60cdeb994..1d77abd3a4 100644 --- a/openair2/ENB_APP/flexran_agent_ran_api.h +++ b/openair2/ENB_APP/flexran_agent_ran_api.h @@ -510,23 +510,33 @@ float flexran_get_rrc_pcell_rsrq(mid_t mod_id, rnti_t rnti); /* Get RRC neighbouring measurement */ int flexran_get_rrc_num_ncell(mid_t mod_id, rnti_t rnti); -/* Get physical cell id */ +/* Get neighbouring physical cell id */ long flexran_get_rrc_neigh_phy_cell_id(mid_t mod_id, rnti_t rnti, long cell_id); +/* Get neighbouring cgi info cell id */ +uint32_t flexran_get_rrc_neigh_cgi_cell_id(mid_t mod_id, rnti_t rnti, long cell_id); + +/* Get neighbouring cgi info tac */ +uint32_t flexran_get_rrc_neigh_cgi_tac(mid_t mod_id, rnti_t rnti, long cell_id); + +/* Get the number of neighbouring cgi mnc */ +uint32_t flexran_get_rrc_neigh_cgi_num_mnc(mid_t mod_id, rnti_t rnti, long cell_id); + +/* Get the number of neighbouring cgi mcc */ +uint32_t flexran_get_rrc_neigh_cgi_num_mcc(mid_t mod_id, rnti_t rnti, long cell_id); + +/* Get neighbouring cgi mnc */ +uint32_t flexran_get_rrc_neigh_cgi_mnc(mid_t mod_id, rnti_t rnti, long cell_id, int mnc_id); + +/* Get neighbouring cgi mcc */ +uint32_t flexran_get_rrc_neigh_cgi_mcc(mid_t mod_id, rnti_t rnti, long cell_id, int mcc_id); + /* Get RSRP of neighbouring Cell */ float flexran_get_rrc_neigh_rsrp(mid_t mod_id, rnti_t rnti, long cell_id); /* Get RSRQ of neighbouring Cell */ float flexran_get_rrc_neigh_rsrq(mid_t mod_id, rnti_t rnti, long cell_id); -/*Get MCC PLMN identity neighbouring Cell*/ -/* currently not implemented -int flexran_get_rrc_neigh_plmn_mcc(mid_t mod_id, rnti_t rnti, int cell_id); */ - -/*Get MNC PLMN identity neighbouring Cell*/ -/* currently not implemented -int flexran_get_rrc_neigh_plmn_mnc(mid_t mod_id, mid_t ue_id, int cell_id); */ - /* Get number of PLMNs that is broadcasted in SIB1 */ uint8_t flexran_get_rrc_num_plmn_ids(mid_t mod_id); From 7024f289a613c571b20e204c8217b5a2f48d5c57 Mon Sep 17 00:00:00 2001 From: Konstantinos Alexandris Date: Wed, 10 Apr 2019 18:31:59 +0200 Subject: [PATCH 03/32] fixes: segmentation faults issues in RRC CM for RRC Measurement report, clean-up and re-implementation of functions in RAN API --- .../CONTROL_MODULES/RRC/flexran_agent_rrc.c | 66 +++++++++-------- openair2/ENB_APP/flexran_agent_ran_api.c | 72 +++++++------------ openair2/ENB_APP/flexran_agent_ran_api.h | 7 +- 3 files changed, 66 insertions(+), 79 deletions(-) diff --git a/openair2/ENB_APP/CONTROL_MODULES/RRC/flexran_agent_rrc.c b/openair2/ENB_APP/CONTROL_MODULES/RRC/flexran_agent_rrc.c index 14f3360fc0..9df22c6937 100644 --- a/openair2/ENB_APP/CONTROL_MODULES/RRC/flexran_agent_rrc.c +++ b/openair2/ENB_APP/CONTROL_MODULES/RRC/flexran_agent_rrc.c @@ -412,7 +412,6 @@ int flexran_agent_rrc_stats_reply(mid_t mod_id, Protocol__FlexEutraMeasurements **eutra_meas = NULL; if (neigh_meas->n_eutra_meas > 0) { - eutra_meas = malloc(sizeof(Protocol__FlexEutraMeasurements) * neigh_meas->n_eutra_meas); if (eutra_meas == NULL) { free(neigh_meas); @@ -438,38 +437,48 @@ int flexran_agent_rrc_stats_reply(mid_t mod_id, eutra_meas[j]->phys_cell_id = flexran_get_rrc_neigh_phy_cell_id(mod_id, rnti, j); eutra_meas[j]->has_phys_cell_id = 1; - /* Initialize CGI measurements. */ - Protocol__FlexEutraCgiMeasurements *cgi_meas; - cgi_meas = malloc(sizeof(Protocol__FlexEutraCgiMeasurements)); + if (flexran_get_rrc_neigh_cgi(mod_id, rnti, j)) { + /* Initialize CGI measurements. */ + Protocol__FlexEutraCgiMeasurements *cgi_meas; + cgi_meas = malloc(sizeof(Protocol__FlexEutraCgiMeasurements)); - protocol__flex_eutra_cgi_measurements__init(cgi_meas); + protocol__flex_eutra_cgi_measurements__init(cgi_meas); - /* EUTRA Cell Global Identity (CGI) */ - Protocol__FlexCellGlobalEutraId *cgi; - cgi = malloc(sizeof(Protocol__FlexCellGlobalEutraId)); + /* EUTRA Cell Global Identity (CGI) */ + Protocol__FlexCellGlobalEutraId *cgi; + cgi = malloc(sizeof(Protocol__FlexCellGlobalEutraId)); - protocol__flex_cell_global_eutra_id__init(cgi); + protocol__flex_cell_global_eutra_id__init(cgi); - cgi->cell_id = flexran_get_rrc_neigh_cgi_cell_id(mod_id, rnti, eutra_meas[j]->phys_cell_id); - cgi->has_cell_id = 1; + cgi->cell_id = flexran_get_rrc_neigh_cgi_cell_id(mod_id, rnti, j); + cgi->has_cell_id = 1; - cgi_meas->tracking_area_code = flexran_get_rrc_neigh_cgi_tac(mod_id, rnti, eutra_meas[j]->phys_cell_id); - cgi_meas->has_tracking_area_code = 1; + cgi_meas->tracking_area_code = flexran_get_rrc_neigh_cgi_tac(mod_id, rnti, j); + cgi_meas->has_tracking_area_code = 1; - /* PLMN for neighbouring cell */ - Protocol__FlexPlmnIdentity *plmn_id; - plmn_id = malloc(sizeof(Protocol__FlexPlmnIdentity)); + /* PLMN for neighbouring cell */ + Protocol__FlexPlmnIdentity *plmn_id; + plmn_id = malloc(sizeof(Protocol__FlexPlmnIdentity)); - protocol__flex_plmn_identity__init(plmn_id); + protocol__flex_plmn_identity__init(plmn_id); - plmn_id->mcc = 0; - for (int m = 0; m < flexran_get_rrc_neigh_cgi_num_mcc(mod_id, rnti, eutra_meas[j]->phys_cell_id); m++) { - plmn_id->mcc += flexran_get_rrc_neigh_cgi_mcc(mod_id, rnti, eutra_meas[j]->phys_cell_id, m); - } + plmn_id->mcc = 0; + plmn_id->n_mcc = flexran_get_rrc_neigh_cgi_num_mcc(mod_id, rnti, j); - plmn_id->mnc = 0; - for (int m = 0; m < flexran_get_rrc_neigh_cgi_num_mnc(mod_id, rnti, eutra_meas[j]->phys_cell_id); m++) { - plmn_id->mnc += flexran_get_rrc_neigh_cgi_mnc(mod_id, rnti, eutra_meas[j]->phys_cell_id, m); + for (int m = 0; m < plmn_id->n_mcc; m++) { + plmn_id->mcc += flexran_get_rrc_neigh_cgi_mcc(mod_id, rnti, j, m); + } + + plmn_id->mnc = 0; + plmn_id->n_mnc = flexran_get_rrc_neigh_cgi_num_mnc(mod_id, rnti, j); + + for (int m = 0; m < plmn_id->n_mnc; m++) { + plmn_id->mnc += flexran_get_rrc_neigh_cgi_mnc(mod_id, rnti, j, m); + } + + cgi->plmn_id = plmn_id; + cgi_meas->cgi = cgi; + eutra_meas[j]->cgi_meas = cgi_meas; } /*RSRP/RSRQ of the neighbouring cell */ @@ -478,13 +487,12 @@ int flexran_agent_rrc_stats_reply(mid_t mod_id, protocol__flex_eutra_ref_signal_meas__init(meas_result); - meas_result->rsrp = flexran_get_rrc_neigh_rsrp(mod_id, rnti, eutra_meas[j]->phys_cell_id); + meas_result->rsrp = flexran_get_rrc_neigh_rsrp(mod_id, rnti, j); meas_result->has_rsrp = 1; - meas_result->rsrq = flexran_get_rrc_neigh_rsrq(mod_id, rnti, eutra_meas[j]->phys_cell_id); + meas_result->rsrq = flexran_get_rrc_neigh_rsrq(mod_id, rnti, j); meas_result->has_rsrq = 1; - eutra_meas[j]->cgi_meas = cgi_meas; eutra_meas[j]->meas_result = meas_result; } @@ -500,11 +508,8 @@ int flexran_agent_rrc_stats_reply(mid_t mod_id, } } } - return 0; - error: - for (int i = 0; i < report_config->nr_ue; i++) { if (ue_report[i]->rrc_measurements && ue_report[i]->rrc_measurements->neigh_meas != NULL) { for (int j = 0; j < ue_report[i]->rrc_measurements->neigh_meas->n_eutra_meas; j++) { @@ -518,7 +523,6 @@ int flexran_agent_rrc_stats_reply(mid_t mod_id, free(cell_report); if (ue_report != NULL) free(ue_report); - return -1; } diff --git a/openair2/ENB_APP/flexran_agent_ran_api.c b/openair2/ENB_APP/flexran_agent_ran_api.c index 687fad690a..94cdcdab16 100644 --- a/openair2/ENB_APP/flexran_agent_ran_api.c +++ b/openair2/ENB_APP/flexran_agent_ran_api.c @@ -1474,7 +1474,7 @@ int flexran_get_rrc_num_ncell(mid_t mod_id, rnti_t rnti) { if (!ue_context_p) return 0; if (!ue_context_p->ue_context.measResults) return 0; if (!ue_context_p->ue_context.measResults->measResultNeighCells) return 0; - if (ue_context_p->ue_context.measResults->measResultNeighCells->present != LTE_MeasResults__measResultNeighCells_PR_measResultListEUTRA) return 0; + //if (ue_context_p->ue_context.measResults->measResultNeighCells->present != LTE_MeasResults__measResultNeighCells_PR_measResultListEUTRA) return 0; return ue_context_p->ue_context.measResults->measResultNeighCells->choice.measResultListEUTRA.list.count; } @@ -1484,79 +1484,59 @@ long flexran_get_rrc_neigh_phy_cell_id(mid_t mod_id, rnti_t rnti, long cell_id) if (!ue_context_p) return -1; if (!ue_context_p->ue_context.measResults) return -1; if (!ue_context_p->ue_context.measResults->measResultNeighCells) return -1; - if (ue_context_p->ue_context.measResults->measResultNeighCells->present != LTE_MeasResults__measResultNeighCells_PR_measResultListEUTRA) return -1; + //if (ue_context_p->ue_context.measResults->measResultNeighCells->present != LTE_MeasResults__measResultNeighCells_PR_measResultListEUTRA) return -1; if (!ue_context_p->ue_context.measResults->measResultNeighCells->choice.measResultListEUTRA.list.array[cell_id]) return -1; return ue_context_p->ue_context.measResults->measResultNeighCells->choice.measResultListEUTRA.list.array[cell_id]->physCellId; } -uint32_t flexran_get_rrc_neigh_cgi_cell_id(mid_t mod_id, rnti_t rnti, long cell_id) { - if (!rrc_is_present(mod_id)) return -1; +int flexran_get_rrc_neigh_cgi(mid_t mod_id, rnti_t rnti, long cell_id) { + if (!rrc_is_present(mod_id)) return 0; struct rrc_eNB_ue_context_s* ue_context_p = rrc_eNB_get_ue_context(RC.rrc[mod_id], rnti); - if (!ue_context_p) return -1; - if (!ue_context_p->ue_context.measResults) return -1; - if (!ue_context_p->ue_context.measResults->measResultNeighCells) return -1; - if (ue_context_p->ue_context.measResults->measResultNeighCells->present != LTE_MeasResults__measResultNeighCells_PR_measResultListEUTRA) return -1; - if (!ue_context_p->ue_context.measResults->measResultNeighCells->choice.measResultListEUTRA.list.array[cell_id]) return -1; + if (!ue_context_p) return 0; + if (!ue_context_p->ue_context.measResults) return 0; + if (!ue_context_p->ue_context.measResults->measResultNeighCells) return 0; + //if (ue_context_p->ue_context.measResults->measResultNeighCells->present != LTE_MeasResults__measResultNeighCells_PR_measResultListEUTRA) return 0; + if (!ue_context_p->ue_context.measResults->measResultNeighCells->choice.measResultListEUTRA.list.array[cell_id]) return 0; + return (!ue_context_p->ue_context.measResults->measResultNeighCells->choice.measResultListEUTRA.list.array[cell_id]->cgi_Info)?0:1; +} + +uint32_t flexran_get_rrc_neigh_cgi_cell_id(mid_t mod_id, rnti_t rnti, long cell_id) { + struct rrc_eNB_ue_context_s* ue_context_p = rrc_eNB_get_ue_context(RC.rrc[mod_id], rnti); + uint8_t *cId = ue_context_p->ue_context.measResults->measResultNeighCells->choice.measResultListEUTRA.list.array[cell_id]->cgi_Info->cellGlobalId.cellIdentity.buf; return ((cId[0] << 20) + (cId[1] << 12) + (cId[2] << 4) + (cId[3] >> 4)); } - uint32_t flexran_get_rrc_neigh_cgi_tac(mid_t mod_id, rnti_t rnti, long cell_id) { - if (!rrc_is_present(mod_id)) return -1; struct rrc_eNB_ue_context_s* ue_context_p = rrc_eNB_get_ue_context(RC.rrc[mod_id], rnti); - if (!ue_context_p) return -1; - if (!ue_context_p->ue_context.measResults) return -1; - if (!ue_context_p->ue_context.measResults->measResultNeighCells) return -1; - if (ue_context_p->ue_context.measResults->measResultNeighCells->present != LTE_MeasResults__measResultNeighCells_PR_measResultListEUTRA) return -1; - if (!ue_context_p->ue_context.measResults->measResultNeighCells->choice.measResultListEUTRA.list.array[cell_id]) return -1; + uint8_t *tac = ue_context_p->ue_context.measResults->measResultNeighCells->choice.measResultListEUTRA.list.array[cell_id]->cgi_Info->trackingAreaCode.buf; return (tac[0] << 8) + (tac[1]); } -uint32_t flexran_get_rrc_neigh_cgi_num_mnc(mid_t mod_id, rnti_t rnti, long cell_id) { - if (!rrc_is_present(mod_id)) return -1; +int flexran_get_rrc_neigh_cgi_num_mnc(mid_t mod_id, rnti_t rnti, long cell_id) { struct rrc_eNB_ue_context_s* ue_context_p = rrc_eNB_get_ue_context(RC.rrc[mod_id], rnti); - if (!ue_context_p) return -1; - if (!ue_context_p->ue_context.measResults) return -1; - if (!ue_context_p->ue_context.measResults->measResultNeighCells) return -1; - if (ue_context_p->ue_context.measResults->measResultNeighCells->present != LTE_MeasResults__measResultNeighCells_PR_measResultListEUTRA) return -1; - if (!ue_context_p->ue_context.measResults->measResultNeighCells->choice.measResultListEUTRA.list.array[cell_id]) return -1; + return ue_context_p->ue_context.measResults->measResultNeighCells->choice.measResultListEUTRA.list.array[cell_id]->cgi_Info->cellGlobalId.plmn_Identity.mnc.list.count; } -uint32_t flexran_get_rrc_neigh_cgi_num_mcc(mid_t mod_id, rnti_t rnti, long cell_id) { - if (!rrc_is_present(mod_id)) return -1; +int flexran_get_rrc_neigh_cgi_num_mcc(mid_t mod_id, rnti_t rnti, long cell_id) { struct rrc_eNB_ue_context_s* ue_context_p = rrc_eNB_get_ue_context(RC.rrc[mod_id], rnti); - if (!ue_context_p) return -1; - if (!ue_context_p->ue_context.measResults) return -1; - if (!ue_context_p->ue_context.measResults->measResultNeighCells) return -1; - if (ue_context_p->ue_context.measResults->measResultNeighCells->present != LTE_MeasResults__measResultNeighCells_PR_measResultListEUTRA) return -1; - if (!ue_context_p->ue_context.measResults->measResultNeighCells->choice.measResultListEUTRA.list.array[cell_id]) return -1; + return ue_context_p->ue_context.measResults->measResultNeighCells->choice.measResultListEUTRA.list.array[cell_id]->cgi_Info->cellGlobalId.plmn_Identity.mcc->list.count; } uint32_t flexran_get_rrc_neigh_cgi_mnc(mid_t mod_id, rnti_t rnti, long cell_id, int mnc_id) { - if (!rrc_is_present(mod_id)) return -1; struct rrc_eNB_ue_context_s* ue_context_p = rrc_eNB_get_ue_context(RC.rrc[mod_id], rnti); - if (!ue_context_p) return -1; - if (!ue_context_p->ue_context.measResults) return -1; - if (!ue_context_p->ue_context.measResults->measResultNeighCells) return -1; - if (ue_context_p->ue_context.measResults->measResultNeighCells->present != LTE_MeasResults__measResultNeighCells_PR_measResultListEUTRA) return -1; - if (!ue_context_p->ue_context.measResults->measResultNeighCells->choice.measResultListEUTRA.list.array[cell_id]) return -1; + int num_mnc = ue_context_p->ue_context.measResults->measResultNeighCells->choice.measResultListEUTRA.list.array[cell_id]->cgi_Info->cellGlobalId.plmn_Identity.mnc.list.count; return *(ue_context_p->ue_context.measResults->measResultNeighCells->choice.measResultListEUTRA.list.array[cell_id]->cgi_Info->cellGlobalId.plmn_Identity.mnc.list.array[mnc_id]) * ((uint32_t) pow(10, num_mnc - mnc_id - 1)); } uint32_t flexran_get_rrc_neigh_cgi_mcc(mid_t mod_id, rnti_t rnti, long cell_id, int mcc_id) { - if (!rrc_is_present(mod_id)) return -1; struct rrc_eNB_ue_context_s* ue_context_p = rrc_eNB_get_ue_context(RC.rrc[mod_id], rnti); - if (!ue_context_p) return -1; - if (!ue_context_p->ue_context.measResults) return -1; - if (!ue_context_p->ue_context.measResults->measResultNeighCells) return -1; - if (ue_context_p->ue_context.measResults->measResultNeighCells->present != LTE_MeasResults__measResultNeighCells_PR_measResultListEUTRA) return -1; - if (!ue_context_p->ue_context.measResults->measResultNeighCells->choice.measResultListEUTRA.list.array[cell_id]) return -1; + int num_mcc = ue_context_p->ue_context.measResults->measResultNeighCells->choice.measResultListEUTRA.list.array[cell_id]->cgi_Info->cellGlobalId.plmn_Identity.mcc->list.count; return *(ue_context_p->ue_context.measResults->measResultNeighCells->choice.measResultListEUTRA.list.array[cell_id]->cgi_Info->cellGlobalId.plmn_Identity.mcc->list.array[mcc_id]) * ((uint32_t) pow(10, num_mcc - mcc_id - 1)); @@ -1568,9 +1548,9 @@ float flexran_get_rrc_neigh_rsrp(mid_t mod_id, rnti_t rnti, long cell_id) { if (!ue_context_p) return -1; if (!ue_context_p->ue_context.measResults) return -1; if (!ue_context_p->ue_context.measResults->measResultNeighCells) return -1; - if (ue_context_p->ue_context.measResults->measResultNeighCells->present != LTE_MeasResults__measResultNeighCells_PR_measResultListEUTRA) return -1; + //if (ue_context_p->ue_context.measResults->measResultNeighCells->present != LTE_MeasResults__measResultNeighCells_PR_measResultListEUTRA) return -1; if (!ue_context_p->ue_context.measResults->measResultNeighCells->choice.measResultListEUTRA.list.array[cell_id]) return -1; - if (!ue_context_p->ue_context.measResults->measResultNeighCells->choice.measResultListEUTRA.list.array[cell_id]->measResult.rsrpResult) return 0; + if (!ue_context_p->ue_context.measResults->measResultNeighCells->choice.measResultListEUTRA.list.array[cell_id]->measResult.rsrpResult) return -1; return RSRP_meas_mapping[*(ue_context_p->ue_context.measResults->measResultNeighCells->choice.measResultListEUTRA.list.array[cell_id]->measResult.rsrpResult)]; } @@ -1580,8 +1560,8 @@ float flexran_get_rrc_neigh_rsrq(mid_t mod_id, rnti_t rnti, long cell_id) { if (!ue_context_p) return -1; if (!ue_context_p->ue_context.measResults) return -1; if (!ue_context_p->ue_context.measResults->measResultNeighCells) return -1; - if (ue_context_p->ue_context.measResults->measResultNeighCells->present != LTE_MeasResults__measResultNeighCells_PR_measResultListEUTRA) return -1; - if (!ue_context_p->ue_context.measResults->measResultNeighCells->choice.measResultListEUTRA.list.array[cell_id]->measResult.rsrqResult) return 0; + //if (ue_context_p->ue_context.measResults->measResultNeighCells->present != LTE_MeasResults__measResultNeighCells_PR_measResultListEUTRA) return -1; + if (!ue_context_p->ue_context.measResults->measResultNeighCells->choice.measResultListEUTRA.list.array[cell_id]->measResult.rsrqResult) return -1; return RSRQ_meas_mapping[*(ue_context_p->ue_context.measResults->measResultNeighCells->choice.measResultListEUTRA.list.array[cell_id]->measResult.rsrqResult)]; } diff --git a/openair2/ENB_APP/flexran_agent_ran_api.h b/openair2/ENB_APP/flexran_agent_ran_api.h index 1d77abd3a4..7c6d008f06 100644 --- a/openair2/ENB_APP/flexran_agent_ran_api.h +++ b/openair2/ENB_APP/flexran_agent_ran_api.h @@ -513,6 +513,9 @@ int flexran_get_rrc_num_ncell(mid_t mod_id, rnti_t rnti); /* Get neighbouring physical cell id */ long flexran_get_rrc_neigh_phy_cell_id(mid_t mod_id, rnti_t rnti, long cell_id); +/* Get neighbouring cgi */ +int flexran_get_rrc_neigh_cgi(mid_t mod_id, rnti_t rnti, long cell_id); + /* Get neighbouring cgi info cell id */ uint32_t flexran_get_rrc_neigh_cgi_cell_id(mid_t mod_id, rnti_t rnti, long cell_id); @@ -520,10 +523,10 @@ uint32_t flexran_get_rrc_neigh_cgi_cell_id(mid_t mod_id, rnti_t rnti, long cell_ uint32_t flexran_get_rrc_neigh_cgi_tac(mid_t mod_id, rnti_t rnti, long cell_id); /* Get the number of neighbouring cgi mnc */ -uint32_t flexran_get_rrc_neigh_cgi_num_mnc(mid_t mod_id, rnti_t rnti, long cell_id); +int flexran_get_rrc_neigh_cgi_num_mnc(mid_t mod_id, rnti_t rnti, long cell_id); /* Get the number of neighbouring cgi mcc */ -uint32_t flexran_get_rrc_neigh_cgi_num_mcc(mid_t mod_id, rnti_t rnti, long cell_id); +int flexran_get_rrc_neigh_cgi_num_mcc(mid_t mod_id, rnti_t rnti, long cell_id); /* Get neighbouring cgi mnc */ uint32_t flexran_get_rrc_neigh_cgi_mnc(mid_t mod_id, rnti_t rnti, long cell_id, int mnc_id); From 0eeee616d8918b42fc50ac281cd1f32464b1cb4c Mon Sep 17 00:00:00 2001 From: Konstantinos Alexandris Date: Thu, 18 Apr 2019 18:18:43 +0200 Subject: [PATCH 04/32] Create RRC struct and getters for Periodic, A1-A5 event and offsets related to RRC Measurement Report --- openair2/ENB_APP/flexran_agent_ran_api.c | 96 ++++++++++++++++++++++++ openair2/ENB_APP/flexran_agent_ran_api.h | 30 ++++++++ openair2/RRC/LTE/rrc_defs.h | 66 ++++++++++++++++ 3 files changed, 192 insertions(+) diff --git a/openair2/ENB_APP/flexran_agent_ran_api.c b/openair2/ENB_APP/flexran_agent_ran_api.c index 94cdcdab16..9e706302f3 100644 --- a/openair2/ENB_APP/flexran_agent_ran_api.c +++ b/openair2/ENB_APP/flexran_agent_ran_api.c @@ -1565,6 +1565,102 @@ float flexran_get_rrc_neigh_rsrq(mid_t mod_id, rnti_t rnti, long cell_id) { return RSRQ_meas_mapping[*(ue_context_p->ue_context.measResults->measResultNeighCells->choice.measResultListEUTRA.list.array[cell_id]->measResult.rsrqResult)]; } +long flexran_get_rrc_ofp(mid_t mod_id, rnti_t rnti) { + if (!rrc_is_present(mod_id)) return -1; + struct rrc_eNB_ue_context_s* ue_context_p = rrc_eNB_get_ue_context(RC.rrc[mod_id], rnti); + if (!ue_context_p) return -1; + if (!ue_context_p->ue_context.measurement_info) return -1; + return ue_context_p->ue_context.measurement_info->offsetFreq; +} + +long flexran_get_rrc_ofn(mid_t mod_id, rnti_t rnti) { + if (!rrc_is_present(mod_id)) return -1; + struct rrc_eNB_ue_context_s* ue_context_p = rrc_eNB_get_ue_context(RC.rrc[mod_id], rnti); + if (!ue_context_p) return -1; + if (!ue_context_p->ue_context.measurement_info) return -1; + return ue_context_p->ue_context.measurement_info->offsetFreq; +} + +long flexran_get_rrc_ocp(mid_t mod_id, rnti_t rnti) { + if (!rrc_is_present(mod_id)) return -1; + struct rrc_eNB_ue_context_s* ue_context_p = rrc_eNB_get_ue_context(RC.rrc[mod_id], rnti); + if (!ue_context_p) return -1; + if (!ue_context_p->ue_context.measurement_info) return -1; + return ue_context_p->ue_context.measurement_info->cellIndividualOffset; +} + +long flexran_get_rrc_ocn(mid_t mod_id, rnti_t rnti) { + if (!rrc_is_present(mod_id)) return -1; + struct rrc_eNB_ue_context_s* ue_context_p = rrc_eNB_get_ue_context(RC.rrc[mod_id], rnti); + if (!ue_context_p) return -1; + if (!ue_context_p->ue_context.measurement_info) return -1; + return ue_context_p->ue_context.measurement_info->cellIndividualOffset; +} + +/* Periodic event */ + +long flexran_get_rrc_per_event_maxReportCells(mid_t mod_id, rnti_t rnti) { + if (!rrc_is_present(mod_id)) return -1; + struct rrc_eNB_ue_context_s* ue_context_p = rrc_eNB_get_ue_context(RC.rrc[mod_id], rnti); + if (!ue_context_p) return -1; + if (!ue_context_p->ue_context.measurement_info) return -1; + if (!ue_context_p->ue_context.measurement_info->events) return -1; + if (!ue_context_p->ue_context.measurement_info->events->per_event) return -1; + return ue_context_p->ue_context.measurement_info->events->per_event->maxReportCells; +} + +/* A3 event */ + +long flexran_get_rrc_a3_event_hysteresis(mid_t mod_id, rnti_t rnti) { + if (!rrc_is_present(mod_id)) return -1; + struct rrc_eNB_ue_context_s* ue_context_p = rrc_eNB_get_ue_context(RC.rrc[mod_id], rnti); + if (!ue_context_p) return -1; + if (!ue_context_p->ue_context.measurement_info) return -1; + if (!ue_context_p->ue_context.measurement_info->events) return -1; + if (!ue_context_p->ue_context.measurement_info->events->a3_event) return -1; + return ue_context_p->ue_context.measurement_info->events->a3_event->hysteresis; +} + +long flexran_get_rrc_a3_event_timeToTrigger(mid_t mod_id, rnti_t rnti) { + if (!rrc_is_present(mod_id)) return -1; + struct rrc_eNB_ue_context_s* ue_context_p = rrc_eNB_get_ue_context(RC.rrc[mod_id], rnti); + if (!ue_context_p) return -1; + if (!ue_context_p->ue_context.measurement_info) return -1; + if (!ue_context_p->ue_context.measurement_info->events) return -1; + if (!ue_context_p->ue_context.measurement_info->events->a3_event) return -1; + return ue_context_p->ue_context.measurement_info->events->a3_event->timeToTrigger; +} + +long flexran_get_rrc_a3_event_maxReportCells(mid_t mod_id, rnti_t rnti) { + if (!rrc_is_present(mod_id)) return -1; + struct rrc_eNB_ue_context_s* ue_context_p = rrc_eNB_get_ue_context(RC.rrc[mod_id], rnti); + if (!ue_context_p) return -1; + if (!ue_context_p->ue_context.measurement_info) return -1; + if (!ue_context_p->ue_context.measurement_info->events) return -1; + if (!ue_context_p->ue_context.measurement_info->events->a3_event) return -1; + return ue_context_p->ue_context.measurement_info->events->a3_event->maxReportCells; +} + +long flexran_get_rrc_a3_event_a3_offset(mid_t mod_id, rnti_t rnti) { + if (!rrc_is_present(mod_id)) return -1; + struct rrc_eNB_ue_context_s* ue_context_p = rrc_eNB_get_ue_context(RC.rrc[mod_id], rnti); + if (!ue_context_p) return -1; + if (!ue_context_p->ue_context.measurement_info) return -1; + if (!ue_context_p->ue_context.measurement_info->events) return -1; + if (!ue_context_p->ue_context.measurement_info->events->a3_event) return -1; + return ue_context_p->ue_context.measurement_info->events->a3_event->a3_offset; +} + +int flexran_get_rrc_a3_event_reportOnLeave(mid_t mod_id, rnti_t rnti) { + if (!rrc_is_present(mod_id)) return -1; + struct rrc_eNB_ue_context_s* ue_context_p = rrc_eNB_get_ue_context(RC.rrc[mod_id], rnti); + if (!ue_context_p) return -1; + if (!ue_context_p->ue_context.measurement_info) return -1; + if (!ue_context_p->ue_context.measurement_info->events) return -1; + if (!ue_context_p->ue_context.measurement_info->events->a3_event) return -1; + return ue_context_p->ue_context.measurement_info->events->a3_event->reportOnLeave; +} + uint8_t flexran_get_rrc_num_plmn_ids(mid_t mod_id) { if (!rrc_is_present(mod_id)) return 0; return RC.rrc[mod_id]->configuration.num_plmn; diff --git a/openair2/ENB_APP/flexran_agent_ran_api.h b/openair2/ENB_APP/flexran_agent_ran_api.h index 7c6d008f06..0eee42bc2d 100644 --- a/openair2/ENB_APP/flexran_agent_ran_api.h +++ b/openair2/ENB_APP/flexran_agent_ran_api.h @@ -540,6 +540,36 @@ float flexran_get_rrc_neigh_rsrp(mid_t mod_id, rnti_t rnti, long cell_id); /* Get RSRQ of neighbouring Cell */ float flexran_get_rrc_neigh_rsrq(mid_t mod_id, rnti_t rnti, long cell_id); +/* Get ofp offset */ +long flexran_get_rrc_ofp(mid_t mod_id, rnti_t rnti); + +/* Get ofn offset */ +long flexran_get_rrc_ofn(mid_t mod_id, rnti_t rnti); + +/* Get ocp offset */ +long flexran_get_rrc_ocp(mid_t mod_id, rnti_t rnti); + +/* Get ocn offset */ +long flexran_get_rrc_ocn(mid_t mod_id, rnti_t rnti); + +/* Get Periodic Event max reported cells */ +long flexran_get_rrc_per_event_maxReportCells(mid_t mod_id, rnti_t rnti); + +/* Get A3 Event hysteresis */ +long flexran_get_rrc_a3_event_hysteresis(mid_t mod_id, rnti_t rnti); + +/* Get A3 Event time to trigger */ +long flexran_get_rrc_a3_event_timeToTrigger(mid_t mod_id, rnti_t rnti); + +/* Get A3 Event max reported cells */ +long flexran_get_rrc_a3_event_maxReportCells(mid_t mod_id, rnti_t rnti); + +/* Get A3 Event a3 offset */ +long flexran_get_rrc_a3_event_a3_offset(mid_t mod_id, rnti_t rnti); + +/* Get A3 Event report on leave */ +int flexran_get_rrc_a3_event_reportOnLeave(mid_t mod_id, rnti_t rnti); + /* Get number of PLMNs that is broadcasted in SIB1 */ uint8_t flexran_get_rrc_num_plmn_ids(mid_t mod_id); diff --git a/openair2/RRC/LTE/rrc_defs.h b/openair2/RRC/LTE/rrc_defs.h index 2f3f679935..47a0ccbf24 100644 --- a/openair2/RRC/LTE/rrc_defs.h +++ b/openair2/RRC/LTE/rrc_defs.h @@ -477,6 +477,71 @@ typedef struct HANDOVER_INFO_s { int x2_id; /* X2AP UE ID in the target eNB */ } HANDOVER_INFO; +typedef struct PER_EVENT_s { + long maxReportCells; +} PER_EVENT_t; + +typedef struct A1_EVENT_s { + long threshold_RSRP; + long hysteresis; + long timeToTrigger; + long maxReportCells; +} A1_EVENT_t; + +typedef struct A2_EVENT_s { + long threshold_RSRP; + long hysteresis; + long timeToTrigger; + long maxReportCells; +} A2_EVENT_t; + +typedef struct A3_EVENT_s { + long a3_offset; + int reportOnLeave; + long hysteresis; + long timeToTrigger; + long maxReportCells; +} A3_EVENT_t; + + +typedef struct A4_EVENT_s { + long threshold_RSRP; + long hysteresis; + long timeToTrigger; + long maxReportCells; +} A4_EVENT_t; + +typedef struct A5_EVENT_s { + long threshold_RSRP_1; + long threshold_RSRP_2; + long hysteresis; + long timeToTrigger; + long maxReportCells; +} A5_EVENT_t; + +typedef struct EVENTS_s { + PER_EVENT_t *per_event; + + A1_EVENT_t *a1_event; + + A2_EVENT_t *a2_event; + + A3_EVENT_t *a3_event; + + A4_EVENT_t *a4_event; + + A5_EVENT_t *a5_event; +} EVENTS_t; + +typedef struct MEASUREMENT_INFO_s { + //TODO: Extend to multiple meas objects for OFP/OFN offsets + long offsetFreq; + //TODO: extend to multiple cells for OCP/OCN offsets + long cellIndividualOffset; + EVENTS_t *events; +} MEASUREMENT_INFO; + + #define RRC_HEADER_SIZE_MAX 64 #define RRC_BUFFER_SIZE_MAX 1024 typedef struct { @@ -559,6 +624,7 @@ typedef struct eNB_RRC_UE_s { SRB_INFO_TABLE_ENTRY Srb2; LTE_MeasConfig_t *measConfig; HANDOVER_INFO *handover_info; + MEASUREMENT_INFO *measurement_info; LTE_MeasResults_t *measResults; LTE_MobilityControlInfo_t *mobilityInfo; From 5dfec71629722cdad2c2b1c6ed43b7b8149099a4 Mon Sep 17 00:00:00 2001 From: Konstantinos Alexandris Date: Fri, 19 Apr 2019 11:45:37 +0200 Subject: [PATCH 05/32] Fill in the RRC Measurement info struct in the RRC layer --- openair2/RRC/LTE/rrc_eNB.c | 68 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) diff --git a/openair2/RRC/LTE/rrc_eNB.c b/openair2/RRC/LTE/rrc_eNB.c index 230b9511f0..96f0bb3dce 100644 --- a/openair2/RRC/LTE/rrc_eNB.c +++ b/openair2/RRC/LTE/rrc_eNB.c @@ -977,6 +977,24 @@ rrc_eNB_free_mem_UE_context( ue_context_pP->ue_context.handover_info = NULL; } + if (ue_context_pP->ue_context.measurement_info->events->a3_event) { + /* TODO: be sure free is enough here (check memory leaks) */ + free(ue_context_pP->ue_context.measurement_info->events->a3_event); + ue_context_pP->ue_context.measurement_info->events->a3_event = NULL; + } + + if (ue_context_pP->ue_context.measurement_info->events) { + /* TODO: be sure free is enough here (check memory leaks) */ + free(ue_context_pP->ue_context.measurement_info->events); + ue_context_pP->ue_context.measurement_info->events = NULL; + } + + if (ue_context_pP->ue_context.measurement_info) { + /* TODO: be sure free is enough here (check memory leaks) */ + free(ue_context_pP->ue_context.measurement_info); + ue_context_pP->ue_context.measurement_info = NULL; + } + //SRB_INFO SI; //SRB_INFO Srb0; //SRB_INFO_TABLE_ENTRY Srb1; @@ -3302,6 +3320,19 @@ void rrc_eNB_generate_defaultRRCConnectionReconfiguration(const protocol_ctxt_t // } ASN_SEQUENCE_ADD(&MeasObj_list->list, MeasObj); // LTE_RRCConnectionReconfiguration->criticalExtensions.choice.c1.choice.rrcConnectionReconfiguration_r8.measConfig->measObjectToAddModList = MeasObj_list; + + if (!ue_context_pP->ue_context.measurement_info) { + ue_context_pP->ue_context.measurement_info = CALLOC(1,sizeof(*(ue_context_pP->ue_context.measurement_info))); + } + + //TODO: Assign proper values + ue_context_pP->ue_context.measurement_info->offsetFreq = 0; + ue_context_pP->ue_context.measurement_info->cellIndividualOffset = LTE_Q_OffsetRange_dB0; + + if (!ue_context_pP->ue_context.measurement_info->events) { + ue_context_pP->ue_context.measurement_info->events = CALLOC(1,sizeof(*(ue_context_pP->ue_context.measurement_info->events))); + } + // Report Configurations for periodical, A1-A5 events ReportConfig_list = CALLOC(1, sizeof(*ReportConfig_list)); ReportConfig_per = CALLOC(1, sizeof(*ReportConfig_per)); @@ -3416,6 +3447,18 @@ void rrc_eNB_generate_defaultRRCConnectionReconfiguration(const protocol_ctxt_t ReportConfig_A5->reportConfig.choice.reportConfigEUTRA.reportAmount = LTE_ReportConfigEUTRA__reportAmount_infinity; ASN_SEQUENCE_ADD(&ReportConfig_list->list, ReportConfig_A5); // LTE_RRCConnectionReconfiguration->criticalExtensions.choice.c1.choice.rrcConnectionReconfiguration_r8.measConfig->reportConfigToAddModList = ReportConfig_list; + + /* A3 event update */ + if (!ue_context_pP->ue_context.measurement_info->events->a3_event) { + ue_context_pP->ue_context.measurement_info->events->a3_event = CALLOC(1,sizeof(*(ue_context_pP->ue_context.measurement_info->events->a3_event))); + } + + ue_context_pP->ue_context.measurement_info->events->a3_event->a3_offset = ReportConfig_A3->reportConfig.choice.reportConfigEUTRA.triggerType.choice.event.eventId.choice.eventA3.a3_Offset; + ue_context_pP->ue_context.measurement_info->events->a3_event->reportOnLeave = ReportConfig_A3->reportConfig.choice.reportConfigEUTRA.triggerType.choice.event.eventId.choice.eventA3.reportOnLeave; + ue_context_pP->ue_context.measurement_info->events->a3_event->hysteresis = ReportConfig_A3->reportConfig.choice.reportConfigEUTRA.triggerType.choice.event.hysteresis; + ue_context_pP->ue_context.measurement_info->events->a3_event->timeToTrigger = ReportConfig_A3->reportConfig.choice.reportConfigEUTRA.triggerType.choice.event.timeToTrigger; + ue_context_pP->ue_context.measurement_info->events->a3_event->maxReportCells = ReportConfig_A3->reportConfig.choice.reportConfigEUTRA.maxReportCells; + rsrp = CALLOC(1, sizeof(LTE_RSRP_Range_t)); *rsrp = 20; Sparams = CALLOC(1, sizeof(*Sparams)); @@ -5287,6 +5330,19 @@ rrc_eNB_generate_HO_RRCConnectionReconfiguration(const protocol_ctxt_t *const ct //} ASN_SEQUENCE_ADD(&MeasObj_list->list, MeasObj); // rrcConnectionReconfiguration->criticalExtensions.choice.c1.choice.rrcConnectionReconfiguration_r8.measConfig->measObjectToAddModList = MeasObj_list; + + if (!ue_context_pP->ue_context.measurement_info) { + ue_context_pP->ue_context.measurement_info = CALLOC(1,sizeof(*(ue_context_pP->ue_context.measurement_info))); + } + + //TODO: Assign proper values + ue_context_pP->ue_context.measurement_info->offsetFreq = 0; + ue_context_pP->ue_context.measurement_info->cellIndividualOffset = LTE_Q_OffsetRange_dB0; + + if (!ue_context_pP->ue_context.measurement_info->events) { + ue_context_pP->ue_context.measurement_info->events = CALLOC(1,sizeof(*(ue_context_pP->ue_context.measurement_info->events))); + } + // Report Configurations for periodical, A1-A5 events ReportConfig_list = CALLOC(1, sizeof(*ReportConfig_list)); ReportConfig_per = CALLOC(1, sizeof(*ReportConfig_per)); @@ -5401,6 +5457,18 @@ rrc_eNB_generate_HO_RRCConnectionReconfiguration(const protocol_ctxt_t *const ct ReportConfig_A5->reportConfig.choice.reportConfigEUTRA.reportAmount = LTE_ReportConfigEUTRA__reportAmount_infinity; ASN_SEQUENCE_ADD(&ReportConfig_list->list, ReportConfig_A5); // rrcConnectionReconfiguration->criticalExtensions.choice.c1.choice.rrcConnectionReconfiguration_r8.measConfig->reportConfigToAddModList = ReportConfig_list; + + /* A3 event update */ + if (!ue_context_pP->ue_context.measurement_info->events->a3_event) { + ue_context_pP->ue_context.measurement_info->events->a3_event = CALLOC(1,sizeof(*(ue_context_pP->ue_context.measurement_info->events->a3_event))); + } + + ue_context_pP->ue_context.measurement_info->events->a3_event->a3_offset = ReportConfig_A3->reportConfig.choice.reportConfigEUTRA.triggerType.choice.event.eventId.choice.eventA3.a3_Offset; + ue_context_pP->ue_context.measurement_info->events->a3_event->reportOnLeave = ReportConfig_A3->reportConfig.choice.reportConfigEUTRA.triggerType.choice.event.eventId.choice.eventA3.reportOnLeave; + ue_context_pP->ue_context.measurement_info->events->a3_event->hysteresis = ReportConfig_A3->reportConfig.choice.reportConfigEUTRA.triggerType.choice.event.hysteresis; + ue_context_pP->ue_context.measurement_info->events->a3_event->timeToTrigger = ReportConfig_A3->reportConfig.choice.reportConfigEUTRA.triggerType.choice.event.timeToTrigger; + ue_context_pP->ue_context.measurement_info->events->a3_event->maxReportCells = ReportConfig_A3->reportConfig.choice.reportConfigEUTRA.maxReportCells; + rsrp = CALLOC(1, sizeof(RSRP_Range_t)); *rsrp = 20; Sparams = CALLOC(1, sizeof(*Sparams)); From b7530528e0f4ca6e6bb2f99ed278dd77c3fec1d9 Mon Sep 17 00:00:00 2001 From: Konstantinos Alexandris Date: Tue, 23 Apr 2019 12:03:22 +0200 Subject: [PATCH 06/32] To be tested: Add code for measurement report based on the neighbouring cells after x2 setup, ocs/ocn for multiple cells --- openair2/COMMON/x2ap_messages_def.h | 2 + openair2/COMMON/x2ap_messages_types.h | 12 +++ openair2/ENB_APP/flexran_agent_ran_api.c | 6 +- openair2/ENB_APP/flexran_agent_ran_api.h | 2 +- openair2/RRC/LTE/rrc_defs.h | 9 +- openair2/RRC/LTE/rrc_eNB.c | 126 +++++++++++++++++------ openair2/RRC/LTE/rrc_proto.h | 3 + openair2/X2AP/x2ap_eNB_handler.c | 17 +++ 8 files changed, 138 insertions(+), 39 deletions(-) diff --git a/openair2/COMMON/x2ap_messages_def.h b/openair2/COMMON/x2ap_messages_def.h index 2a040c8000..c588753ca8 100644 --- a/openair2/COMMON/x2ap_messages_def.h +++ b/openair2/COMMON/x2ap_messages_def.h @@ -39,6 +39,8 @@ MESSAGE_DEF(X2AP_REGISTER_ENB_CNF , MESSAGE_PRIORITY_MED, x2ap_reg MESSAGE_DEF(X2AP_DEREGISTERED_ENB_IND , MESSAGE_PRIORITY_MED, x2ap_deregistered_enb_ind_t , x2ap_deregistered_enb_ind) /* handover messages X2AP <-> RRC */ +MESSAGE_DEF(X2AP_SETUP_REQ , MESSAGE_PRIORITY_MED, x2ap_setup_req_t , x2ap_setup_req) +MESSAGE_DEF(X2AP_SETUP_RESP , MESSAGE_PRIORITY_MED, x2ap_setup_resp_t , x2ap_setup_resp) MESSAGE_DEF(X2AP_HANDOVER_REQ , MESSAGE_PRIORITY_MED, x2ap_handover_req_t , x2ap_handover_req) MESSAGE_DEF(X2AP_HANDOVER_REQ_ACK , MESSAGE_PRIORITY_MED, x2ap_handover_req_ack_t , x2ap_handover_req_ack) MESSAGE_DEF(X2AP_HANDOVER_CANCEL , MESSAGE_PRIORITY_MED, x2ap_handover_cancel_t , x2ap_handover_cancel) diff --git a/openair2/COMMON/x2ap_messages_types.h b/openair2/COMMON/x2ap_messages_types.h index 708430b8b2..d284f4d0b9 100644 --- a/openair2/COMMON/x2ap_messages_types.h +++ b/openair2/COMMON/x2ap_messages_types.h @@ -29,6 +29,8 @@ // Defines to access message fields. #define X2AP_REGISTER_ENB_REQ(mSGpTR) (mSGpTR)->ittiMsg.x2ap_register_enb_req +#define X2AP_SETUP_REQ(mSGpTR) (mSGpTR)->ittiMsg.x2ap_setup_req +#define X2AP_SETUP_RESP(mSGpTR) (mSGpTR)->ittiMsg.x2ap_setup_resp #define X2AP_HANDOVER_REQ(mSGpTR) (mSGpTR)->ittiMsg.x2ap_handover_req #define X2AP_HANDOVER_REQ_ACK(mSGpTR) (mSGpTR)->ittiMsg.x2ap_handover_req_ack #define X2AP_REGISTER_ENB_CNF(mSGpTR) (mSGpTR)->ittiMsg.x2ap_register_enb_cnf @@ -41,6 +43,16 @@ // eNB application layer -> X2AP messages +typedef struct x2ap_setup_req_s { + uint32_t Nid_cell[MAX_NUM_CCs]; + int num_cc; +} x2ap_setup_req_t; + +typedef struct x2ap_setup_resp_s { + uint32_t Nid_cell[MAX_NUM_CCs]; + int num_cc; +} x2ap_setup_resp_t; + /* X2AP UE CONTEXT RELEASE */ typedef struct x2ap_ue_context_release_s { /* used for X2AP->RRC in source and RRC->X2AP in target */ diff --git a/openair2/ENB_APP/flexran_agent_ran_api.c b/openair2/ENB_APP/flexran_agent_ran_api.c index 9e706302f3..fbda394db2 100644 --- a/openair2/ENB_APP/flexran_agent_ran_api.c +++ b/openair2/ENB_APP/flexran_agent_ran_api.c @@ -1586,15 +1586,15 @@ long flexran_get_rrc_ocp(mid_t mod_id, rnti_t rnti) { struct rrc_eNB_ue_context_s* ue_context_p = rrc_eNB_get_ue_context(RC.rrc[mod_id], rnti); if (!ue_context_p) return -1; if (!ue_context_p->ue_context.measurement_info) return -1; - return ue_context_p->ue_context.measurement_info->cellIndividualOffset; + return ue_context_p->ue_context.measurement_info->cellIndividualOffset[0]; } -long flexran_get_rrc_ocn(mid_t mod_id, rnti_t rnti) { +long flexran_get_rrc_ocn(mid_t mod_id, rnti_t rnti, long cell_id) { if (!rrc_is_present(mod_id)) return -1; struct rrc_eNB_ue_context_s* ue_context_p = rrc_eNB_get_ue_context(RC.rrc[mod_id], rnti); if (!ue_context_p) return -1; if (!ue_context_p->ue_context.measurement_info) return -1; - return ue_context_p->ue_context.measurement_info->cellIndividualOffset; + return ue_context_p->ue_context.measurement_info->cellIndividualOffset[cell_id+1]; } /* Periodic event */ diff --git a/openair2/ENB_APP/flexran_agent_ran_api.h b/openair2/ENB_APP/flexran_agent_ran_api.h index 0eee42bc2d..224b19a264 100644 --- a/openair2/ENB_APP/flexran_agent_ran_api.h +++ b/openair2/ENB_APP/flexran_agent_ran_api.h @@ -550,7 +550,7 @@ long flexran_get_rrc_ofn(mid_t mod_id, rnti_t rnti); long flexran_get_rrc_ocp(mid_t mod_id, rnti_t rnti); /* Get ocn offset */ -long flexran_get_rrc_ocn(mid_t mod_id, rnti_t rnti); +long flexran_get_rrc_ocn(mid_t mod_id, rnti_t rnti, long cell_id); /* Get Periodic Event max reported cells */ long flexran_get_rrc_per_event_maxReportCells(mid_t mod_id, rnti_t rnti); diff --git a/openair2/RRC/LTE/rrc_defs.h b/openair2/RRC/LTE/rrc_defs.h index 47a0ccbf24..a7ec8cc567 100644 --- a/openair2/RRC/LTE/rrc_defs.h +++ b/openair2/RRC/LTE/rrc_defs.h @@ -61,6 +61,8 @@ #define MAX_PAYLOAD 1024 /* maximum payload size*/ +#define MAX_NUM_NEIGH_CELLs 6 /* maximum neighbouring cells number */ + #define UE_STATE_NOTIFICATION_INTERVAL 50 #define IPV4_ADDR "%u.%u.%u.%u" @@ -537,7 +539,7 @@ typedef struct MEASUREMENT_INFO_s { //TODO: Extend to multiple meas objects for OFP/OFN offsets long offsetFreq; //TODO: extend to multiple cells for OCP/OCN offsets - long cellIndividualOffset; + long cellIndividualOffset[MAX_NUM_NEIGH_CELLs+1]; EVENTS_t *events; } MEASUREMENT_INFO; @@ -822,6 +824,11 @@ typedef struct eNB_RRC_INST_s { /// NR cell id uint64_t nr_cellid; + // Neighborouring cells id + int num_neigh_cells; + int num_neigh_cells_cc[MAX_NUM_CCs]; + uint32_t neigh_cells_id[MAX_NUM_NEIGH_CELLs][MAX_NUM_CCs]; + // other RAN parameters int srb1_timer_poll_retransmit; int srb1_poll_pdu; diff --git a/openair2/RRC/LTE/rrc_eNB.c b/openair2/RRC/LTE/rrc_eNB.c index 96f0bb3dce..c09fd86bd8 100644 --- a/openair2/RRC/LTE/rrc_eNB.c +++ b/openair2/RRC/LTE/rrc_eNB.c @@ -2942,8 +2942,9 @@ void rrc_eNB_generate_defaultRRCConnectionReconfiguration(const protocol_ctxt_t LTE_RSRP_Range_t *rsrp = NULL; struct LTE_MeasConfig__speedStatePars *Sparams = NULL; LTE_QuantityConfig_t *quantityConfig = NULL; - struct LTE_RRCConnectionReconfiguration_r8_IEs__dedicatedInfoNASList - *dedicatedInfoNASList = NULL; + LTE_CellsToAddMod_t *CellToAdd = NULL; + LTE_CellsToAddModList_t *CellsToAddModList = NULL; + struct LTE_RRCConnectionReconfiguration_r8_IEs__dedicatedInfoNASList *dedicatedInfoNASList = NULL; LTE_DedicatedInfoNAS_t *dedicatedInfoNas = NULL; /* For no gcc warnings */ @@ -3306,20 +3307,9 @@ void rrc_eNB_generate_defaultRRCConnectionReconfiguration(const protocol_ctxt_t MeasObj->measObject.choice.measObjectEUTRA.neighCellConfig.size = 1; MeasObj->measObject.choice.measObjectEUTRA.neighCellConfig.bits_unused = 6; MeasObj->measObject.choice.measObjectEUTRA.offsetFreq = NULL; // Default is 15 or 0dB - // MeasObj->measObject.choice.measObjectEUTRA.cellsToAddModList = - // (LTE_CellsToAddModList_t *) CALLOC(1, sizeof(*CellsToAddModList)); - // CellsToAddModList = MeasObj->measObject.choice.measObjectEUTRA.cellsToAddModList; - // - // // Add adjacent cell lists (6 per eNB) - // for (i = 0; i < 6; i++) { - // CellToAdd = (LTE_CellsToAddMod_t *) CALLOC(1, sizeof(*CellToAdd)); - // CellToAdd->cellIndex = i + 1; - // CellToAdd->physCellId = get_adjacent_cell_id(ctxt_pP->module_id, i); - // CellToAdd->cellIndividualOffset = LTE_Q_OffsetRange_dB0; - // ASN_SEQUENCE_ADD(&CellsToAddModList->list, CellToAdd); - // } - ASN_SEQUENCE_ADD(&MeasObj_list->list, MeasObj); - // LTE_RRCConnectionReconfiguration->criticalExtensions.choice.c1.choice.rrcConnectionReconfiguration_r8.measConfig->measObjectToAddModList = MeasObj_list; + MeasObj->measObject.choice.measObjectEUTRA.cellsToAddModList = + (LTE_CellsToAddModList_t *) CALLOC(1, sizeof(*CellsToAddModList)); + CellsToAddModList = MeasObj->measObject.choice.measObjectEUTRA.cellsToAddModList; if (!ue_context_pP->ue_context.measurement_info) { ue_context_pP->ue_context.measurement_info = CALLOC(1,sizeof(*(ue_context_pP->ue_context.measurement_info))); @@ -3327,7 +3317,20 @@ void rrc_eNB_generate_defaultRRCConnectionReconfiguration(const protocol_ctxt_t //TODO: Assign proper values ue_context_pP->ue_context.measurement_info->offsetFreq = 0; - ue_context_pP->ue_context.measurement_info->cellIndividualOffset = LTE_Q_OffsetRange_dB0; + ue_context_pP->ue_context.measurement_info->cellIndividualOffset[0] = 0; + + /* TODO: Extend to multiple carriers */ + // Add adjacent cell lists (max 6 per eNB) + for (i = 0; i < RC.rrc[ctxt_pP->module_id]->num_neigh_cells; i++) { + CellToAdd = (LTE_CellsToAddMod_t *) CALLOC(1, sizeof(*CellToAdd)); + CellToAdd->cellIndex = i + 1; + CellToAdd->physCellId = RC.rrc[ctxt_pP->module_id]->neigh_cells_id[i][0];//get_adjacent_cell_id(ctxt_pP->module_id, i); + CellToAdd->cellIndividualOffset = LTE_Q_OffsetRange_dB0; + ue_context_pP->ue_context.measurement_info->cellIndividualOffset[i+1] = CellToAdd->cellIndividualOffset; + ASN_SEQUENCE_ADD(&CellsToAddModList->list, CellToAdd); + } + ASN_SEQUENCE_ADD(&MeasObj_list->list, MeasObj); + // LTE_RRCConnectionReconfiguration->criticalExtensions.choice.c1.choice.rrcConnectionReconfiguration_r8.measConfig->measObjectToAddModList = MeasObj_list; if (!ue_context_pP->ue_context.measurement_info->events) { ue_context_pP->ue_context.measurement_info->events = CALLOC(1,sizeof(*(ue_context_pP->ue_context.measurement_info->events))); @@ -4398,6 +4401,50 @@ rrc_eNB_generate_HandoverPreparationInformation( *_size = ho_size; } +void rrc_eNB_process_x2_setup_request(int mod_id, x2ap_setup_req_t *m) { + + RC.rrc[mod_id]->num_neigh_cells ++; + + if (RC.rrc[mod_id]->num_neigh_cells > MAX_NUM_NEIGH_CELLs) { + LOG_E(RRC, "Error: number of neighbouring cells is exceeded \n"); + return; + } + + if (m->num_cc > MAX_NUM_CCs) { + LOG_E(RRC, "Error: number of neighbouring cells carriers is exceeded \n"); + return; + } + + RC.rrc[mod_id]->num_neigh_cells_cc[RC.rrc[mod_id]->num_neigh_cells-1] = m->num_cc; + + for (int i=0; inum_cc; i++) { + RC.rrc[mod_id]->neigh_cells_id[RC.rrc[mod_id]->num_neigh_cells-1][i] = m->Nid_cell[i]; + } + +} + +void rrc_eNB_process_x2_setup_response(int mod_id, x2ap_setup_resp_t *m) { + + RC.rrc[mod_id]->num_neigh_cells ++; + + if (RC.rrc[mod_id]->num_neigh_cells > MAX_NUM_NEIGH_CELLs) { + LOG_E(RRC, "Error: number of neighbouring cells is exceeded \n"); + return; + } + + if (m->num_cc > MAX_NUM_CCs) { + LOG_E(RRC, "Error: number of neighbouring cells carriers is exceeded \n"); + return; + } + + RC.rrc[mod_id]->num_neigh_cells_cc[RC.rrc[mod_id]->num_neigh_cells-1] = m->num_cc; + + for (int i=0; inum_cc; i++) { + RC.rrc[mod_id]->neigh_cells_id[RC.rrc[mod_id]->num_neigh_cells-1][i] = m->Nid_cell[i]; + } + +} + void rrc_eNB_process_handoverPreparationInformation(int mod_id, x2ap_handover_req_t *m) { struct rrc_eNB_ue_context_s *ue_context_target_p = NULL; /* TODO: get proper UE rnti */ @@ -4705,8 +4752,8 @@ rrc_eNB_generate_HO_RRCConnectionReconfiguration(const protocol_ctxt_t *const ct LTE_QuantityConfig_t *quantityConfig = NULL; LTE_MobilityControlInfo_t *mobilityInfo = NULL; LTE_SecurityConfigHO_t *securityConfigHO = NULL; - //CellsToAddMod_t *CellToAdd = NULL; - //CellsToAddModList_t *CellsToAddModList = NULL; + LTE_CellsToAddMod_t *CellToAdd = NULL; + LTE_CellsToAddModList_t *CellsToAddModList = NULL; struct LTE_RRCConnectionReconfiguration_r8_IEs__dedicatedInfoNASList *dedicatedInfoNASList = NULL; LTE_DedicatedInfoNAS_t *dedicatedInfoNas = NULL; /* for no gcc warnings */ @@ -5297,7 +5344,7 @@ rrc_eNB_generate_HO_RRCConnectionReconfiguration(const protocol_ctxt_t *const ct MeasId5->measObjectId = 1; MeasId5->reportConfigId = 6; ASN_SEQUENCE_ADD(&MeasId_list->list, MeasId5); - // rrcConnectionReconfiguration->criticalExtensions.choice.c1.choice.rrcConnectionReconfiguration_r8.measConfig->measIdToAddModList = MeasId_list; + // LTE_RRCConnectionReconfiguration->criticalExtensions.choice.c1.choice.rrcConnectionReconfiguration_r8.measConfig->measIdToAddModList = MeasId_list; // Add one EUTRA Measurement Object MeasObj_list = CALLOC(1, sizeof(*MeasObj_list)); memset((void *)MeasObj_list, 0, sizeof(*MeasObj_list)); @@ -5317,19 +5364,9 @@ rrc_eNB_generate_HO_RRCConnectionReconfiguration(const protocol_ctxt_t *const ct MeasObj->measObject.choice.measObjectEUTRA.neighCellConfig.size = 1; MeasObj->measObject.choice.measObjectEUTRA.neighCellConfig.bits_unused = 6; MeasObj->measObject.choice.measObjectEUTRA.offsetFreq = NULL; // Default is 15 or 0dB - //MeasObj->measObject.choice.measObjectEUTRA.cellsToAddModList = - //(CellsToAddModList_t *) CALLOC(1, sizeof(*CellsToAddModList)); - //CellsToAddModList = MeasObj->measObject.choice.measObjectEUTRA.cellsToAddModList; - // Add adjacent cell lists (6 per eNB) - //for (i = 0; i < 6; i++) { - //CellToAdd = (CellsToAddMod_t *) CALLOC(1, sizeof(*CellToAdd)); - //CellToAdd->cellIndex = 1;//i + 1; - //CellToAdd->physCellId = 1;//get_adjacent_cell_id(ctxt_pP->module_id, i); - //CellToAdd->cellIndividualOffset = Q_OffsetRange_dB0; - //ASN_SEQUENCE_ADD(&CellsToAddModList->list, CellToAdd); - //} - ASN_SEQUENCE_ADD(&MeasObj_list->list, MeasObj); - // rrcConnectionReconfiguration->criticalExtensions.choice.c1.choice.rrcConnectionReconfiguration_r8.measConfig->measObjectToAddModList = MeasObj_list; + MeasObj->measObject.choice.measObjectEUTRA.cellsToAddModList = + (LTE_CellsToAddModList_t *) CALLOC(1, sizeof(*CellsToAddModList)); + CellsToAddModList = MeasObj->measObject.choice.measObjectEUTRA.cellsToAddModList; if (!ue_context_pP->ue_context.measurement_info) { ue_context_pP->ue_context.measurement_info = CALLOC(1,sizeof(*(ue_context_pP->ue_context.measurement_info))); @@ -5337,7 +5374,20 @@ rrc_eNB_generate_HO_RRCConnectionReconfiguration(const protocol_ctxt_t *const ct //TODO: Assign proper values ue_context_pP->ue_context.measurement_info->offsetFreq = 0; - ue_context_pP->ue_context.measurement_info->cellIndividualOffset = LTE_Q_OffsetRange_dB0; + ue_context_pP->ue_context.measurement_info->cellIndividualOffset[0] = 0; + + /* TODO: Extend to multiple carriers */ + // Add adjacent cell lists (max 6 per eNB) + for (i = 0; i < RC.rrc[ctxt_pP->module_id]->num_neigh_cells; i++) { + CellToAdd = (LTE_CellsToAddMod_t *) CALLOC(1, sizeof(*CellToAdd)); + CellToAdd->cellIndex = i + 1; + CellToAdd->physCellId = RC.rrc[ctxt_pP->module_id]->neigh_cells_id[i][0];//get_adjacent_cell_id(ctxt_pP->module_id, i); + CellToAdd->cellIndividualOffset = LTE_Q_OffsetRange_dB0; + ue_context_pP->ue_context.measurement_info->cellIndividualOffset[i+1] = CellToAdd->cellIndividualOffset; + ASN_SEQUENCE_ADD(&CellsToAddModList->list, CellToAdd); + } + ASN_SEQUENCE_ADD(&MeasObj_list->list, MeasObj); + // LTE_RRCConnectionReconfiguration->criticalExtensions.choice.c1.choice.rrcConnectionReconfiguration_r8.measConfig->measObjectToAddModList = MeasObj_list; if (!ue_context_pP->ue_context.measurement_info->events) { ue_context_pP->ue_context.measurement_info->events = CALLOC(1,sizeof(*(ue_context_pP->ue_context.measurement_info->events))); @@ -8291,6 +8341,14 @@ void *rrc_enb_process_itti_msg(void *notUsed) { rrc_eNB_process_S1AP_PATH_SWITCH_REQ_ACK(msg_p, msg_name_p, instance); break; + case X2AP_SETUP_REQ: + rrc_eNB_process_x2_setup_request(instance, &X2AP_SETUP_REQ(msg_p)); + break; + + case X2AP_SETUP_RESP: + rrc_eNB_process_x2_setup_response(instance, &X2AP_SETUP_RESP(msg_p)); + break; + case X2AP_HANDOVER_REQ: LOG_I(RRC, "[eNB %d] target eNB Receives X2 HO Req %s\n", instance, msg_name_p); rrc_eNB_process_handoverPreparationInformation(instance, &X2AP_HANDOVER_REQ(msg_p)); diff --git a/openair2/RRC/LTE/rrc_proto.h b/openair2/RRC/LTE/rrc_proto.h index 34439753d8..5fc935c0ea 100644 --- a/openair2/RRC/LTE/rrc_proto.h +++ b/openair2/RRC/LTE/rrc_proto.h @@ -357,6 +357,9 @@ void *rrc_enb_task(void *args_p); \param void *args_p Pointer on arguments to start the task. */ void *rrc_ue_task(void *args_p); +void rrc_eNB_process_x2_setup_request(int mod_id, x2ap_setup_req_t *m); + +void rrc_eNB_process_x2_setup_response(int mod_id, x2ap_setup_resp_t *m); void rrc_eNB_process_handoverPreparationInformation(int mod_id, x2ap_handover_req_t *m); diff --git a/openair2/X2AP/x2ap_eNB_handler.c b/openair2/X2AP/x2ap_eNB_handler.c index ad1cac0479..2a44501a33 100644 --- a/openair2/X2AP/x2ap_eNB_handler.c +++ b/openair2/X2AP/x2ap_eNB_handler.c @@ -291,6 +291,7 @@ x2ap_eNB_handle_x2_setup_request(instance_t instance, x2ap_eNB_instance_t *instance_p; x2ap_eNB_data_t *x2ap_eNB_data; + MessageDef *msg; uint32_t eNB_id = 0; DevAssert (pdu != NULL); @@ -391,17 +392,25 @@ x2ap_eNB_handle_x2_setup_request(instance_t instance, X2AP_ERROR("%s %d: ie is a NULL pointer \n",__FILE__,__LINE__); return -1; } + + msg = itti_alloc_new_message(TASK_X2AP, X2AP_SETUP_REQ); + + X2AP_SETUP_REQ(msg).num_cc = ie->value.choice.ServedCells.list.count; + if (ie->value.choice.ServedCells.list.count > 0) { x2ap_eNB_data->num_cc = ie->value.choice.ServedCells.list.count; for (int i=0; ivalue.choice.ServedCells.list.count;i++) { servedCellMember = (ServedCells__Member *)ie->value.choice.ServedCells.list.array[i]; x2ap_eNB_data->Nid_cell[i] = servedCellMember->servedCellInfo.pCI; + X2AP_SETUP_REQ(msg).Nid_cell[i] = x2ap_eNB_data->Nid_cell[i]; } } instance_p = x2ap_eNB_get_instance(instance); DevAssert(instance_p != NULL); + itti_send_msg_to_task(TASK_RRC_ENB, instance_p->instance, msg); + return x2ap_eNB_generate_x2_setup_response(instance_p, x2ap_eNB_data); } @@ -418,6 +427,7 @@ int x2ap_eNB_handle_x2_setup_response(instance_t instance, x2ap_eNB_instance_t *instance_p; x2ap_eNB_data_t *x2ap_eNB_data; + MessageDef *msg; uint32_t eNB_id = 0; DevAssert (pdu != NULL); @@ -500,11 +510,16 @@ int x2ap_eNB_handle_x2_setup_response(instance_t instance, return -1; } + msg = itti_alloc_new_message(TASK_X2AP, X2AP_SETUP_RESP); + + X2AP_SETUP_RESP(msg).num_cc = ie->value.choice.ServedCells.list.count; + if (ie->value.choice.ServedCells.list.count > 0) { x2ap_eNB_data->num_cc = ie->value.choice.ServedCells.list.count; for (int i=0; ivalue.choice.ServedCells.list.count;i++) { servedCellMember = (ServedCells__Member *)ie->value.choice.ServedCells.list.array[i]; x2ap_eNB_data->Nid_cell[i] = servedCellMember->servedCellInfo.pCI; + X2AP_SETUP_RESP(msg).Nid_cell[i] = x2ap_eNB_data->Nid_cell[i]; } } @@ -521,6 +536,8 @@ int x2ap_eNB_handle_x2_setup_response(instance_t instance, instance_p->x2_target_enb_associated_nb ++; x2ap_handle_x2_setup_message(instance_p, x2ap_eNB_data, 0); + itti_send_msg_to_task(TASK_RRC_ENB, instance_p->instance, msg); + return 0; } From 772dc508e89bf334077d4c62a5767f768a97d161 Mon Sep 17 00:00:00 2001 From: Konstantinos Alexandris Date: Wed, 24 Apr 2019 17:21:11 +0200 Subject: [PATCH 07/32] Fix: Segfault error, free properly measurement info struct, add rsrp/rsrq filter coefficient --- openair2/ENB_APP/flexran_agent_ran_api.c | 16 ++++++++++++++ openair2/ENB_APP/flexran_agent_ran_api.h | 6 ++++++ openair2/RRC/LTE/rrc_defs.h | 4 +++- openair2/RRC/LTE/rrc_eNB.c | 27 +++++++++++++----------- 4 files changed, 40 insertions(+), 13 deletions(-) diff --git a/openair2/ENB_APP/flexran_agent_ran_api.c b/openair2/ENB_APP/flexran_agent_ran_api.c index fbda394db2..634dc775f1 100644 --- a/openair2/ENB_APP/flexran_agent_ran_api.c +++ b/openair2/ENB_APP/flexran_agent_ran_api.c @@ -1597,6 +1597,22 @@ long flexran_get_rrc_ocn(mid_t mod_id, rnti_t rnti, long cell_id) { return ue_context_p->ue_context.measurement_info->cellIndividualOffset[cell_id+1]; } +long flexran_get_filter_coeff_rsrp(mid_t mod_id, rnti_t rnti) { + if (!rrc_is_present(mod_id)) return -1; + struct rrc_eNB_ue_context_s* ue_context_p = rrc_eNB_get_ue_context(RC.rrc[mod_id], rnti); + if (!ue_context_p) return -1; + if (!ue_context_p->ue_context.measurement_info) return -1; + return ue_context_p->ue_context.measurement_info->filterCoefficientRSRP; +} + +long flexran_get_filter_coeff_rsrq(mid_t mod_id, rnti_t rnti) { + if (!rrc_is_present(mod_id)) return -1; + struct rrc_eNB_ue_context_s* ue_context_p = rrc_eNB_get_ue_context(RC.rrc[mod_id], rnti); + if (!ue_context_p) return -1; + if (!ue_context_p->ue_context.measurement_info) return -1; + return ue_context_p->ue_context.measurement_info->filterCoefficientRSRQ; +} + /* Periodic event */ long flexran_get_rrc_per_event_maxReportCells(mid_t mod_id, rnti_t rnti) { diff --git a/openair2/ENB_APP/flexran_agent_ran_api.h b/openair2/ENB_APP/flexran_agent_ran_api.h index 224b19a264..4a65284cba 100644 --- a/openair2/ENB_APP/flexran_agent_ran_api.h +++ b/openair2/ENB_APP/flexran_agent_ran_api.h @@ -570,6 +570,12 @@ long flexran_get_rrc_a3_event_a3_offset(mid_t mod_id, rnti_t rnti); /* Get A3 Event report on leave */ int flexran_get_rrc_a3_event_reportOnLeave(mid_t mod_id, rnti_t rnti); +/* Get filter coefficient for rsrp */ +long flexran_get_filter_coeff_rsrp(mid_t mod_id, rnti_t rnti); + +/* Get filter coefficient for rsrq */ +long flexran_get_filter_coeff_rsrq(mid_t mod_id, rnti_t rnti); + /* Get number of PLMNs that is broadcasted in SIB1 */ uint8_t flexran_get_rrc_num_plmn_ids(mid_t mod_id); diff --git a/openair2/RRC/LTE/rrc_defs.h b/openair2/RRC/LTE/rrc_defs.h index a7ec8cc567..21feaf5e4c 100644 --- a/openair2/RRC/LTE/rrc_defs.h +++ b/openair2/RRC/LTE/rrc_defs.h @@ -538,8 +538,10 @@ typedef struct EVENTS_s { typedef struct MEASUREMENT_INFO_s { //TODO: Extend to multiple meas objects for OFP/OFN offsets long offsetFreq; - //TODO: extend to multiple cells for OCP/OCN offsets + //TODO: extend to multiple carriers for OCP/OCN offsets long cellIndividualOffset[MAX_NUM_NEIGH_CELLs+1]; + long filterCoefficientRSRP; + long filterCoefficientRSRQ; EVENTS_t *events; } MEASUREMENT_INFO; diff --git a/openair2/RRC/LTE/rrc_eNB.c b/openair2/RRC/LTE/rrc_eNB.c index c09fd86bd8..37888c9716 100644 --- a/openair2/RRC/LTE/rrc_eNB.c +++ b/openair2/RRC/LTE/rrc_eNB.c @@ -977,20 +977,16 @@ rrc_eNB_free_mem_UE_context( ue_context_pP->ue_context.handover_info = NULL; } - if (ue_context_pP->ue_context.measurement_info->events->a3_event) { - /* TODO: be sure free is enough here (check memory leaks) */ - free(ue_context_pP->ue_context.measurement_info->events->a3_event); - ue_context_pP->ue_context.measurement_info->events->a3_event = NULL; - } - - if (ue_context_pP->ue_context.measurement_info->events) { - /* TODO: be sure free is enough here (check memory leaks) */ - free(ue_context_pP->ue_context.measurement_info->events); - ue_context_pP->ue_context.measurement_info->events = NULL; - } - if (ue_context_pP->ue_context.measurement_info) { /* TODO: be sure free is enough here (check memory leaks) */ + if (ue_context_pP->ue_context.measurement_info->events) { + if (ue_context_pP->ue_context.measurement_info->events->a3_event) { + free(ue_context_pP->ue_context.measurement_info->events->a3_event); + ue_context_pP->ue_context.measurement_info->events->a3_event = NULL; + } + free(ue_context_pP->ue_context.measurement_info->events); + ue_context_pP->ue_context.measurement_info->events = NULL; + } free(ue_context_pP->ue_context.measurement_info); ue_context_pP->ue_context.measurement_info = NULL; } @@ -3486,6 +3482,9 @@ void rrc_eNB_generate_defaultRRCConnectionReconfiguration(const protocol_ctxt_t *quantityConfig->quantityConfigEUTRA->filterCoefficientRSRP = LTE_FilterCoefficient_fc4; *quantityConfig->quantityConfigEUTRA->filterCoefficientRSRQ = LTE_FilterCoefficient_fc4; + ue_context_pP->ue_context.measurement_info->filterCoefficientRSRP = *quantityConfig->quantityConfigEUTRA->filterCoefficientRSRP; + ue_context_pP->ue_context.measurement_info->filterCoefficientRSRQ = *quantityConfig->quantityConfigEUTRA->filterCoefficientRSRQ; + /* Initialize NAS list */ dedicatedInfoNASList = CALLOC(1, sizeof(struct LTE_RRCConnectionReconfiguration_r8_IEs__dedicatedInfoNASList)); @@ -5542,6 +5541,10 @@ rrc_eNB_generate_HO_RRCConnectionReconfiguration(const protocol_ctxt_t *const ct CALLOC(1, sizeof(*(quantityConfig->quantityConfigEUTRA->filterCoefficientRSRQ))); *quantityConfig->quantityConfigEUTRA->filterCoefficientRSRP = LTE_FilterCoefficient_fc4; *quantityConfig->quantityConfigEUTRA->filterCoefficientRSRQ = LTE_FilterCoefficient_fc4; + + ue_context_pP->ue_context.measurement_info->filterCoefficientRSRP = *quantityConfig->quantityConfigEUTRA->filterCoefficientRSRP; + ue_context_pP->ue_context.measurement_info->filterCoefficientRSRQ = *quantityConfig->quantityConfigEUTRA->filterCoefficientRSRQ; + /* mobilityinfo */ mobilityInfo = ue_context_pP->ue_context.mobilityInfo; From 76a7b7036e93a90e72b11f17e51ea265a2ecfd81 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Thu, 25 Apr 2019 11:53:17 +0200 Subject: [PATCH 08/32] FlexRAN: Add Protobuf UE-specific RRC measurement report configuration --- .../ENB_APP/MESSAGES/V2/config_common.proto | 68 +++++++++++++++++++ .../ENB_APP/MESSAGES/V2/config_messages.proto | 2 + 2 files changed, 70 insertions(+) diff --git a/openair2/ENB_APP/MESSAGES/V2/config_common.proto b/openair2/ENB_APP/MESSAGES/V2/config_common.proto index 695d7bcdb1..4958cdb27b 100644 --- a/openair2/ENB_APP/MESSAGES/V2/config_common.proto +++ b/openair2/ENB_APP/MESSAGES/V2/config_common.proto @@ -268,3 +268,71 @@ message flex_plmn { optional uint32 mnc = 2; optional uint32 mnc_length = 3; } + +// +// UE-related RRC configuration + +message flex_measurement_info { + // arbitrary offset OFS, from TS + optional int64 offset_freq_serving = 1; + // arbitrary offset OFN + optional int64 offset_freq_neighbouring = 2; + // arbitrary offset OCS + OCN + repeated int64 cell_individual_offset = 3; + // Parameter k for exponential moving average calculation coefficient + // a = 1/2^(k/4) of all measured RSRPs + optional int64 filter_coefficient_rsrp = 4; + // Parameter k for RSRQ filtering + optional int64 filter_coefficient_rsrq = 5; + optional flex_measurement_event event = 6; +} + +message flex_measurement_event { + optional flex_per_event periodical = 1; + optional flex_a1_event a1 = 2; + optional flex_a2_event a2 = 3; + optional flex_a3_event a3 = 4; + optional flex_a4_event a4 = 5; + optional flex_a5_event a5 = 6; +} + +message flex_per_event { + optional int64 max_report_cells = 1; +} + +message flex_a1_event { + optional int64 threshold_rsrp = 1; + optional int64 hysteresis = 2; + optional int64 time_to_trigger = 3; + optional int64 max_report_cells = 4; +} + +message flex_a2_event { + optional int64 threshold_rsrp = 1; + optional int64 hysteresis = 2; + optional int64 time_to_trigger = 3; + optional int64 max_report_cells = 4; +} + +message flex_a3_event { + optional int64 a3_offset = 1; + optional int32 report_on_leave = 2; + optional int64 hysteresis = 3; + optional int64 time_to_trigger = 4; + optional int64 max_report_cells = 5; +} + +message flex_a4_event { + optional int64 threshold_rsrp = 1; + optional int64 hysteresis = 2; + optional int64 time_to_trigger = 3; + optional int64 max_report_cells = 4; +} + +message flex_a5_event { + optional int64 threshold_rsrp_1 = 1; + optional int64 threshold_rsrp_2 = 2; + optional int64 hysteresis = 3; + optional int64 time_to_trigger = 4; + optional int64 max_report_cells = 5; +} diff --git a/openair2/ENB_APP/MESSAGES/V2/config_messages.proto b/openair2/ENB_APP/MESSAGES/V2/config_messages.proto index dd983aa09c..c339ad0bf6 100644 --- a/openair2/ENB_APP/MESSAGES/V2/config_messages.proto +++ b/openair2/ENB_APP/MESSAGES/V2/config_messages.proto @@ -97,6 +97,8 @@ message flex_ue_config { optional uint64 imsi = 30; optional uint32 dl_slice_id = 31; optional uint32 ul_slice_id = 32; + // Configuration about RRC measurements + optional flex_measurement_info info = 33; } message flex_lc_ue_config { From f5e928afab48c304402657f6dcb5958724f7c773 Mon Sep 17 00:00:00 2001 From: Konstantinos Alexandris Date: Thu, 25 Apr 2019 14:47:43 +0200 Subject: [PATCH 09/32] Fix: condition on CellsToAddModList memory allocation in case of zero neighbouring cells --- openair2/RRC/LTE/rrc_eNB.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/openair2/RRC/LTE/rrc_eNB.c b/openair2/RRC/LTE/rrc_eNB.c index 37888c9716..5401f0a3f1 100644 --- a/openair2/RRC/LTE/rrc_eNB.c +++ b/openair2/RRC/LTE/rrc_eNB.c @@ -3303,9 +3303,12 @@ void rrc_eNB_generate_defaultRRCConnectionReconfiguration(const protocol_ctxt_t MeasObj->measObject.choice.measObjectEUTRA.neighCellConfig.size = 1; MeasObj->measObject.choice.measObjectEUTRA.neighCellConfig.bits_unused = 6; MeasObj->measObject.choice.measObjectEUTRA.offsetFreq = NULL; // Default is 15 or 0dB - MeasObj->measObject.choice.measObjectEUTRA.cellsToAddModList = - (LTE_CellsToAddModList_t *) CALLOC(1, sizeof(*CellsToAddModList)); - CellsToAddModList = MeasObj->measObject.choice.measObjectEUTRA.cellsToAddModList; + + if (RC.rrc[ctxt_pP->module_id]->num_neigh_cells > 0) { + MeasObj->measObject.choice.measObjectEUTRA.cellsToAddModList = + (LTE_CellsToAddModList_t *) CALLOC(1, sizeof(*CellsToAddModList)); + CellsToAddModList = MeasObj->measObject.choice.measObjectEUTRA.cellsToAddModList; + } if (!ue_context_pP->ue_context.measurement_info) { ue_context_pP->ue_context.measurement_info = CALLOC(1,sizeof(*(ue_context_pP->ue_context.measurement_info))); @@ -5363,9 +5366,12 @@ rrc_eNB_generate_HO_RRCConnectionReconfiguration(const protocol_ctxt_t *const ct MeasObj->measObject.choice.measObjectEUTRA.neighCellConfig.size = 1; MeasObj->measObject.choice.measObjectEUTRA.neighCellConfig.bits_unused = 6; MeasObj->measObject.choice.measObjectEUTRA.offsetFreq = NULL; // Default is 15 or 0dB - MeasObj->measObject.choice.measObjectEUTRA.cellsToAddModList = - (LTE_CellsToAddModList_t *) CALLOC(1, sizeof(*CellsToAddModList)); - CellsToAddModList = MeasObj->measObject.choice.measObjectEUTRA.cellsToAddModList; + + if (RC.rrc[ctxt_pP->module_id]->num_neigh_cells > 0) { + MeasObj->measObject.choice.measObjectEUTRA.cellsToAddModList = + (LTE_CellsToAddModList_t *) CALLOC(1, sizeof(*CellsToAddModList)); + CellsToAddModList = MeasObj->measObject.choice.measObjectEUTRA.cellsToAddModList; + } if (!ue_context_pP->ue_context.measurement_info) { ue_context_pP->ue_context.measurement_info = CALLOC(1,sizeof(*(ue_context_pP->ue_context.measurement_info))); From 3cd1717fb648cb452692c03b794d75dd2f0c5424 Mon Sep 17 00:00:00 2001 From: Konstantinos Alexandris Date: Mon, 29 Apr 2019 15:03:03 +0200 Subject: [PATCH 10/32] add measurement information/clean-up measurement report in flexran agent --- .../CONTROL_MODULES/RRC/flexran_agent_rrc.c | 172 ++++++++++++++---- openair2/ENB_APP/flexran_agent_ran_api.c | 5 + openair2/ENB_APP/flexran_agent_ran_api.h | 2 + 3 files changed, 143 insertions(+), 36 deletions(-) diff --git a/openair2/ENB_APP/CONTROL_MODULES/RRC/flexran_agent_rrc.c b/openair2/ENB_APP/CONTROL_MODULES/RRC/flexran_agent_rrc.c index 9df22c6937..32038ee153 100644 --- a/openair2/ENB_APP/CONTROL_MODULES/RRC/flexran_agent_rrc.c +++ b/openair2/ENB_APP/CONTROL_MODULES/RRC/flexran_agent_rrc.c @@ -130,6 +130,18 @@ int flexran_agent_destroy_ue_state_change(Protocol__FlexranMessage *msg) { free(msg->ue_state_change_msg->header); if (msg->ue_state_change_msg->config->capabilities) free(msg->ue_state_change_msg->config->capabilities); + if (msg->ue_state_change_msg->config->info) { + if (msg->ue_state_change_msg->config->info->cell_individual_offset) { + free(msg->ue_state_change_msg->config->info->cell_individual_offset); + } + if (msg->ue_state_change_msg->config->info->event) { + if (msg->ue_state_change_msg->config->info->event->a3) { + free(msg->ue_state_change_msg->config->info->event->a3); + } + free(msg->ue_state_change_msg->config->info->event); + } + free(msg->ue_state_change_msg->config->info); + } free(msg->ue_state_change_msg->config); free(msg->ue_state_change_msg); free(msg); @@ -442,58 +454,66 @@ int flexran_agent_rrc_stats_reply(mid_t mod_id, Protocol__FlexEutraCgiMeasurements *cgi_meas; cgi_meas = malloc(sizeof(Protocol__FlexEutraCgiMeasurements)); - protocol__flex_eutra_cgi_measurements__init(cgi_meas); + if (cgi_meas) { + protocol__flex_eutra_cgi_measurements__init(cgi_meas); - /* EUTRA Cell Global Identity (CGI) */ - Protocol__FlexCellGlobalEutraId *cgi; - cgi = malloc(sizeof(Protocol__FlexCellGlobalEutraId)); + cgi_meas->tracking_area_code = flexran_get_rrc_neigh_cgi_tac(mod_id, rnti, j); + cgi_meas->has_tracking_area_code = 1; - protocol__flex_cell_global_eutra_id__init(cgi); + /* EUTRA Cell Global Identity (CGI) */ + Protocol__FlexCellGlobalEutraId *cgi; + cgi = malloc(sizeof(Protocol__FlexCellGlobalEutraId)); - cgi->cell_id = flexran_get_rrc_neigh_cgi_cell_id(mod_id, rnti, j); - cgi->has_cell_id = 1; + if (cgi) { + protocol__flex_cell_global_eutra_id__init(cgi); - cgi_meas->tracking_area_code = flexran_get_rrc_neigh_cgi_tac(mod_id, rnti, j); - cgi_meas->has_tracking_area_code = 1; + cgi->cell_id = flexran_get_rrc_neigh_cgi_cell_id(mod_id, rnti, j); + cgi->has_cell_id = 1; - /* PLMN for neighbouring cell */ - Protocol__FlexPlmnIdentity *plmn_id; - plmn_id = malloc(sizeof(Protocol__FlexPlmnIdentity)); + /* PLMN for neighbouring cell */ + Protocol__FlexPlmnIdentity *plmn_id; + plmn_id = malloc(sizeof(Protocol__FlexPlmnIdentity)); - protocol__flex_plmn_identity__init(plmn_id); + if (plmn_id) { + protocol__flex_plmn_identity__init(plmn_id); - plmn_id->mcc = 0; - plmn_id->n_mcc = flexran_get_rrc_neigh_cgi_num_mcc(mod_id, rnti, j); + plmn_id->mcc = 0; + plmn_id->n_mcc = flexran_get_rrc_neigh_cgi_num_mcc(mod_id, rnti, j); - for (int m = 0; m < plmn_id->n_mcc; m++) { - plmn_id->mcc += flexran_get_rrc_neigh_cgi_mcc(mod_id, rnti, j, m); + for (int m = 0; m < plmn_id->n_mcc; m++) { + plmn_id->mcc += flexran_get_rrc_neigh_cgi_mcc(mod_id, rnti, j, m); + } + + plmn_id->mnc = 0; + plmn_id->n_mnc = flexran_get_rrc_neigh_cgi_num_mnc(mod_id, rnti, j); + + for (int m = 0; m < plmn_id->n_mnc; m++) { + plmn_id->mnc += flexran_get_rrc_neigh_cgi_mnc(mod_id, rnti, j, m); + } + + cgi->plmn_id = plmn_id; + } + cgi_meas->cgi = cgi; + } + eutra_meas[j]->cgi_meas = cgi_meas; } - - plmn_id->mnc = 0; - plmn_id->n_mnc = flexran_get_rrc_neigh_cgi_num_mnc(mod_id, rnti, j); - - for (int m = 0; m < plmn_id->n_mnc; m++) { - plmn_id->mnc += flexran_get_rrc_neigh_cgi_mnc(mod_id, rnti, j, m); - } - - cgi->plmn_id = plmn_id; - cgi_meas->cgi = cgi; - eutra_meas[j]->cgi_meas = cgi_meas; } /*RSRP/RSRQ of the neighbouring cell */ Protocol__FlexEutraRefSignalMeas *meas_result; meas_result = malloc(sizeof(Protocol__FlexEutraRefSignalMeas)); - protocol__flex_eutra_ref_signal_meas__init(meas_result); + if (meas_result) { + protocol__flex_eutra_ref_signal_meas__init(meas_result); - meas_result->rsrp = flexran_get_rrc_neigh_rsrp(mod_id, rnti, j); - meas_result->has_rsrp = 1; + meas_result->rsrp = flexran_get_rrc_neigh_rsrp(mod_id, rnti, j); + meas_result->has_rsrp = 1; - meas_result->rsrq = flexran_get_rrc_neigh_rsrq(mod_id, rnti, j); - meas_result->has_rsrq = 1; + meas_result->rsrq = flexran_get_rrc_neigh_rsrq(mod_id, rnti, j); + meas_result->has_rsrq = 1; - eutra_meas[j]->meas_result = meas_result; + eutra_meas[j]->meas_result = meas_result; + } } neigh_meas->eutra_meas = eutra_meas; @@ -531,8 +551,18 @@ int flexran_agent_rrc_destroy_stats_reply(Protocol__FlexStatsReply *reply) for (int i = 0; i < reply->n_ue_report; i++){ if (reply->ue_report[i]->rrc_measurements && reply->ue_report[i]->rrc_measurements->neigh_meas) { for (int j = 0; j < reply->ue_report[i]->rrc_measurements->neigh_meas->n_eutra_meas; j++) { - free(reply->ue_report[i]->rrc_measurements->neigh_meas->eutra_meas[j]->cgi_meas); - free(reply->ue_report[i]->rrc_measurements->neigh_meas->eutra_meas[j]->meas_result); + if (reply->ue_report[i]->rrc_measurements->neigh_meas->eutra_meas[j]->cgi_meas) { + if (reply->ue_report[i]->rrc_measurements->neigh_meas->eutra_meas[j]->cgi_meas->cgi) { + if (reply->ue_report[i]->rrc_measurements->neigh_meas->eutra_meas[j]->cgi_meas->plmn_id) { + free(reply->ue_report[i]->rrc_measurements->neigh_meas->eutra_meas[j]->cgi_meas->cgi->plmn_id); + } + free(reply->ue_report[i]->rrc_measurements->neigh_meas->eutra_meas[j]->cgi_meas->cgi); + } + free(reply->ue_report[i]->rrc_measurements->neigh_meas->eutra_meas[j]->cgi_meas); + } + if (reply->ue_report[i]->rrc_measurements->neigh_meas->eutra_meas[j]->meas_result) { + free(reply->ue_report[i]->rrc_measurements->neigh_meas->eutra_meas[j]->meas_result); + } free(reply->ue_report[i]->rrc_measurements->neigh_meas->eutra_meas[j]); } free(reply->ue_report[i]->rrc_measurements->neigh_meas->eutra_meas); @@ -641,6 +671,76 @@ void flexran_agent_fill_rrc_ue_config(mid_t mod_id, rnti_t rnti, ue_conf->has_extended_bsr_size = 1; ue_conf->extended_bsr_size = flexran_get_extended_bsr_size(mod_id, rnti); + + Protocol__FlexMeasurementInfo *meas_info; + meas_info = malloc(sizeof(Protocol__FlexMeasurementInfo)); + + if (meas_info) { + protocol__flex_measurement_info__init(meas_info); + + meas_info->has_offset_freq_serving = 1; + meas_info->offset_freq_serving = flexran_get_rrc_ofp(mod_id, rnti); + + meas_info->has_offset_freq_neighbouring = 1; + meas_info->offset_freq_neighbouring = flexran_get_rrc_ofn(mod_id, rnti); + + int num_adj_cells = flexran_get_rrc_num_adj_cells(mod_id); + meas_info->n_cell_individual_offset = num_adj_cells + 1; + + int64_t *cell_individual_offset; + if (num_adj_cells > 0) { + cell_individual_offset = malloc(sizeof(int64_t)*(num_adj_cells+1)); + if (cell_individual_offset) { + cell_individual_offset[0] = flexran_get_rrc_ocp(mod_id, rnti); + for (int i=0; i < num_adj_cells; i++) { + cell_individual_offset[i+1] = flexran_get_rrc_ocn(mod_id, rnti,i); + } + meas_info->cell_individual_offset = cell_individual_offset; + } + } + else { + cell_individual_offset = malloc(sizeof(int64_t)); + if (cell_individual_offset) { + *cell_individual_offset = flexran_get_rrc_ocp(mod_id, rnti); + meas_info->cell_individual_offset = cell_individual_offset; + } + } + + meas_info->has_filter_coefficient_rsrp = 1; + meas_info->filter_coefficient_rsrp = flexran_get_filter_coeff_rsrp(mod_id, rnti); + + meas_info->has_filter_coefficient_rsrq = 1; + meas_info->filter_coefficient_rsrq = flexran_get_filter_coeff_rsrq(mod_id, rnti); + + Protocol__FlexMeasurementEvent *event; + event = malloc(sizeof(Protocol__FlexMeasurementEvent)); + + if (event) { + protocol__flex_measurement_event__init(event); + Protocol__FlexA3Event *a3_event; + a3_event = malloc(sizeof(Protocol__FlexA3Event)); + if (a3_event) { + protocol__flex_a3_event__init(a3_event); + a3_event->has_a3_offset = 1; + a3_event->a3_offset = flexran_get_rrc_a3_event_a3_offset(mod_id, rnti); + + a3_event->has_report_on_leave = 1; + a3_event->report_on_leave = flexran_get_rrc_a3_event_reportOnLeave(mod_id, rnti); + + a3_event->has_hysteresis = 1; + a3_event->hysteresis = flexran_get_rrc_a3_event_hysteresis(mod_id, rnti); + + a3_event->has_time_to_trigger = 1; + a3_event->time_to_trigger = flexran_get_rrc_a3_event_timeToTrigger(mod_id, rnti); + + a3_event->has_max_report_cells = 1; + a3_event->max_report_cells = flexran_get_rrc_a3_event_maxReportCells(mod_id, rnti); + event->a3 = a3_event; + } + meas_info->event = event; + } + ue_conf->info = meas_info; + } } int flexran_agent_register_rrc_xface(mid_t mod_id) diff --git a/openair2/ENB_APP/flexran_agent_ran_api.c b/openair2/ENB_APP/flexran_agent_ran_api.c index 634dc775f1..b418e9cbb3 100644 --- a/openair2/ENB_APP/flexran_agent_ran_api.c +++ b/openair2/ENB_APP/flexran_agent_ran_api.c @@ -1697,6 +1697,11 @@ uint8_t flexran_get_rrc_mnc_digit_length(mid_t mod_id, uint8_t index) { return RC.rrc[mod_id]->configuration.mnc_digit_length[index]; } +int flexran_get_rrc_num_adj_cells(mid_t mod_id) { + if (!rrc_is_present(mod_id)) return 0; + return RC.rrc[mod_id]->num_neigh_cells; +} + /**************************** SLICING ****************************/ int flexran_get_ue_dl_slice_id(mid_t mod_id, mid_t ue_id) { diff --git a/openair2/ENB_APP/flexran_agent_ran_api.h b/openair2/ENB_APP/flexran_agent_ran_api.h index 4a65284cba..6efa7986dd 100644 --- a/openair2/ENB_APP/flexran_agent_ran_api.h +++ b/openair2/ENB_APP/flexran_agent_ran_api.h @@ -588,6 +588,8 @@ uint16_t flexran_get_rrc_mnc(mid_t mod_id, uint8_t index); /* Get index'th MNC's digit length broadcasted in SIB1 */ uint8_t flexran_get_rrc_mnc_digit_length(mid_t mod_id, uint8_t index); +/* Get number of adjacent cells via X2 interface */ +int flexran_get_rrc_num_adj_cells(mid_t mod_id); /************************** Slice configuration **************************/ /* Get the DL slice ID for a UE */ From 1de4b7400b583a10a8b35a59af22340dfde52c4a Mon Sep 17 00:00:00 2001 From: Konstantinos Alexandris Date: Mon, 29 Apr 2019 18:25:48 +0200 Subject: [PATCH 11/32] Fix: flexran agent for HO case, to be tested if Nb_ue in RRC is needed --- openair2/RRC/LTE/rrc_eNB.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/openair2/RRC/LTE/rrc_eNB.c b/openair2/RRC/LTE/rrc_eNB.c index 5401f0a3f1..814f3aa178 100644 --- a/openair2/RRC/LTE/rrc_eNB.c +++ b/openair2/RRC/LTE/rrc_eNB.c @@ -7204,6 +7204,7 @@ rrc_eNB_decode_dcch( LTE_RRCConnectionReconfigurationComplete__criticalExtensions_PR_rrcConnectionReconfigurationComplete_r8) { /*NN: revise the condition */ /*FK: left the condition as is for the case MME is used (S1 mode) but setting dedicated_DRB = 1 otherwise (noS1 mode) so that no second RRCReconfiguration message activationg more DRB is sent as this causes problems with the nasmesh driver.*/ + int flexran_agent_handover = 0; if (EPC_MODE_ENABLED) { if (ue_context_p->ue_context.Status == RRC_RECONFIGURED) { dedicated_DRB = 1; @@ -7240,6 +7241,8 @@ rrc_eNB_decode_dcch( break; } + flexran_agent_handover = 1; + RC.rrc[ctxt_pP->module_id]->Nb_ue++; dedicated_DRB = 3; RC.mac[ctxt_pP->module_id]->UE_list.UE_sched_ctrl[UE_id].crnti_reconfigurationcomplete_flag = 0; ue_context_p->ue_context.Status = RRC_RECONFIGURED; @@ -7272,7 +7275,7 @@ rrc_eNB_decode_dcch( if (flexran_agent_get_rrc_xface(ctxt_pP->module_id)) { flexran_agent_get_rrc_xface(ctxt_pP->module_id)->flexran_agent_notify_ue_state_change(ctxt_pP->module_id, ue_context_p->ue_id_rnti, - PROTOCOL__FLEX_UE_STATE_CHANGE_TYPE__FLUESC_UPDATED); + flexran_agent_handover?PROTOCOL__FLEX_UE_STATE_CHANGE_TYPE__FLUESC_ACTIVATED:PROTOCOL__FLEX_UE_STATE_CHANGE_TYPE__FLUESC_UPDATED); } } From 1b90c4a02d3924e99d2fc8039b8f30fd882b2aa0 Mon Sep 17 00:00:00 2001 From: Konstantinos Alexandris Date: Fri, 10 May 2019 17:45:47 +0200 Subject: [PATCH 12/32] Create RRC setters for Periodic, A1-A5 event and offsets related to RRC Measurement Report --- cmake_targets/CMakeLists.txt | 1 + .../RRC/flexran_agent_rrc_internal.c | 147 +++++ .../RRC/flexran_agent_rrc_internal.h | 31 + openair2/ENB_APP/MESSAGES/V2/flexran.proto | 5 +- openair2/ENB_APP/flexran_agent_common.c | 53 +- openair2/ENB_APP/flexran_agent_ran_api.c | 398 ++++++++++++- openair2/ENB_APP/flexran_agent_ran_api.h | 39 ++ openair2/RRC/LTE/rrc_eNB.c | 528 ++++++++++++------ openair2/RRC/LTE/rrc_proto.h | 3 +- 9 files changed, 1020 insertions(+), 185 deletions(-) create mode 100644 openair2/ENB_APP/CONTROL_MODULES/RRC/flexran_agent_rrc_internal.c create mode 100644 openair2/ENB_APP/CONTROL_MODULES/RRC/flexran_agent_rrc_internal.h diff --git a/cmake_targets/CMakeLists.txt b/cmake_targets/CMakeLists.txt index 29792d1260..8f08c2375f 100644 --- a/cmake_targets/CMakeLists.txt +++ b/cmake_targets/CMakeLists.txt @@ -887,6 +887,7 @@ add_library(FLEXRAN_AGENT ${OPENAIR2_DIR}/ENB_APP/CONTROL_MODULES/PHY/flexran_agent_phy.c ${OPENAIR2_DIR}/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac.c ${OPENAIR2_DIR}/ENB_APP/CONTROL_MODULES/RRC/flexran_agent_rrc.c + ${OPENAIR2_DIR}/ENB_APP/CONTROL_MODULES/RRC/flexran_agent_rrc_internal.c ${OPENAIR2_DIR}/ENB_APP/CONTROL_MODULES/PDCP/flexran_agent_pdcp.c ${OPENAIR2_DIR}/ENB_APP/flexran_agent.c ${OPENAIR2_DIR}/ENB_APP/flexran_agent_task_manager.c diff --git a/openair2/ENB_APP/CONTROL_MODULES/RRC/flexran_agent_rrc_internal.c b/openair2/ENB_APP/CONTROL_MODULES/RRC/flexran_agent_rrc_internal.c new file mode 100644 index 0000000000..e8bbd13af4 --- /dev/null +++ b/openair2/ENB_APP/CONTROL_MODULES/RRC/flexran_agent_rrc_internal.c @@ -0,0 +1,147 @@ +/* + * 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 "flexran_agent_rrc_internal.h" +#include "flexran_agent_ran_api.h" + +int update_rrc_reconfig(mid_t mod_id, rnti_t rnti, Protocol__FlexRrcTriggering *trigg) { + + // Measurement info reconfiguration + + if (trigg->meas_info) { + + /* Set serving cell frequency offset */ + if (trigg->meas_info->has_offset_freq_serving) { + if (flexran_set_rrc_ofp(mod_id, rnti, trigg->meas_info->offset_freq_serving) < 0) { + LOG_E(FLEXRAN_AGENT, "Cannot set Serving cell frequency offset\n"); + return -1; + } + } + + /* Set neighbouring cell frequency offset */ + if (trigg->meas_info->has_offset_freq_neighbouring) { + if (flexran_set_rrc_ofn(mod_id, rnti, trigg->meas_info->offset_freq_neighbouring) < 0) { + LOG_E(FLEXRAN_AGENT, "Cannot set Neighbouring cell frequency offset\n"); + return -1; + } + } + + if (trigg->meas_info->n_cell_individual_offset > 0) { + /* Set the serving cell offset */ + if (flexran_set_rrc_ocp(mod_id, rnti, trigg->meas_info->cell_individual_offset[0]) < 0) { + LOG_E(FLEXRAN_AGENT, "Cannot set Serving cell offset\n"); + return -1; + } + + /* Set the neighbouring cell offset */ + for (int i=0; i<(trigg->meas_info->n_cell_individual_offset-1); i++) { + if (flexran_set_rrc_ocn(mod_id, rnti, i, trigg->meas_info->cell_individual_offset[i+1]) < 0) { + LOG_E(FLEXRAN_AGENT, "Cannot set Neighbouring cell offset\n"); + return -1; + } + } + } + + if (trigg->meas_info->has_offset_freq_neighbouring) { + if (flexran_set_rrc_ofn(mod_id, rnti, trigg->meas_info->offset_freq_neighbouring) < 0) { + LOG_E(FLEXRAN_AGENT, "Cannot set Neighbouring cell frequency offset\n"); + return -1; + } + } + + + /* Set rsrp filter coefficient */ + if (trigg->meas_info->has_filter_coefficient_rsrp) { + if (flexran_set_filter_coeff_rsrp(mod_id, rnti, trigg->meas_info->filter_coefficient_rsrp) < 0) { + LOG_E(FLEXRAN_AGENT, "Cannot set RSRP filter coefficient\n"); + return -1; + } + } + + /* Set rsrq filter coefficient */ + if (trigg->meas_info->has_filter_coefficient_rsrq) { + if (flexran_set_filter_coeff_rsrq(mod_id, rnti, trigg->meas_info->filter_coefficient_rsrq) < 0) { + LOG_E(FLEXRAN_AGENT, "Cannot set RSRQ filter coefficient\n"); + return -1; + } + } + + if (trigg->meas_info->event) { + + /* Set Periodic event parameters */ + if (trigg->meas_info->event->periodical) { + + /* Set Periodic event maximum number of reported cells */ + if (trigg->meas_info->event->periodical->has_max_report_cells) { + if (flexran_set_rrc_per_event_maxReportCells(mod_id, rnti, trigg->meas_info->event->periodical->max_report_cells) < 0) { + LOG_E(FLEXRAN_AGENT, "Cannot set Periodic event max\n"); + return -1; + } + } + } + + /* Set A3 event parameters */ + if (trigg->meas_info->event->a3) { + + /* Set A3 event a3 offset */ + if (trigg->meas_info->event->a3->has_a3_offset) { + if (flexran_set_rrc_a3_event_a3_offset(mod_id, rnti, trigg->meas_info->event->a3->a3_offset) < 0) { + LOG_E(FLEXRAN_AGENT, "Cannot set A3 event offset\n"); + return -1; + } + } + + /* Set A3 event report on leave */ + if (trigg->meas_info->event->a3->has_report_on_leave) { + if (flexran_set_rrc_a3_event_reportOnLeave(mod_id, rnti, trigg->meas_info->event->a3->report_on_leave) < 0) { + LOG_E(FLEXRAN_AGENT, "Cannot set A3 event report on leave\n"); + return -1; + } + } + + /* Set A3 event hysteresis */ + if (trigg->meas_info->event->a3->has_hysteresis) { + if (flexran_set_rrc_a3_event_hysteresis(mod_id, rnti, trigg->meas_info->event->a3->hysteresis) < 0) { + LOG_E(FLEXRAN_AGENT, "Cannot set A3 event hysteresis\n"); + return -1; + } + } + + /* Set A3 event time to trigger */ + if (trigg->meas_info->event->a3->has_time_to_trigger) { + if (flexran_set_rrc_a3_event_timeToTrigger(mod_id, rnti, trigg->meas_info->event->a3->time_to_trigger) < 0) { + LOG_E(FLEXRAN_AGENT, "Cannot set A3 event time to trigger\n"); + return -1; + } + } + + /* Set A3 event maximum number of reported cells */ + if (trigg->meas_info->event->a3->has_max_report_cells) { + if (flexran_set_rrc_a3_event_maxReportCells(mod_id, rnti, trigg->meas_info->event->a3->max_report_cells) < 0) { + LOG_E(FLEXRAN_AGENT, "Cannot set A3 event max report cells\n"); + return -1; + } + } + } + } + } + return 0; +} diff --git a/openair2/ENB_APP/CONTROL_MODULES/RRC/flexran_agent_rrc_internal.h b/openair2/ENB_APP/CONTROL_MODULES/RRC/flexran_agent_rrc_internal.h new file mode 100644 index 0000000000..3987cb8f3f --- /dev/null +++ b/openair2/ENB_APP/CONTROL_MODULES/RRC/flexran_agent_rrc_internal.h @@ -0,0 +1,31 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +#ifndef FLEXRAN_AGENT_RRC_INTERNAL_H_ +#define FLEXRAN_AGENT_RRC_INTERNAL_H_ + +#include "flexran_agent_rrc_internal.h" +#include "flexran_agent_ran_api.h" + +int update_rrc_reconfig(mid_t mod_id, rnti_t rnti, Protocol__FlexRrcTriggering *trigg); + +#endif /*FLEXRAN_AGENT_RRC_INTERNAL_H_*/ + diff --git a/openair2/ENB_APP/MESSAGES/V2/flexran.proto b/openair2/ENB_APP/MESSAGES/V2/flexran.proto index b1702f949e..840e53f616 100644 --- a/openair2/ENB_APP/MESSAGES/V2/flexran.proto +++ b/openair2/ENB_APP/MESSAGES/V2/flexran.proto @@ -7,7 +7,7 @@ import "time_common.proto"; import "config_messages.proto"; import "controller_commands.proto"; import "control_delegation.proto"; - +import "config_common.proto"; message flexran_message { optional flexran_direction msg_dir = 100; @@ -188,7 +188,8 @@ message flex_ul_mac_config { message flex_rrc_triggering { optional flex_header header = 1; - optional string rrc_trigger = 2; + optional string rrc_trigger = 2; + optional flex_measurement_info meas_info = 3; } // diff --git a/openair2/ENB_APP/flexran_agent_common.c b/openair2/ENB_APP/flexran_agent_common.c index 5cbcee370a..e2bd5f8146 100644 --- a/openair2/ENB_APP/flexran_agent_common.c +++ b/openair2/ENB_APP/flexran_agent_common.c @@ -41,6 +41,7 @@ //#include "PHY/extern.h" #include "common/utils/LOG/log.h" #include "flexran_agent_mac_internal.h" +#include "flexran_agent_rrc_internal.h" //#include "SCHED/defs.h" #include "RRC/LTE/rrc_extern.h" @@ -805,10 +806,12 @@ error: int flexran_agent_rrc_measurement(mid_t mod_id, const void *params, Protocol__FlexranMessage **msg) { - protocol_ctxt_t ctxt; + //protocol_ctxt_t ctxt; Protocol__FlexranMessage *input = (Protocol__FlexranMessage *)params; Protocol__FlexRrcTriggering *triggering = input->rrc_triggering; - agent_reconf_rrc *reconf_param = malloc(sizeof(agent_reconf_rrc)); + //agent_reconf_rrc *rrc_reconf = malloc(sizeof(agent_reconf_rrc)); + + #if 0 reconf_param->trigger_policy = triggering->rrc_trigger; reconf_param->report_interval = 0; reconf_param->report_amount = 0; @@ -817,9 +820,51 @@ int flexran_agent_rrc_measurement(mid_t mod_id, const void *params, Protocol__Fl PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, mod_id, ENB_FLAG_YES, ue_context_p->ue_context.rnti, flexran_get_current_frame(mod_id), flexran_get_current_subframe (mod_id), mod_id); flexran_rrc_eNB_generate_defaultRRCConnectionReconfiguration(&ctxt, ue_context_p, 0, reconf_param); } + #endif + + // TODO: Step 1 - Verification process + + // Step 2 - Set the proper values using FlexRAN API (protected with mutex ?) + int num_ue = 0; + + if (flexran_agent_get_rrc_xface(mod_id)) + num_ue = flexran_get_rrc_num_ues(mod_id); + else if (flexran_agent_get_mac_xface(mod_id)) + num_ue = flexran_get_mac_num_ues(mod_id); + + if (flexran_agent_get_rrc_xface(mod_id) && flexran_agent_get_mac_xface(mod_id) + && flexran_get_rrc_num_ues(mod_id) != flexran_get_mac_num_ues(mod_id)) { + const int nrrc = flexran_get_rrc_num_ues(mod_id); + const int nmac = flexran_get_mac_num_ues(mod_id); + num_ue = nrrc < nmac ? nrrc : nmac; + LOG_E(FLEXRAN_AGENT, "%s(): different numbers of UEs in RRC (%d) and MAC (%d), reporting for %d UEs\n", + __func__, nrrc, nmac, num_ue); + } + + if (num_ue == 0) + return 0; + + int error = 0; + rnti_t rntis[num_ue]; + flexran_get_rrc_rnti_list(mod_id, rntis, num_ue); + for (int i = 0; i < num_ue; i++) { + const rnti_t rnti = rntis[i]; + if (flexran_agent_get_rrc_xface(mod_id)) + error = update_rrc_reconfig(mod_id, rnti, triggering); + if (error < 0) { + LOG_E(FLEXRAN_AGENT, "Error in updating user %d\n", i); + } + else { + // Step 3 - Call the proper wrapper in FlexRAN API + if (flexran_call_rrc_reconfiguration (mod_id, rnti) <0) { + LOG_E(FLEXRAN_AGENT, "Error in reconfiguring user %d\n", i); + } + } + } + *msg = NULL; - free(reconf_param); - reconf_param = NULL; + //free(reconf_param); + //reconf_param = NULL; return 0; } diff --git a/openair2/ENB_APP/flexran_agent_ran_api.c b/openair2/ENB_APP/flexran_agent_ran_api.c index b418e9cbb3..b711e9b13e 100644 --- a/openair2/ENB_APP/flexran_agent_ran_api.c +++ b/openair2/ENB_APP/flexran_agent_ran_api.c @@ -1434,6 +1434,19 @@ uint32_t flexran_get_pdcp_rx_oo(mid_t mod_id, uint16_t uid, lcid_t lcid) } /******************** RRC *****************************/ +/* RRC Wrappers */ +int flexran_call_rrc_reconfiguration (mid_t mod_id, rnti_t rnti) { + if (!rrc_is_present(mod_id)) return -1; + protocol_ctxt_t ctxt; + memset(&ctxt, 0, sizeof(ctxt)); + struct rrc_eNB_ue_context_s* ue_context_p = rrc_eNB_get_ue_context(RC.rrc[mod_id], rnti); + if (!ue_context_p) return -1; + PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, mod_id, ENB_FLAG_YES, ue_context_p->ue_context.rnti, flexran_get_current_frame(mod_id), flexran_get_current_subframe (mod_id), mod_id); + flexran_rrc_eNB_generate_defaultRRCConnectionReconfiguration(&ctxt, ue_context_p, 0); + return 0; +} + +/* RRC Getters */ LTE_MeasId_t flexran_get_rrc_pcell_measid(mid_t mod_id, rnti_t rnti) { if (!rrc_is_present(mod_id)) return -1; @@ -1565,6 +1578,8 @@ float flexran_get_rrc_neigh_rsrq(mid_t mod_id, rnti_t rnti, long cell_id) { return RSRQ_meas_mapping[*(ue_context_p->ue_context.measResults->measResultNeighCells->choice.measResultListEUTRA.list.array[cell_id]->measResult.rsrqResult)]; } +/* Measurement offsets */ + long flexran_get_rrc_ofp(mid_t mod_id, rnti_t rnti) { if (!rrc_is_present(mod_id)) return -1; struct rrc_eNB_ue_context_s* ue_context_p = rrc_eNB_get_ue_context(RC.rrc[mod_id], rnti); @@ -1586,7 +1601,40 @@ long flexran_get_rrc_ocp(mid_t mod_id, rnti_t rnti) { struct rrc_eNB_ue_context_s* ue_context_p = rrc_eNB_get_ue_context(RC.rrc[mod_id], rnti); if (!ue_context_p) return -1; if (!ue_context_p->ue_context.measurement_info) return -1; - return ue_context_p->ue_context.measurement_info->cellIndividualOffset[0]; + switch (ue_context_p->ue_context.measurement_info->cellIndividualOffset[0]) { + case LTE_Q_OffsetRange_dB_24: return -24; + case LTE_Q_OffsetRange_dB_22: return -22; + case LTE_Q_OffsetRange_dB_20: return -20; + case LTE_Q_OffsetRange_dB_18: return -18; + case LTE_Q_OffsetRange_dB_16: return -16; + case LTE_Q_OffsetRange_dB_14: return -14; + case LTE_Q_OffsetRange_dB_12: return -12; + case LTE_Q_OffsetRange_dB_10: return -10; + case LTE_Q_OffsetRange_dB_8: return -8; + case LTE_Q_OffsetRange_dB_6: return -6; + case LTE_Q_OffsetRange_dB_5: return -5; + case LTE_Q_OffsetRange_dB_4: return -4; + case LTE_Q_OffsetRange_dB_3: return -3; + case LTE_Q_OffsetRange_dB_2: return -2; + case LTE_Q_OffsetRange_dB_1: return -1; + case LTE_Q_OffsetRange_dB0: return 0; + case LTE_Q_OffsetRange_dB1: return 1; + case LTE_Q_OffsetRange_dB2: return 2; + case LTE_Q_OffsetRange_dB3: return 3; + case LTE_Q_OffsetRange_dB4: return 4; + case LTE_Q_OffsetRange_dB5: return 5; + case LTE_Q_OffsetRange_dB6: return 6; + case LTE_Q_OffsetRange_dB8: return 8; + case LTE_Q_OffsetRange_dB10: return 10; + case LTE_Q_OffsetRange_dB12: return 12; + case LTE_Q_OffsetRange_dB14: return 14; + case LTE_Q_OffsetRange_dB16: return 16; + case LTE_Q_OffsetRange_dB18: return 18; + case LTE_Q_OffsetRange_dB20: return 20; + case LTE_Q_OffsetRange_dB22: return 22; + case LTE_Q_OffsetRange_dB24: return 24; + default: return -99; + } } long flexran_get_rrc_ocn(mid_t mod_id, rnti_t rnti, long cell_id) { @@ -1594,7 +1642,40 @@ long flexran_get_rrc_ocn(mid_t mod_id, rnti_t rnti, long cell_id) { struct rrc_eNB_ue_context_s* ue_context_p = rrc_eNB_get_ue_context(RC.rrc[mod_id], rnti); if (!ue_context_p) return -1; if (!ue_context_p->ue_context.measurement_info) return -1; - return ue_context_p->ue_context.measurement_info->cellIndividualOffset[cell_id+1]; + switch (ue_context_p->ue_context.measurement_info->cellIndividualOffset[cell_id+1]) { + case LTE_Q_OffsetRange_dB_24: return -24; + case LTE_Q_OffsetRange_dB_22: return -22; + case LTE_Q_OffsetRange_dB_20: return -20; + case LTE_Q_OffsetRange_dB_18: return -18; + case LTE_Q_OffsetRange_dB_16: return -16; + case LTE_Q_OffsetRange_dB_14: return -14; + case LTE_Q_OffsetRange_dB_12: return -12; + case LTE_Q_OffsetRange_dB_10: return -10; + case LTE_Q_OffsetRange_dB_8: return -8; + case LTE_Q_OffsetRange_dB_6: return -6; + case LTE_Q_OffsetRange_dB_5: return -5; + case LTE_Q_OffsetRange_dB_4: return -4; + case LTE_Q_OffsetRange_dB_3: return -3; + case LTE_Q_OffsetRange_dB_2: return -2; + case LTE_Q_OffsetRange_dB_1: return -1; + case LTE_Q_OffsetRange_dB0: return 0; + case LTE_Q_OffsetRange_dB1: return 1; + case LTE_Q_OffsetRange_dB2: return 2; + case LTE_Q_OffsetRange_dB3: return 3; + case LTE_Q_OffsetRange_dB4: return 4; + case LTE_Q_OffsetRange_dB5: return 5; + case LTE_Q_OffsetRange_dB6: return 6; + case LTE_Q_OffsetRange_dB8: return 8; + case LTE_Q_OffsetRange_dB10: return 10; + case LTE_Q_OffsetRange_dB12: return 12; + case LTE_Q_OffsetRange_dB14: return 14; + case LTE_Q_OffsetRange_dB16: return 16; + case LTE_Q_OffsetRange_dB18: return 18; + case LTE_Q_OffsetRange_dB20: return 20; + case LTE_Q_OffsetRange_dB22: return 22; + case LTE_Q_OffsetRange_dB24: return 24; + default: return -99; + } } long flexran_get_filter_coeff_rsrp(mid_t mod_id, rnti_t rnti) { @@ -1602,7 +1683,25 @@ long flexran_get_filter_coeff_rsrp(mid_t mod_id, rnti_t rnti) { struct rrc_eNB_ue_context_s* ue_context_p = rrc_eNB_get_ue_context(RC.rrc[mod_id], rnti); if (!ue_context_p) return -1; if (!ue_context_p->ue_context.measurement_info) return -1; - return ue_context_p->ue_context.measurement_info->filterCoefficientRSRP; + switch (ue_context_p->ue_context.measurement_info->filterCoefficientRSRP) { + case LTE_FilterCoefficient_fc0: return 0; + case LTE_FilterCoefficient_fc1: return 1; + case LTE_FilterCoefficient_fc2: return 2; + case LTE_FilterCoefficient_fc3: return 3; + case LTE_FilterCoefficient_fc4: return 4; + case LTE_FilterCoefficient_fc5: return 5; + case LTE_FilterCoefficient_fc6: return 6; + case LTE_FilterCoefficient_fc7: return 7; + case LTE_FilterCoefficient_fc8: return 8; + case LTE_FilterCoefficient_fc9: return 9; + case LTE_FilterCoefficient_fc11: return 11; + case LTE_FilterCoefficient_fc13: return 13; + case LTE_FilterCoefficient_fc15: return 15; + case LTE_FilterCoefficient_fc17: return 17; + case LTE_FilterCoefficient_fc19: return 19; + case LTE_FilterCoefficient_spare1: return -1; /* spare means no coefficient */ + default: return -1; + } } long flexran_get_filter_coeff_rsrq(mid_t mod_id, rnti_t rnti) { @@ -1610,7 +1709,25 @@ long flexran_get_filter_coeff_rsrq(mid_t mod_id, rnti_t rnti) { struct rrc_eNB_ue_context_s* ue_context_p = rrc_eNB_get_ue_context(RC.rrc[mod_id], rnti); if (!ue_context_p) return -1; if (!ue_context_p->ue_context.measurement_info) return -1; - return ue_context_p->ue_context.measurement_info->filterCoefficientRSRQ; + switch (ue_context_p->ue_context.measurement_info->filterCoefficientRSRQ) { + case LTE_FilterCoefficient_fc0: return 0; + case LTE_FilterCoefficient_fc1: return 1; + case LTE_FilterCoefficient_fc2: return 2; + case LTE_FilterCoefficient_fc3: return 3; + case LTE_FilterCoefficient_fc4: return 4; + case LTE_FilterCoefficient_fc5: return 5; + case LTE_FilterCoefficient_fc6: return 6; + case LTE_FilterCoefficient_fc7: return 7; + case LTE_FilterCoefficient_fc8: return 8; + case LTE_FilterCoefficient_fc9: return 9; + case LTE_FilterCoefficient_fc11: return 11; + case LTE_FilterCoefficient_fc13: return 13; + case LTE_FilterCoefficient_fc15: return 15; + case LTE_FilterCoefficient_fc17: return 17; + case LTE_FilterCoefficient_fc19: return 19; + case LTE_FilterCoefficient_spare1: return -1; /* spare means no coefficient */ + default: return -1; + } } /* Periodic event */ @@ -1644,7 +1761,25 @@ long flexran_get_rrc_a3_event_timeToTrigger(mid_t mod_id, rnti_t rnti) { if (!ue_context_p->ue_context.measurement_info) return -1; if (!ue_context_p->ue_context.measurement_info->events) return -1; if (!ue_context_p->ue_context.measurement_info->events->a3_event) return -1; - return ue_context_p->ue_context.measurement_info->events->a3_event->timeToTrigger; + switch (ue_context_p->ue_context.measurement_info->events->a3_event->timeToTrigger) { + case LTE_TimeToTrigger_ms0: return 0; + case LTE_TimeToTrigger_ms40: return 40; + case LTE_TimeToTrigger_ms64: return 64; + case LTE_TimeToTrigger_ms80: return 80; + case LTE_TimeToTrigger_ms100: return 100; + case LTE_TimeToTrigger_ms128: return 128; + case LTE_TimeToTrigger_ms160: return 160; + case LTE_TimeToTrigger_ms256: return 256; + case LTE_TimeToTrigger_ms320: return 320; + case LTE_TimeToTrigger_ms480: return 480; + case LTE_TimeToTrigger_ms512: return 512; + case LTE_TimeToTrigger_ms640: return 640; + case LTE_TimeToTrigger_ms1024: return 1024; + case LTE_TimeToTrigger_ms1280: return 1280; + case LTE_TimeToTrigger_ms2560: return 2560; + case LTE_TimeToTrigger_ms5120: return 5120; + default: return -1; + } } long flexran_get_rrc_a3_event_maxReportCells(mid_t mod_id, rnti_t rnti) { @@ -1677,6 +1812,259 @@ int flexran_get_rrc_a3_event_reportOnLeave(mid_t mod_id, rnti_t rnti) { return ue_context_p->ue_context.measurement_info->events->a3_event->reportOnLeave; } +/* RRC Setters */ + +/* Measurement offsets */ + +int flexran_set_rrc_ofp(mid_t mod_id, rnti_t rnti, long offsetFreq) { + if (!rrc_is_present(mod_id)) return -1; + struct rrc_eNB_ue_context_s* ue_context_p = rrc_eNB_get_ue_context(RC.rrc[mod_id], rnti); + if (!ue_context_p) return -1; + if (!ue_context_p->ue_context.measurement_info) return -1; + ue_context_p->ue_context.measurement_info->offsetFreq = offsetFreq; + return 0; +} + +int flexran_set_rrc_ofn(mid_t mod_id, rnti_t rnti, long offsetFreq) { + if (!rrc_is_present(mod_id)) return -1; + struct rrc_eNB_ue_context_s* ue_context_p = rrc_eNB_get_ue_context(RC.rrc[mod_id], rnti); + if (!ue_context_p) return -1; + if (!ue_context_p->ue_context.measurement_info) return -1; + ue_context_p->ue_context.measurement_info->offsetFreq = offsetFreq; + return 0; +} + +int flexran_set_rrc_ocp(mid_t mod_id, rnti_t rnti, long cellIndividualOffset) { + if (!rrc_is_present(mod_id)) return -1; + struct rrc_eNB_ue_context_s* ue_context_p = rrc_eNB_get_ue_context(RC.rrc[mod_id], rnti); + if (!ue_context_p) return -1; + if (!ue_context_p->ue_context.measurement_info) return -1; + LTE_Q_OffsetRange_t *cio = &ue_context_p->ue_context.measurement_info->cellIndividualOffset[0]; + switch (cellIndividualOffset) { + case -24: *cio = LTE_Q_OffsetRange_dB_24; break; + case -22: *cio = LTE_Q_OffsetRange_dB_22; break; + case -20: *cio = LTE_Q_OffsetRange_dB_20; break; + case -18: *cio = LTE_Q_OffsetRange_dB_18; break; + case -16: *cio = LTE_Q_OffsetRange_dB_16; break; + case -14: *cio = LTE_Q_OffsetRange_dB_14; break; + case -12: *cio = LTE_Q_OffsetRange_dB_12; break; + case -10: *cio = LTE_Q_OffsetRange_dB_10; break; + case -8: *cio = LTE_Q_OffsetRange_dB_8; break; + case -6: *cio = LTE_Q_OffsetRange_dB_6; break; + case -5: *cio = LTE_Q_OffsetRange_dB_5; break; + case -4: *cio = LTE_Q_OffsetRange_dB_4; break; + case -3: *cio = LTE_Q_OffsetRange_dB_3; break; + case -2: *cio = LTE_Q_OffsetRange_dB_2; break; + case -1: *cio = LTE_Q_OffsetRange_dB_1; break; + case 0: *cio = LTE_Q_OffsetRange_dB0; break; + case 1: *cio = LTE_Q_OffsetRange_dB1; break; + case 2: *cio = LTE_Q_OffsetRange_dB2; break; + case 3: *cio = LTE_Q_OffsetRange_dB3; break; + case 4: *cio = LTE_Q_OffsetRange_dB4; break; + case 5: *cio = LTE_Q_OffsetRange_dB5; break; + case 6: *cio = LTE_Q_OffsetRange_dB6; break; + case 8: *cio = LTE_Q_OffsetRange_dB8; break; + case 10: *cio = LTE_Q_OffsetRange_dB10; break; + case 12: *cio = LTE_Q_OffsetRange_dB12; break; + case 14: *cio = LTE_Q_OffsetRange_dB14; break; + case 16: *cio = LTE_Q_OffsetRange_dB16; break; + case 18: *cio = LTE_Q_OffsetRange_dB18; break; + case 20: *cio = LTE_Q_OffsetRange_dB20; break; + case 22: *cio = LTE_Q_OffsetRange_dB22; break; + case 24: *cio = LTE_Q_OffsetRange_dB24; break; + default: return -1; + } + return 0; +} + +int flexran_set_rrc_ocn(mid_t mod_id, rnti_t rnti, long cell_id, long cellIndividualOffset) { + if (!rrc_is_present(mod_id)) return -1; + struct rrc_eNB_ue_context_s* ue_context_p = rrc_eNB_get_ue_context(RC.rrc[mod_id], rnti); + if (!ue_context_p) return -1; + if (!ue_context_p->ue_context.measurement_info) return -1; + LTE_Q_OffsetRange_t *cio = &ue_context_p->ue_context.measurement_info->cellIndividualOffset[cell_id+1]; + switch (cellIndividualOffset) { + case -24: *cio = LTE_Q_OffsetRange_dB_24; break; + case -22: *cio = LTE_Q_OffsetRange_dB_22; break; + case -20: *cio = LTE_Q_OffsetRange_dB_20; break; + case -18: *cio = LTE_Q_OffsetRange_dB_18; break; + case -16: *cio = LTE_Q_OffsetRange_dB_16; break; + case -14: *cio = LTE_Q_OffsetRange_dB_14; break; + case -12: *cio = LTE_Q_OffsetRange_dB_12; break; + case -10: *cio = LTE_Q_OffsetRange_dB_10; break; + case -8: *cio = LTE_Q_OffsetRange_dB_8; break; + case -6: *cio = LTE_Q_OffsetRange_dB_6; break; + case -5: *cio = LTE_Q_OffsetRange_dB_5; break; + case -4: *cio = LTE_Q_OffsetRange_dB_4; break; + case -3: *cio = LTE_Q_OffsetRange_dB_3; break; + case -2: *cio = LTE_Q_OffsetRange_dB_2; break; + case -1: *cio = LTE_Q_OffsetRange_dB_1; break; + case 0: *cio = LTE_Q_OffsetRange_dB0; break; + case 1: *cio = LTE_Q_OffsetRange_dB1; break; + case 2: *cio = LTE_Q_OffsetRange_dB2; break; + case 3: *cio = LTE_Q_OffsetRange_dB3; break; + case 4: *cio = LTE_Q_OffsetRange_dB4; break; + case 5: *cio = LTE_Q_OffsetRange_dB5; break; + case 6: *cio = LTE_Q_OffsetRange_dB6; break; + case 8: *cio = LTE_Q_OffsetRange_dB8; break; + case 10: *cio = LTE_Q_OffsetRange_dB10; break; + case 12: *cio = LTE_Q_OffsetRange_dB12; break; + case 14: *cio = LTE_Q_OffsetRange_dB14; break; + case 16: *cio = LTE_Q_OffsetRange_dB16; break; + case 18: *cio = LTE_Q_OffsetRange_dB18; break; + case 20: *cio = LTE_Q_OffsetRange_dB20; break; + case 22: *cio = LTE_Q_OffsetRange_dB22; break; + case 24: *cio = LTE_Q_OffsetRange_dB24; break; + default: return -1; + } + return 0; +} + +int flexran_set_filter_coeff_rsrp(mid_t mod_id, rnti_t rnti, long filterCoefficientRSRP) { + if (!rrc_is_present(mod_id)) return -1; + struct rrc_eNB_ue_context_s* ue_context_p = rrc_eNB_get_ue_context(RC.rrc[mod_id], rnti); + if (!ue_context_p) return -1; + if (!ue_context_p->ue_context.measurement_info) return -1; + LTE_FilterCoefficient_t *fc = &ue_context_p->ue_context.measurement_info->filterCoefficientRSRP; + switch (filterCoefficientRSRP) { + case 0: *fc = LTE_FilterCoefficient_fc0; break; + case 1: *fc = LTE_FilterCoefficient_fc1; break; + case 2: *fc = LTE_FilterCoefficient_fc2; break; + case 3: *fc = LTE_FilterCoefficient_fc3; break; + case 4: *fc = LTE_FilterCoefficient_fc4; break; + case 5: *fc = LTE_FilterCoefficient_fc5; break; + case 6: *fc = LTE_FilterCoefficient_fc6; break; + case 7: *fc = LTE_FilterCoefficient_fc7; break; + case 8: *fc = LTE_FilterCoefficient_fc8; break; + case 9: *fc = LTE_FilterCoefficient_fc9; break; + case 11: *fc = LTE_FilterCoefficient_fc11; break; + case 13: *fc = LTE_FilterCoefficient_fc13; break; + case 15: *fc = LTE_FilterCoefficient_fc15; break; + case 17: *fc = LTE_FilterCoefficient_fc17; break; + case 19: *fc = LTE_FilterCoefficient_fc19; break; + case -1: *fc = LTE_FilterCoefficient_spare1; break; + default: return -1; + } + return 0; +} + +int flexran_set_filter_coeff_rsrq(mid_t mod_id, rnti_t rnti, long filterCoefficientRSRQ) { + if (!rrc_is_present(mod_id)) return -1; + struct rrc_eNB_ue_context_s* ue_context_p = rrc_eNB_get_ue_context(RC.rrc[mod_id], rnti); + if (!ue_context_p) return -1; + if (!ue_context_p->ue_context.measurement_info) return -1; + LTE_FilterCoefficient_t *fc = &ue_context_p->ue_context.measurement_info->filterCoefficientRSRQ; + switch (filterCoefficientRSRQ) { + case 0: *fc = LTE_FilterCoefficient_fc0; break; + case 1: *fc = LTE_FilterCoefficient_fc1; break; + case 2: *fc = LTE_FilterCoefficient_fc2; break; + case 3: *fc = LTE_FilterCoefficient_fc3; break; + case 4: *fc = LTE_FilterCoefficient_fc4; break; + case 5: *fc = LTE_FilterCoefficient_fc5; break; + case 6: *fc = LTE_FilterCoefficient_fc6; break; + case 7: *fc = LTE_FilterCoefficient_fc7; break; + case 8: *fc = LTE_FilterCoefficient_fc8; break; + case 9: *fc = LTE_FilterCoefficient_fc9; break; + case 11: *fc = LTE_FilterCoefficient_fc11; break; + case 13: *fc = LTE_FilterCoefficient_fc13; break; + case 15: *fc = LTE_FilterCoefficient_fc15; break; + case 17: *fc = LTE_FilterCoefficient_fc17; break; + case 19: *fc = LTE_FilterCoefficient_fc19; break; + case -1: *fc = LTE_FilterCoefficient_spare1; break; + default: return -1; + } + return 0; +} + +/* Periodic event */ + +int flexran_set_rrc_per_event_maxReportCells(mid_t mod_id, rnti_t rnti, long maxReportCells) { + if (!rrc_is_present(mod_id)) return -1; + struct rrc_eNB_ue_context_s* ue_context_p = rrc_eNB_get_ue_context(RC.rrc[mod_id], rnti); + if (!ue_context_p) return -1; + if (!ue_context_p->ue_context.measurement_info) return -1; + if (!ue_context_p->ue_context.measurement_info->events) return -1; + if (!ue_context_p->ue_context.measurement_info->events->per_event) return -1; + ue_context_p->ue_context.measurement_info->events->per_event->maxReportCells = maxReportCells; + return 0; +} + +/* A3 event */ + +int flexran_set_rrc_a3_event_hysteresis(mid_t mod_id, rnti_t rnti, long hysteresis) { + if (!rrc_is_present(mod_id)) return -1; + struct rrc_eNB_ue_context_s* ue_context_p = rrc_eNB_get_ue_context(RC.rrc[mod_id], rnti); + if (!ue_context_p) return -1; + if (!ue_context_p->ue_context.measurement_info) return -1; + if (!ue_context_p->ue_context.measurement_info->events) return -1; + if (!ue_context_p->ue_context.measurement_info->events->a3_event) return -1; + ue_context_p->ue_context.measurement_info->events->a3_event->hysteresis = hysteresis; + return 0; +} + +int flexran_set_rrc_a3_event_timeToTrigger(mid_t mod_id, rnti_t rnti, long timeToTrigger) { + if (!rrc_is_present(mod_id)) return -1; + struct rrc_eNB_ue_context_s* ue_context_p = rrc_eNB_get_ue_context(RC.rrc[mod_id], rnti); + if (!ue_context_p) return -1; + if (!ue_context_p->ue_context.measurement_info) return -1; + if (!ue_context_p->ue_context.measurement_info->events) return -1; + if (!ue_context_p->ue_context.measurement_info->events->a3_event) return -1; + LTE_TimeToTrigger_t *ttt = &ue_context_p->ue_context.measurement_info->events->a3_event->timeToTrigger; + switch (timeToTrigger) { + case 0: *ttt = LTE_TimeToTrigger_ms0; break; + case 40: *ttt = LTE_TimeToTrigger_ms40; break; + case 64: *ttt = LTE_TimeToTrigger_ms64; break; + case 80: *ttt = LTE_TimeToTrigger_ms80; break; + case 100: *ttt = LTE_TimeToTrigger_ms100; break; + case 128: *ttt = LTE_TimeToTrigger_ms128; break; + case 160: *ttt = LTE_TimeToTrigger_ms160; break; + case 256: *ttt = LTE_TimeToTrigger_ms256; break; + case 320: *ttt = LTE_TimeToTrigger_ms320; break; + case 480: *ttt = LTE_TimeToTrigger_ms480; break; + case 512: *ttt = LTE_TimeToTrigger_ms512; break; + case 640: *ttt = LTE_TimeToTrigger_ms640; break; + case 1024: *ttt = LTE_TimeToTrigger_ms1024; break; + case 1280: *ttt = LTE_TimeToTrigger_ms1280; break; + case 2560: *ttt = LTE_TimeToTrigger_ms2560; break; + case 5120: *ttt = LTE_TimeToTrigger_ms5120; break; + default: return -1; + } + return 0; +} + +int flexran_set_rrc_a3_event_maxReportCells(mid_t mod_id, rnti_t rnti, long maxReportCells) { + if (!rrc_is_present(mod_id)) return -1; + struct rrc_eNB_ue_context_s* ue_context_p = rrc_eNB_get_ue_context(RC.rrc[mod_id], rnti); + if (!ue_context_p) return -1; + if (!ue_context_p->ue_context.measurement_info) return -1; + if (!ue_context_p->ue_context.measurement_info->events) return -1; + if (!ue_context_p->ue_context.measurement_info->events->a3_event) return -1; + ue_context_p->ue_context.measurement_info->events->a3_event->maxReportCells = maxReportCells; + return 0; +} + +int flexran_set_rrc_a3_event_a3_offset(mid_t mod_id, rnti_t rnti, long a3_offset) { + if (!rrc_is_present(mod_id)) return -1; + struct rrc_eNB_ue_context_s* ue_context_p = rrc_eNB_get_ue_context(RC.rrc[mod_id], rnti); + if (!ue_context_p) return -1; + if (!ue_context_p->ue_context.measurement_info) return -1; + if (!ue_context_p->ue_context.measurement_info->events) return -1; + if (!ue_context_p->ue_context.measurement_info->events->a3_event) return -1; + ue_context_p->ue_context.measurement_info->events->a3_event->a3_offset = a3_offset; + return 0; +} + +int flexran_set_rrc_a3_event_reportOnLeave(mid_t mod_id, rnti_t rnti, int reportOnLeave) { + if (!rrc_is_present(mod_id)) return -1; + struct rrc_eNB_ue_context_s* ue_context_p = rrc_eNB_get_ue_context(RC.rrc[mod_id], rnti); + if (!ue_context_p) return -1; + if (!ue_context_p->ue_context.measurement_info) return -1; + if (!ue_context_p->ue_context.measurement_info->events) return -1; + if (!ue_context_p->ue_context.measurement_info->events->a3_event) return -1; + ue_context_p->ue_context.measurement_info->events->a3_event->reportOnLeave = reportOnLeave; + return 0; +} + uint8_t flexran_get_rrc_num_plmn_ids(mid_t mod_id) { if (!rrc_is_present(mod_id)) return 0; return RC.rrc[mod_id]->configuration.num_plmn; diff --git a/openair2/ENB_APP/flexran_agent_ran_api.h b/openair2/ENB_APP/flexran_agent_ran_api.h index 6efa7986dd..aabd327638 100644 --- a/openair2/ENB_APP/flexran_agent_ran_api.h +++ b/openair2/ENB_APP/flexran_agent_ran_api.h @@ -498,6 +498,9 @@ uint32_t flexran_get_pdcp_rx_aiat_w(mid_t mod_id, uint16_t uid, lcid_t lcid); uint32_t flexran_get_pdcp_rx_oo(mid_t mod_id, uint16_t uid, lcid_t lcid); /*********************RRC**********************/ +/* Call RRC Reconfiguration wrapper function */ +int flexran_call_rrc_reconfiguration (mid_t mod_id, rnti_t rnti); + /*Get primary cell measuremeant id flexRAN*/ LTE_MeasId_t flexran_get_rrc_pcell_measid(mid_t mod_id, rnti_t rnti); @@ -576,6 +579,42 @@ long flexran_get_filter_coeff_rsrp(mid_t mod_id, rnti_t rnti); /* Get filter coefficient for rsrq */ long flexran_get_filter_coeff_rsrq(mid_t mod_id, rnti_t rnti); +/* Set ofp offset */ +int flexran_set_rrc_ofp(mid_t mod_id, rnti_t rnti, long offsetFreq); + +/* Set ofn offset */ +int flexran_set_rrc_ofn(mid_t mod_id, rnti_t rnti, long offsetFreq); + +/* Set ocp offset */ +int flexran_set_rrc_ocp(mid_t mod_id, rnti_t rnti, long cellIndividualOffset); + +/* Set ocn offset */ +int flexran_set_rrc_ocn(mid_t mod_id, rnti_t rnti, long cell_id, long cellIndividualOffset); + +/* Set Periodic Event max reported cells */ +int flexran_set_rrc_per_event_maxReportCells(mid_t mod_id, rnti_t rnti, long maxReportCells); + +/* Set A3 Event hysteresis */ +int flexran_set_rrc_a3_event_hysteresis(mid_t mod_id, rnti_t rnti, long hysteresis); + +/* Set A3 Event time to trigger */ +int flexran_set_rrc_a3_event_timeToTrigger(mid_t mod_id, rnti_t rnti, long timeToTrigger); + +/* Set A3 Event max reported cells */ +int flexran_set_rrc_a3_event_maxReportCells(mid_t mod_id, rnti_t rnti, long maxReportCells); + +/* Set A3 Event a3 offset */ +int flexran_set_rrc_a3_event_a3_offset(mid_t mod_id, rnti_t rnti, long a3_offset); + +/* Set A3 Event report on leave */ +int flexran_set_rrc_a3_event_reportOnLeave(mid_t mod_id, rnti_t rnti, int reportOnLeave); + +/* Set filter coefficient for rsrp */ +int flexran_set_filter_coeff_rsrp(mid_t mod_id, rnti_t rnti, long filterCoefficientRSRP); + +/* Set filter coefficient for rsrq */ +int flexran_set_filter_coeff_rsrq(mid_t mod_id, rnti_t rnti, long filterCoefficientRSRQ); + /* Get number of PLMNs that is broadcasted in SIB1 */ uint8_t flexran_get_rrc_num_plmn_ids(mid_t mod_id); diff --git a/openair2/RRC/LTE/rrc_eNB.c b/openair2/RRC/LTE/rrc_eNB.c index 814f3aa178..40e82bb74e 100644 --- a/openair2/RRC/LTE/rrc_eNB.c +++ b/openair2/RRC/LTE/rrc_eNB.c @@ -3617,16 +3617,15 @@ void rrc_eNB_generate_defaultRRCConnectionReconfiguration(const protocol_ctxt_t void flexran_rrc_eNB_generate_defaultRRCConnectionReconfiguration(const protocol_ctxt_t *const ctxt_pP, rrc_eNB_ue_context_t *const ue_context_pP, - const uint8_t ho_state, - agent_reconf_rrc *trig_param - ) + const uint8_t ho_state) //----------------------------------------------------------------------------- { - uint8_t buffer[RRC_BUF_SIZE]; - uint16_t size; - int i; - // configure SRB1/SRB2, PhysicalConfigDedicated, LTE_MAC_MainConfig for UE - eNB_RRC_INST *rrc_inst = RC.rrc[ctxt_pP->module_id]; + uint8_t buffer[RRC_BUF_SIZE]; + uint16_t size; + int i; + + /* Configure SRB1/SRB2, PhysicalConfigDedicated, LTE_MAC_MainConfig for UE */ + eNB_RRC_INST *rrc_inst = RC.rrc[ctxt_pP->module_id]; struct LTE_PhysicalConfigDedicated **physicalConfigDedicated = &ue_context_pP->ue_context.physicalConfigDedicated; struct LTE_SRB_ToAddMod *SRB2_config = NULL; struct LTE_SRB_ToAddMod__rlc_Config *SRB2_rlc_config = NULL; @@ -3634,7 +3633,7 @@ flexran_rrc_eNB_generate_defaultRRCConnectionReconfiguration(const protocol_ctxt struct LTE_LogicalChannelConfig__ul_SpecificParameters *SRB2_ul_SpecificParameters = NULL; LTE_SRB_ToAddModList_t *SRB_configList = ue_context_pP->ue_context.SRB_configList; - LTE_SRB_ToAddModList_t **SRB_configList2 = NULL; + LTE_SRB_ToAddModList_t **SRB_configList2 = NULL; struct LTE_DRB_ToAddMod *DRB_config = NULL; struct LTE_RLC_Config *DRB_rlc_config = NULL; struct LTE_PDCP_Config *DRB_pdcp_config = NULL; @@ -3644,22 +3643,24 @@ flexran_rrc_eNB_generate_defaultRRCConnectionReconfiguration(const protocol_ctxt struct LTE_LogicalChannelConfig__ul_SpecificParameters *DRB_ul_SpecificParameters = NULL; LTE_DRB_ToAddModList_t **DRB_configList = &ue_context_pP->ue_context.DRB_configList; - LTE_DRB_ToAddModList_t **DRB_configList2 = NULL; + LTE_DRB_ToAddModList_t **DRB_configList2 = NULL; LTE_MAC_MainConfig_t *mac_MainConfig = NULL; LTE_MeasObjectToAddModList_t *MeasObj_list = NULL; LTE_MeasObjectToAddMod_t *MeasObj = NULL; LTE_ReportConfigToAddModList_t *ReportConfig_list = NULL; - LTE_ReportConfigToAddMod_t *ReportConfig_per;//, *ReportConfig_A1, - // *ReportConfig_A2, *ReportConfig_A3, *ReportConfig_A4, *ReportConfig_A5; + LTE_ReportConfigToAddMod_t *ReportConfig_per, *ReportConfig_A1, + *ReportConfig_A2, *ReportConfig_A3, *ReportConfig_A4, *ReportConfig_A5; LTE_MeasIdToAddModList_t *MeasId_list = NULL; - LTE_MeasIdToAddMod_t *MeasId0; //, *MeasId1, *MeasId2, *MeasId3, *MeasId4, *MeasId5; -#if (LTE_RRC_VERSION >= MAKE_VERSION(10, 0, 0)) - long *sr_ProhibitTimer_r9 = NULL; - // uint8_t sCellIndexToAdd = rrc_find_free_SCell_index(enb_mod_idP, ue_mod_idP, 1); - //uint8_t sCellIndexToAdd = 0; + LTE_MeasIdToAddMod_t *MeasId0, *MeasId1, *MeasId2, *MeasId3, *MeasId4, *MeasId5; + +#if (LTE_RRC_VERSION >= MAKE_VERSION(9, 0, 0)) + long *sr_ProhibitTimer_r9 = NULL; #endif - long *logicalchannelgroup, *logicalchannelgroup_drb; - long *maxHARQ_Tx, *periodicBSR_Timer; + + long *logicalchannelgroup = NULL; + long *logicalchannelgroup_drb = NULL; + long *maxHARQ_Tx = NULL; + long *periodicBSR_Timer = NULL; LTE_RSRP_Range_t *rsrp = NULL; struct LTE_MeasConfig__speedStatePars *Sparams = NULL; LTE_QuantityConfig_t *quantityConfig = NULL; @@ -3667,13 +3668,16 @@ flexran_rrc_eNB_generate_defaultRRCConnectionReconfiguration(const protocol_ctxt LTE_CellsToAddModList_t *CellsToAddModList = NULL; struct LTE_RRCConnectionReconfiguration_r8_IEs__dedicatedInfoNASList *dedicatedInfoNASList = NULL; LTE_DedicatedInfoNAS_t *dedicatedInfoNas = NULL; - /* for no gcc warnings */ - (void)dedicatedInfoNas; + + /* For no gcc warnings */ + (void) dedicatedInfoNas; LTE_C_RNTI_t *cba_RNTI = NULL; int measurements_enabled; uint8_t xid = rrc_eNB_get_next_transaction_identifier(ctxt_pP->module_id); //Transaction_id, -#ifdef CBA - //struct PUSCH_CBAConfigDedicated_vlola *pusch_CBAConfigDedicated_vlola; + uint8_t cc_id = ue_context_pP->ue_context.primaryCC_id; + LTE_UE_EUTRA_Capability_t *UEcap = ue_context_pP->ue_context.UE_Capability; + +#ifdef CBA // Contention Based Access uint8_t *cba_RNTI_buf; cba_RNTI = CALLOC(1, sizeof(LTE_C_RNTI_t)); cba_RNTI_buf = CALLOC(1, 2 * sizeof(uint8_t)); @@ -3681,27 +3685,33 @@ flexran_rrc_eNB_generate_defaultRRCConnectionReconfiguration(const protocol_ctxt cba_RNTI->size = 2; cba_RNTI->bits_unused = 0; - // associate UEs to the CBa groups as a function of their UE id + /* Associate UEs to the CBA groups as a function of their UE id */ if (rrc_inst->num_active_cba_groups) { cba_RNTI->buf[0] = rrc_inst->cba_rnti[ue_mod_idP % rrc_inst->num_active_cba_groups] & 0xff; cba_RNTI->buf[1] = 0xff; - LOG_D(RRC, - "[eNB %d] Frame %d: cba_RNTI = %x in group %d is attribued to UE %d\n", - enb_mod_idP, frameP, + LOG_D(RRC, "[eNB %d] Frame %d: cba_RNTI = %x in group %d is attribued to UE %d\n", + enb_mod_idP, + frameP, rrc_inst->cba_rnti[ue_mod_idP % rrc_inst->num_active_cba_groups], ue_mod_idP % rrc_inst->num_active_cba_groups, ue_mod_idP); } else { cba_RNTI->buf[0] = 0x0; cba_RNTI->buf[1] = 0x0; - LOG_D(RRC, "[eNB %d] Frame %d: no cba_RNTI is configured for UE %d\n", enb_mod_idP, frameP, ue_mod_idP); + LOG_D(RRC, "[eNB %d] Frame %d: no cba_RNTI is configured for UE %d\n", + enb_mod_idP, + frameP, + ue_mod_idP); } - #endif - T(T_ENB_RRC_CONNECTION_RECONFIGURATION, T_INT(ctxt_pP->module_id), T_INT(ctxt_pP->frame), - T_INT(ctxt_pP->subframe), T_INT(ctxt_pP->rnti)); - // Configure SRB2 - /// SRB2 - SRB_configList2=&ue_context_pP->ue_context.SRB_configList2[xid]; + + T(T_ENB_RRC_CONNECTION_RECONFIGURATION, + T_INT(ctxt_pP->module_id), + T_INT(ctxt_pP->frame), + T_INT(ctxt_pP->subframe), + T_INT(ctxt_pP->rnti)); + + /* Configure SRB2 */ + SRB_configList2 = &(ue_context_pP->ue_context.SRB_configList2[xid]); if (*SRB_configList2) { free(*SRB_configList2); @@ -3726,22 +3736,19 @@ flexran_rrc_eNB_generate_defaultRRCConnectionReconfiguration(const protocol_ctxt SRB2_lchan_config->present = LTE_SRB_ToAddMod__logicalChannelConfig_PR_explicitValue; SRB2_ul_SpecificParameters = CALLOC(1, sizeof(*SRB2_ul_SpecificParameters)); SRB2_ul_SpecificParameters->priority = 3; // let some priority for SRB1 and dedicated DRBs - SRB2_ul_SpecificParameters->prioritisedBitRate = - LTE_LogicalChannelConfig__ul_SpecificParameters__prioritisedBitRate_infinity; - SRB2_ul_SpecificParameters->bucketSizeDuration = - LTE_LogicalChannelConfig__ul_SpecificParameters__bucketSizeDuration_ms50; - // LCG for CCCH and DCCH is 0 as defined in 36331 + SRB2_ul_SpecificParameters->prioritisedBitRate = LTE_LogicalChannelConfig__ul_SpecificParameters__prioritisedBitRate_infinity; + SRB2_ul_SpecificParameters->bucketSizeDuration = LTE_LogicalChannelConfig__ul_SpecificParameters__bucketSizeDuration_ms50; + + /* LCG for CCCH and DCCH is 0 as defined in 36331 */ logicalchannelgroup = CALLOC(1, sizeof(long)); *logicalchannelgroup = 0; SRB2_ul_SpecificParameters->logicalChannelGroup = logicalchannelgroup; SRB2_lchan_config->choice.explicitValue.ul_SpecificParameters = SRB2_ul_SpecificParameters; - // this list has the configuration for SRB1 and SRB2 - ASN_SEQUENCE_ADD(&SRB_configList->list, SRB2_config); - // this list has only the configuration for SRB2 - ASN_SEQUENCE_ADD(&(*SRB_configList2)->list, SRB2_config); - // Configure DRB - //*DRB_configList = CALLOC(1, sizeof(*DRB_configList)); + ASN_SEQUENCE_ADD(&SRB_configList->list, SRB2_config); // this list has the configuration for SRB1 and SRB2 + ASN_SEQUENCE_ADD(&(*SRB_configList2)->list, SRB2_config); // this list has only the configuration for SRB2 + + /* Configure DRB */ // list for all the configured DRB if (*DRB_configList) { free(*DRB_configList); @@ -3749,8 +3756,8 @@ flexran_rrc_eNB_generate_defaultRRCConnectionReconfiguration(const protocol_ctxt *DRB_configList = CALLOC(1, sizeof(**DRB_configList)); memset(*DRB_configList, 0, sizeof(**DRB_configList)); - // list for the configured DRB for a this xid - DRB_configList2=&ue_context_pP->ue_context.DRB_configList2[xid]; + + DRB_configList2=&ue_context_pP->ue_context.DRB_configList2[xid]; // list for the configured DRB for a this xid if (*DRB_configList2) { free(*DRB_configList2); @@ -3758,17 +3765,17 @@ flexran_rrc_eNB_generate_defaultRRCConnectionReconfiguration(const protocol_ctxt *DRB_configList2 = CALLOC(1, sizeof(**DRB_configList2)); memset(*DRB_configList2, 0, sizeof(**DRB_configList2)); - /// DRB + DRB_config = CALLOC(1, sizeof(*DRB_config)); DRB_config->eps_BearerIdentity = CALLOC(1, sizeof(long)); *(DRB_config->eps_BearerIdentity) = 5L; // LW set to first value, allowed value 5..15, value : x+4 - // DRB_config->drb_Identity = (LTE_DRB_Identity_t) 1; //allowed values 1..32 // NN: this is the 1st DRB for this ue, so set it to 1 DRB_config->drb_Identity = (LTE_DRB_Identity_t) 1; // (ue_mod_idP+1); //allowed values 1..32, value: x DRB_config->logicalChannelIdentity = CALLOC(1, sizeof(long)); *(DRB_config->logicalChannelIdentity) = (long)3; // value : x+2 DRB_rlc_config = CALLOC(1, sizeof(*DRB_rlc_config)); DRB_config->rlc_Config = DRB_rlc_config; + #ifdef RRC_DEFAULT_RAB_IS_AM DRB_rlc_config->present = LTE_RLC_Config_PR_am; DRB_rlc_config->choice.am.ul_AM_RLC.t_PollRetransmit = LTE_T_PollRetransmit_ms50; @@ -3781,21 +3788,25 @@ flexran_rrc_eNB_generate_defaultRRCConnectionReconfiguration(const protocol_ctxt DRB_rlc_config->present = LTE_RLC_Config_PR_um_Bi_Directional; DRB_rlc_config->choice.um_Bi_Directional.ul_UM_RLC.sn_FieldLength = LTE_SN_FieldLength_size10; DRB_rlc_config->choice.um_Bi_Directional.dl_UM_RLC.sn_FieldLength = LTE_SN_FieldLength_size10; + #ifdef CBA - DRB_rlc_config->choice.um_Bi_Directional.dl_UM_RLC.t_Reordering = LTE_T_Reordering_ms5;//T_Reordering_ms25; + DRB_rlc_config->choice.um_Bi_Directional.dl_UM_RLC.t_Reordering = LTE_T_Reordering_ms5; //T_Reordering_ms25; #else DRB_rlc_config->choice.um_Bi_Directional.dl_UM_RLC.t_Reordering = LTE_T_Reordering_ms35; #endif + #endif + DRB_pdcp_config = CALLOC(1, sizeof(*DRB_pdcp_config)); DRB_config->pdcp_Config = DRB_pdcp_config; DRB_pdcp_config->discardTimer = CALLOC(1, sizeof(long)); *DRB_pdcp_config->discardTimer = LTE_PDCP_Config__discardTimer_infinity; DRB_pdcp_config->rlc_AM = NULL; DRB_pdcp_config->rlc_UM = NULL; - /* avoid gcc warnings */ + /* Avoid gcc warnings */ (void)PDCP_rlc_AM; (void)PDCP_rlc_UM; + #ifdef RRC_DEFAULT_RAB_IS_AM // EXMIMO_IOT PDCP_rlc_AM = CALLOC(1, sizeof(*PDCP_rlc_AM)); DRB_pdcp_config->rlc_AM = PDCP_rlc_AM; @@ -3805,52 +3816,97 @@ flexran_rrc_eNB_generate_defaultRRCConnectionReconfiguration(const protocol_ctxt DRB_pdcp_config->rlc_UM = PDCP_rlc_UM; PDCP_rlc_UM->pdcp_SN_Size = LTE_PDCP_Config__rlc_UM__pdcp_SN_Size_len12bits; #endif + DRB_pdcp_config->headerCompression.present = LTE_PDCP_Config__headerCompression_PR_notUsed; DRB_lchan_config = CALLOC(1, sizeof(*DRB_lchan_config)); DRB_config->logicalChannelConfig = DRB_lchan_config; DRB_ul_SpecificParameters = CALLOC(1, sizeof(*DRB_ul_SpecificParameters)); DRB_lchan_config->ul_SpecificParameters = DRB_ul_SpecificParameters; - DRB_ul_SpecificParameters->priority = 12; // lower priority than srb1, srb2 and other dedicated bearer - DRB_ul_SpecificParameters->prioritisedBitRate = LTE_LogicalChannelConfig__ul_SpecificParameters__prioritisedBitRate_kBps8 ; - //LogicalChannelConfig__ul_SpecificParameters__prioritisedBitRate_infinity; - DRB_ul_SpecificParameters->bucketSizeDuration = - LTE_LogicalChannelConfig__ul_SpecificParameters__bucketSizeDuration_ms50; + DRB_ul_SpecificParameters->priority = 12; // lower priority than srb1, srb2 and other dedicated bearer + DRB_ul_SpecificParameters->prioritisedBitRate = LTE_LogicalChannelConfig__ul_SpecificParameters__prioritisedBitRate_kBps8; // LogicalChannelConfig__ul_SpecificParameters__prioritisedBitRate_infinity; + DRB_ul_SpecificParameters->bucketSizeDuration = LTE_LogicalChannelConfig__ul_SpecificParameters__bucketSizeDuration_ms50; // LCG for DTCH can take the value from 1 to 3 as defined in 36331: normally controlled by upper layers (like RRM) logicalchannelgroup_drb = CALLOC(1, sizeof(long)); *logicalchannelgroup_drb = 1; DRB_ul_SpecificParameters->logicalChannelGroup = logicalchannelgroup_drb; + ASN_SEQUENCE_ADD(&(*DRB_configList)->list, DRB_config); ASN_SEQUENCE_ADD(&(*DRB_configList2)->list, DRB_config); - //ue_context_pP->ue_context.DRB_configList2[0] = &(*DRB_configList); + + /* MAC Main Config */ + // The different parts of MAC main config are set below mac_MainConfig = CALLOC(1, sizeof(*mac_MainConfig)); - // ue_context_pP->ue_context.mac_MainConfig = LTE_MAC_MainConfig; + ue_context_pP->ue_context.mac_MainConfig = mac_MainConfig; mac_MainConfig->ul_SCH_Config = CALLOC(1, sizeof(*mac_MainConfig->ul_SCH_Config)); maxHARQ_Tx = CALLOC(1, sizeof(long)); *maxHARQ_Tx = LTE_MAC_MainConfig__ul_SCH_Config__maxHARQ_Tx_n5; mac_MainConfig->ul_SCH_Config->maxHARQ_Tx = maxHARQ_Tx; + + /* BSR reconfiguration */ periodicBSR_Timer = CALLOC(1, sizeof(long)); - *periodicBSR_Timer = LTE_PeriodicBSR_Timer_r12_sf64; + *periodicBSR_Timer = LTE_PeriodicBSR_Timer_r12_sf64; //LTE_PeriodicBSR_Timer_r12_infinity; // LTE_PeriodicBSR_Timer_r12_sf64; // LTE_PeriodicBSR_Timer_r12_sf20 mac_MainConfig->ul_SCH_Config->periodicBSR_Timer = periodicBSR_Timer; - mac_MainConfig->ul_SCH_Config->retxBSR_Timer = LTE_RetxBSR_Timer_r12_sf320; + mac_MainConfig->ul_SCH_Config->retxBSR_Timer = LTE_RetxBSR_Timer_r12_sf320; // LTE_RetxBSR_Timer_r12_sf320; // LTE_RetxBSR_Timer_r12_sf5120 mac_MainConfig->ul_SCH_Config->ttiBundling = 0; // FALSE mac_MainConfig->timeAlignmentTimerDedicated = LTE_TimeAlignmentTimer_infinity; - mac_MainConfig->drx_Config = NULL; + + /* PHR reconfiguration */ mac_MainConfig->phr_Config = CALLOC(1, sizeof(*mac_MainConfig->phr_Config)); mac_MainConfig->phr_Config->present = LTE_MAC_MainConfig__phr_Config_PR_setup; - mac_MainConfig->phr_Config->choice.setup.periodicPHR_Timer = LTE_MAC_MainConfig__phr_Config__setup__periodicPHR_Timer_sf20; // sf20 = 20 subframes - mac_MainConfig->phr_Config->choice.setup.prohibitPHR_Timer = LTE_MAC_MainConfig__phr_Config__setup__prohibitPHR_Timer_sf20; // sf20 = 20 subframes - mac_MainConfig->phr_Config->choice.setup.dl_PathlossChange = LTE_MAC_MainConfig__phr_Config__setup__dl_PathlossChange_dB1; // Value dB1 =1 dB, dB3 = 3 dB -#if (LTE_RRC_VERSION >= MAKE_VERSION(10, 0, 0)) + mac_MainConfig->phr_Config->choice.setup.periodicPHR_Timer = LTE_MAC_MainConfig__phr_Config__setup__periodicPHR_Timer_sf500; // sf20 = 20 subframes // LTE_MAC_MainConfig__phr_Config__setup__periodicPHR_Timer_infinity + mac_MainConfig->phr_Config->choice.setup.prohibitPHR_Timer = LTE_MAC_MainConfig__phr_Config__setup__prohibitPHR_Timer_sf200; // sf20 = 20 subframes // LTE_MAC_MainConfig__phr_Config__setup__prohibitPHR_Timer_sf1000 + mac_MainConfig->phr_Config->choice.setup.dl_PathlossChange = LTE_MAC_MainConfig__phr_Config__setup__dl_PathlossChange_dB3; // Value dB1 =1 dB, dB3 = 3 dB + + if (!NODE_IS_CU(RC.rrc[ctxt_pP->module_id]->node_type)) { + /* CDRX Configuration */ + // Need to check if UE is a BR UE + rnti_t rnti = ue_context_pP->ue_id_rnti; + module_id_t module_id = ctxt_pP->module_id; + int UE_id = find_UE_id(module_id, rnti); + eNB_MAC_INST *mac = RC.mac[module_id]; + UE_list_t *UE_list = &(mac->UE_list); + + if (UE_id != -1) { + if ((rrc_inst->carrier[cc_id].sib1->tdd_Config == NULL) && + (UE_list->UE_template[ue_context_pP->ue_context.primaryCC_id][UE_id].rach_resource_type == 0)) { + // CDRX can be only configured in case of FDD and non BR UE (09/04/19) + + LOG_D(RRC, "Processing the DRX configuration in RRC Connection Reconfiguration\n"); + + /* Process the IE drx_Config */ + if (cc_id < MAX_NUM_CCs) { + mac_MainConfig->drx_Config = do_DrxConfig(module_id, cc_id, &rrc_inst->configuration, UEcap); // drx_Config IE + } else { + LOG_E(RRC, "Invalid CC_id for DRX configuration\n"); + } + + /* Set timers and thresholds values in local MAC context of UE */ + eNB_Config_Local_DRX(module_id, ue_context_pP->ue_id_rnti, mac_MainConfig->drx_Config); + + LOG_D(RRC, "DRX configured in mac main config for RRC Connection Reconfiguration\n"); + + } else { // CDRX not implemented for TDD and LTE-M (09/04/19) + mac_MainConfig->drx_Config = NULL; + } + } else { // UE_id invalid + LOG_E(RRC, "Invalid UE_id found!\n"); + mac_MainConfig->drx_Config = NULL; + } + } else { // No CDRX with the CU/DU split in this version + LOG_E(RRC, "CU/DU split activated\n"); + mac_MainConfig->drx_Config = NULL; + } + +#if (LTE_RRC_VERSION >= MAKE_VERSION(9, 0, 0)) sr_ProhibitTimer_r9 = CALLOC(1, sizeof(long)); - *sr_ProhibitTimer_r9 = 0; // SR tx on PUCCH, Value in number of SR period(s). Value 0 = no timer for SR, Value 2= 2*SR + *sr_ProhibitTimer_r9 = 0; // SR tx on PUCCH, Value in number of SR period(s). Value 0 = no timer for SR, Value 2 = 2*SR mac_MainConfig->ext1 = CALLOC(1, sizeof(struct LTE_MAC_MainConfig__ext1)); mac_MainConfig->ext1->sr_ProhibitTimer_r9 = sr_ProhibitTimer_r9; - //sps_RA_ConfigList_rlola = NULL; #endif - //change the transmission mode for the primary component carrier - //TODO: add codebook subset restriction here - //TODO: change TM for secondary CC in SCelltoaddmodlist + // change the transmission mode for the primary component carrier + // TODO: add codebook subset restriction here + // TODO: change TM for secondary CC in SCelltoaddmodlist if (*physicalConfigDedicated) { if ((*physicalConfigDedicated)->antennaInfo) { (*physicalConfigDedicated)->antennaInfo->choice.explicitValue.transmissionMode = rrc_inst->configuration.radioresourceconfig[0].ue_TransmissionMode; @@ -3897,19 +3953,20 @@ flexran_rrc_eNB_generate_defaultRRCConnectionReconfiguration(const protocol_ctxt LOG_E(RRC,"antenna_info not present in physical_config_dedicated. Not reconfiguring!\n"); } - /* CSI Configuration through RRC */ + /* CSI RRC Reconfiguration */ if ((*physicalConfigDedicated)->cqi_ReportConfig != NULL) { if ((rrc_inst->configuration.radioresourceconfig[0].ue_TransmissionMode == LTE_AntennaInfoDedicated__transmissionMode_tm4) || (rrc_inst->configuration.radioresourceconfig[0].ue_TransmissionMode == LTE_AntennaInfoDedicated__transmissionMode_tm5) || (rrc_inst->configuration.radioresourceconfig[0].ue_TransmissionMode == LTE_AntennaInfoDedicated__transmissionMode_tm6)) { - //feedback mode needs to be set as well - //TODO: I think this is taken into account in the PHY automatically based on the transmission mode variable - LOG_I(RRC, "Setting cqi aperiodic reporting mode to rm31 (hardcoded)\n"); + + // feedback mode needs to be set as well + // TODO: I think this is taken into account in the PHY automatically based on the transmission mode variable + LOG_I(RRC, "Setting cqi reporting mode to rm31 (hardcoded)\n"); #if (LTE_RRC_VERSION >= MAKE_VERSION(10, 0, 0)) - *((*physicalConfigDedicated)->cqi_ReportConfig->cqi_ReportModeAperiodic)=LTE_CQI_ReportModeAperiodic_rm31; + *((*physicalConfigDedicated)->cqi_ReportConfig->cqi_ReportModeAperiodic) = LTE_CQI_ReportModeAperiodic_rm31; // HLC CQI, single PMI #else - *((*physicalConfigDedicated)->cqi_ReportConfig->cqi_ReportModeAperiodic)=LTE_CQI_ReportConfig__cqi_ReportModeAperiodic_rm31; // HLC CQI, no PMI + *((*physicalConfigDedicated)->cqi_ReportConfig->cqi_ReportModeAperiodic) = LTE_CQI_ReportConfig__cqi_ReportModeAperiodic_rm31; // HLC CQI, single PMI #endif } } else { @@ -3927,9 +3984,33 @@ flexran_rrc_eNB_generate_defaultRRCConnectionReconfiguration(const protocol_ctxt MeasId0->measObjectId = 1; MeasId0->reportConfigId = 1; ASN_SEQUENCE_ADD(&MeasId_list->list, MeasId0); - /* - * Add one EUTRA Measurement Object - */ + MeasId1 = CALLOC(1, sizeof(*MeasId1)); + MeasId1->measId = 2; + MeasId1->measObjectId = 1; + MeasId1->reportConfigId = 2; + ASN_SEQUENCE_ADD(&MeasId_list->list, MeasId1); + MeasId2 = CALLOC(1, sizeof(*MeasId2)); + MeasId2->measId = 3; + MeasId2->measObjectId = 1; + MeasId2->reportConfigId = 3; + ASN_SEQUENCE_ADD(&MeasId_list->list, MeasId2); + MeasId3 = CALLOC(1, sizeof(*MeasId3)); + MeasId3->measId = 4; + MeasId3->measObjectId = 1; + MeasId3->reportConfigId = 4; + ASN_SEQUENCE_ADD(&MeasId_list->list, MeasId3); + MeasId4 = CALLOC(1, sizeof(*MeasId4)); + MeasId4->measId = 5; + MeasId4->measObjectId = 1; + MeasId4->reportConfigId = 5; + ASN_SEQUENCE_ADD(&MeasId_list->list, MeasId4); + MeasId5 = CALLOC(1, sizeof(*MeasId5)); + MeasId5->measId = 6; + MeasId5->measObjectId = 1; + MeasId5->reportConfigId = 6; + ASN_SEQUENCE_ADD(&MeasId_list->list, MeasId5); + // LTE_RRCConnectionReconfiguration->criticalExtensions.choice.c1.choice.rrcConnectionReconfiguration_r8.measConfig->measIdToAddModList = MeasId_list; + // Add one EUTRA Measurement Object MeasObj_list = CALLOC(1, sizeof(*MeasObj_list)); memset((void *)MeasObj_list, 0, sizeof(*MeasObj_list)); // Configure MeasObject @@ -3937,64 +4018,161 @@ flexran_rrc_eNB_generate_defaultRRCConnectionReconfiguration(const protocol_ctxt memset((void *)MeasObj, 0, sizeof(*MeasObj)); MeasObj->measObjectId = 1; MeasObj->measObject.present = LTE_MeasObjectToAddMod__measObject_PR_measObjectEUTRA; - MeasObj->measObject.choice.measObjectEUTRA.carrierFreq = 3350; //band 7, 2.68GHz - //MeasObj->measObject.choice.measObjectEUTRA.carrierFreq = 36090; //band 33, 1.909GHz + MeasObj->measObject.choice.measObjectEUTRA.carrierFreq = + to_earfcn_DL(RC.rrc[ctxt_pP->module_id]->configuration.eutra_band[0], + RC.rrc[ctxt_pP->module_id]->configuration.downlink_frequency[0], + RC.rrc[ctxt_pP->module_id]->configuration.N_RB_DL[0]); MeasObj->measObject.choice.measObjectEUTRA.allowedMeasBandwidth = LTE_AllowedMeasBandwidth_mbw25; MeasObj->measObject.choice.measObjectEUTRA.presenceAntennaPort1 = 1; MeasObj->measObject.choice.measObjectEUTRA.neighCellConfig.buf = CALLOC(1, sizeof(uint8_t)); MeasObj->measObject.choice.measObjectEUTRA.neighCellConfig.buf[0] = 0; MeasObj->measObject.choice.measObjectEUTRA.neighCellConfig.size = 1; MeasObj->measObject.choice.measObjectEUTRA.neighCellConfig.bits_unused = 6; - MeasObj->measObject.choice.measObjectEUTRA.offsetFreq = NULL; // Default is 15 or 0dB - MeasObj->measObject.choice.measObjectEUTRA.cellsToAddModList = - (LTE_CellsToAddModList_t *) CALLOC(1, sizeof(*CellsToAddModList)); - CellsToAddModList = MeasObj->measObject.choice.measObjectEUTRA.cellsToAddModList; + *(MeasObj->measObject.choice.measObjectEUTRA.offsetFreq) = ue_context_pP->ue_context.measurement_info->offsetFreq; // Default is 15 or 0dB - // Add adjacent cell lists (6 per eNB) - for (i = 0; i < 6; i++) { - CellToAdd = (LTE_CellsToAddMod_t *) CALLOC(1, sizeof(*CellToAdd)); - CellToAdd->cellIndex = i + 1; - CellToAdd->physCellId = get_adjacent_cell_id(ctxt_pP->module_id, i); - CellToAdd->cellIndividualOffset = LTE_Q_OffsetRange_dB0; - ASN_SEQUENCE_ADD(&CellsToAddModList->list, CellToAdd); + if (RC.rrc[ctxt_pP->module_id]->num_neigh_cells > 0) { + MeasObj->measObject.choice.measObjectEUTRA.cellsToAddModList = + (LTE_CellsToAddModList_t *) CALLOC(1, sizeof(*CellsToAddModList)); + CellsToAddModList = MeasObj->measObject.choice.measObjectEUTRA.cellsToAddModList; } + /* TODO: Extend to multiple carriers */ + // Add adjacent cell lists (max 6 per eNB) + for (i = 0; i < RC.rrc[ctxt_pP->module_id]->num_neigh_cells; i++) { + CellToAdd = (LTE_CellsToAddMod_t *) CALLOC(1, sizeof(*CellToAdd)); + CellToAdd->cellIndex = i + 1; + CellToAdd->physCellId = RC.rrc[ctxt_pP->module_id]->neigh_cells_id[i][0];//get_adjacent_cell_id(ctxt_pP->module_id, i); + CellToAdd->cellIndividualOffset = ue_context_pP->ue_context.measurement_info->cellIndividualOffset[i+1]; + ASN_SEQUENCE_ADD(&CellsToAddModList->list, CellToAdd); + } ASN_SEQUENCE_ADD(&MeasObj_list->list, MeasObj); // LTE_RRCConnectionReconfiguration->criticalExtensions.choice.c1.choice.rrcConnectionReconfiguration_r8.measConfig->measObjectToAddModList = MeasObj_list; // Report Configurations for periodical, A1-A5 events - - /* RRC Strategy Measurement */ - - if (strcmp("one_shot", trig_param->trigger_policy) == 0) { - trig_param->report_interval = 0; - trig_param->report_amount = 0; - } else if (strcmp("event_driven", trig_param->trigger_policy) == 0) { - trig_param->report_interval = 6; - trig_param->report_amount = 2; - } else if (strcmp("periodical", trig_param->trigger_policy) == 0) { - trig_param->report_interval = 1; - trig_param->report_amount = 7; - } else { - LOG_E(FLEXRAN_AGENT, "There is something wrong on RRC agent!"); - } - ReportConfig_list = CALLOC(1, sizeof(*ReportConfig_list)); ReportConfig_per = CALLOC(1, sizeof(*ReportConfig_per)); - // Periodical Measurement Report + ReportConfig_A1 = CALLOC(1, sizeof(*ReportConfig_A1)); + ReportConfig_A2 = CALLOC(1, sizeof(*ReportConfig_A2)); + ReportConfig_A3 = CALLOC(1, sizeof(*ReportConfig_A3)); + ReportConfig_A4 = CALLOC(1, sizeof(*ReportConfig_A4)); + ReportConfig_A5 = CALLOC(1, sizeof(*ReportConfig_A5)); ReportConfig_per->reportConfigId = 1; ReportConfig_per->reportConfig.present = LTE_ReportConfigToAddMod__reportConfig_PR_reportConfigEUTRA; ReportConfig_per->reportConfig.choice.reportConfigEUTRA.triggerType.present = LTE_ReportConfigEUTRA__triggerType_PR_periodical; ReportConfig_per->reportConfig.choice.reportConfigEUTRA.triggerType.choice.periodical.purpose = LTE_ReportConfigEUTRA__triggerType__periodical__purpose_reportStrongestCells; - // ReportConfig_per->reportConfig.choice.reportConfigEUTRA.triggerType.choice.event.timeToTrigger = TimeToTrigger_ms40; ReportConfig_per->reportConfig.choice.reportConfigEUTRA.triggerQuantity = LTE_ReportConfigEUTRA__triggerQuantity_rsrp; ReportConfig_per->reportConfig.choice.reportConfigEUTRA.reportQuantity = LTE_ReportConfigEUTRA__reportQuantity_both; ReportConfig_per->reportConfig.choice.reportConfigEUTRA.maxReportCells = 2; - ReportConfig_per->reportConfig.choice.reportConfigEUTRA.reportInterval = trig_param->report_interval ;//ReportInterval_ms2048; // RRC counter frame- ms1024 is 1ms - ReportConfig_per->reportConfig.choice.reportConfigEUTRA.reportAmount = trig_param->report_amount; //ReportConfigEUTRA__reportAmount_r2; // put r1 to see once, r2 for 2 times and ... + ReportConfig_per->reportConfig.choice.reportConfigEUTRA.reportInterval = LTE_ReportInterval_ms120; + ReportConfig_per->reportConfig.choice.reportConfigEUTRA.reportAmount = LTE_ReportConfigEUTRA__reportAmount_infinity; ASN_SEQUENCE_ADD(&ReportConfig_list->list, ReportConfig_per); + ReportConfig_A1->reportConfigId = 2; + ReportConfig_A1->reportConfig.present = LTE_ReportConfigToAddMod__reportConfig_PR_reportConfigEUTRA; + ReportConfig_A1->reportConfig.choice.reportConfigEUTRA.triggerType.present = + LTE_ReportConfigEUTRA__triggerType_PR_event; + ReportConfig_A1->reportConfig.choice.reportConfigEUTRA.triggerType.choice.event.eventId.present = + LTE_ReportConfigEUTRA__triggerType__event__eventId_PR_eventA1; + ReportConfig_A1->reportConfig.choice.reportConfigEUTRA.triggerType.choice.event.eventId.choice.eventA1. + a1_Threshold.present = LTE_ThresholdEUTRA_PR_threshold_RSRP; + ReportConfig_A1->reportConfig.choice.reportConfigEUTRA.triggerType.choice.event.eventId.choice.eventA1. + a1_Threshold.choice.threshold_RSRP = 10; + ReportConfig_A1->reportConfig.choice.reportConfigEUTRA.triggerQuantity = LTE_ReportConfigEUTRA__triggerQuantity_rsrp; + ReportConfig_A1->reportConfig.choice.reportConfigEUTRA.reportQuantity = LTE_ReportConfigEUTRA__reportQuantity_both; + ReportConfig_A1->reportConfig.choice.reportConfigEUTRA.maxReportCells = 2; + ReportConfig_A1->reportConfig.choice.reportConfigEUTRA.reportInterval = LTE_ReportInterval_ms120; + ReportConfig_A1->reportConfig.choice.reportConfigEUTRA.reportAmount = LTE_ReportConfigEUTRA__reportAmount_infinity; + ASN_SEQUENCE_ADD(&ReportConfig_list->list, ReportConfig_A1); + //if (ho_state == 1 /*HO_MEASURMENT */ ) { + LOG_I(RRC, "[eNB %d] frame %d: requesting A2, A3, A4, and A5 event reporting\n", + ctxt_pP->module_id, ctxt_pP->frame); + ReportConfig_A2->reportConfigId = 3; + ReportConfig_A2->reportConfig.present = LTE_ReportConfigToAddMod__reportConfig_PR_reportConfigEUTRA; + ReportConfig_A2->reportConfig.choice.reportConfigEUTRA.triggerType.present = + LTE_ReportConfigEUTRA__triggerType_PR_event; + ReportConfig_A2->reportConfig.choice.reportConfigEUTRA.triggerType.choice.event.eventId.present = + LTE_ReportConfigEUTRA__triggerType__event__eventId_PR_eventA2; + ReportConfig_A2->reportConfig.choice.reportConfigEUTRA.triggerType.choice.event.eventId.choice. + eventA2.a2_Threshold.present = LTE_ThresholdEUTRA_PR_threshold_RSRP; + ReportConfig_A2->reportConfig.choice.reportConfigEUTRA.triggerType.choice.event.eventId.choice. + eventA2.a2_Threshold.choice.threshold_RSRP = 10; + ReportConfig_A2->reportConfig.choice.reportConfigEUTRA.triggerQuantity = + LTE_ReportConfigEUTRA__triggerQuantity_rsrp; + ReportConfig_A2->reportConfig.choice.reportConfigEUTRA.reportQuantity = LTE_ReportConfigEUTRA__reportQuantity_both; + ReportConfig_A2->reportConfig.choice.reportConfigEUTRA.maxReportCells = 2; + ReportConfig_A2->reportConfig.choice.reportConfigEUTRA.reportInterval = LTE_ReportInterval_ms120; + ReportConfig_A2->reportConfig.choice.reportConfigEUTRA.reportAmount = LTE_ReportConfigEUTRA__reportAmount_infinity; + ASN_SEQUENCE_ADD(&ReportConfig_list->list, ReportConfig_A2); + ReportConfig_A3->reportConfigId = 4; + ReportConfig_A3->reportConfig.present = LTE_ReportConfigToAddMod__reportConfig_PR_reportConfigEUTRA; + ReportConfig_A3->reportConfig.choice.reportConfigEUTRA.triggerType.present = + LTE_ReportConfigEUTRA__triggerType_PR_event; + ReportConfig_A3->reportConfig.choice.reportConfigEUTRA.triggerType.choice.event.eventId.present = + LTE_ReportConfigEUTRA__triggerType__event__eventId_PR_eventA3; + ReportConfig_A3->reportConfig.choice.reportConfigEUTRA.triggerType.choice.event.eventId.choice.eventA3.a3_Offset = ue_context_pP->ue_context.measurement_info->events->a3_event->a3_offset;//10; + ReportConfig_A3->reportConfig.choice.reportConfigEUTRA.triggerType.choice.event.eventId.choice. + eventA3.reportOnLeave = ue_context_pP->ue_context.measurement_info->events->a3_event->reportOnLeave; + ReportConfig_A3->reportConfig.choice.reportConfigEUTRA.triggerQuantity = + LTE_ReportConfigEUTRA__triggerQuantity_rsrp; + ReportConfig_A3->reportConfig.choice.reportConfigEUTRA.reportQuantity = LTE_ReportConfigEUTRA__reportQuantity_both; + ReportConfig_A3->reportConfig.choice.reportConfigEUTRA.maxReportCells = ue_context_pP->ue_context.measurement_info->events->a3_event->maxReportCells; + ReportConfig_A3->reportConfig.choice.reportConfigEUTRA.reportInterval = LTE_ReportInterval_ms120; + ReportConfig_A3->reportConfig.choice.reportConfigEUTRA.reportAmount = LTE_ReportConfigEUTRA__reportAmount_infinity; + ReportConfig_A3->reportConfig.choice.reportConfigEUTRA.triggerType.choice.event.hysteresis = ue_context_pP->ue_context.measurement_info->events->a3_event->hysteresis; + ReportConfig_A3->reportConfig.choice.reportConfigEUTRA.triggerType.choice.event.timeToTrigger = + ue_context_pP->ue_context.measurement_info->events->a3_event->timeToTrigger; + ASN_SEQUENCE_ADD(&ReportConfig_list->list, ReportConfig_A3); + ReportConfig_A4->reportConfigId = 5; + ReportConfig_A4->reportConfig.present = LTE_ReportConfigToAddMod__reportConfig_PR_reportConfigEUTRA; + ReportConfig_A4->reportConfig.choice.reportConfigEUTRA.triggerType.present = + LTE_ReportConfigEUTRA__triggerType_PR_event; + ReportConfig_A4->reportConfig.choice.reportConfigEUTRA.triggerType.choice.event.eventId.present = + LTE_ReportConfigEUTRA__triggerType__event__eventId_PR_eventA4; + ReportConfig_A4->reportConfig.choice.reportConfigEUTRA.triggerType.choice.event.eventId.choice. + eventA4.a4_Threshold.present = LTE_ThresholdEUTRA_PR_threshold_RSRP; + ReportConfig_A4->reportConfig.choice.reportConfigEUTRA.triggerType.choice.event.eventId.choice. + eventA4.a4_Threshold.choice.threshold_RSRP = 10; + ReportConfig_A4->reportConfig.choice.reportConfigEUTRA.triggerQuantity = + LTE_ReportConfigEUTRA__triggerQuantity_rsrp; + ReportConfig_A4->reportConfig.choice.reportConfigEUTRA.reportQuantity = LTE_ReportConfigEUTRA__reportQuantity_both; + ReportConfig_A4->reportConfig.choice.reportConfigEUTRA.maxReportCells = 2; + ReportConfig_A4->reportConfig.choice.reportConfigEUTRA.reportInterval = LTE_ReportInterval_ms120; + ReportConfig_A4->reportConfig.choice.reportConfigEUTRA.reportAmount = LTE_ReportConfigEUTRA__reportAmount_infinity; + ASN_SEQUENCE_ADD(&ReportConfig_list->list, ReportConfig_A4); + ReportConfig_A5->reportConfigId = 6; + ReportConfig_A5->reportConfig.present = LTE_ReportConfigToAddMod__reportConfig_PR_reportConfigEUTRA; + ReportConfig_A5->reportConfig.choice.reportConfigEUTRA.triggerType.present = + LTE_ReportConfigEUTRA__triggerType_PR_event; + ReportConfig_A5->reportConfig.choice.reportConfigEUTRA.triggerType.choice.event.eventId.present = + LTE_ReportConfigEUTRA__triggerType__event__eventId_PR_eventA5; + ReportConfig_A5->reportConfig.choice.reportConfigEUTRA.triggerType.choice.event.eventId.choice. + eventA5.a5_Threshold1.present = LTE_ThresholdEUTRA_PR_threshold_RSRP; + ReportConfig_A5->reportConfig.choice.reportConfigEUTRA.triggerType.choice.event.eventId.choice. + eventA5.a5_Threshold2.present = LTE_ThresholdEUTRA_PR_threshold_RSRP; + ReportConfig_A5->reportConfig.choice.reportConfigEUTRA.triggerType.choice.event.eventId.choice. + eventA5.a5_Threshold1.choice.threshold_RSRP = 10; + ReportConfig_A5->reportConfig.choice.reportConfigEUTRA.triggerType.choice.event.eventId.choice. + eventA5.a5_Threshold2.choice.threshold_RSRP = 10; + ReportConfig_A5->reportConfig.choice.reportConfigEUTRA.triggerQuantity = + LTE_ReportConfigEUTRA__triggerQuantity_rsrp; + ReportConfig_A5->reportConfig.choice.reportConfigEUTRA.reportQuantity = LTE_ReportConfigEUTRA__reportQuantity_both; + ReportConfig_A5->reportConfig.choice.reportConfigEUTRA.maxReportCells = 2; + ReportConfig_A5->reportConfig.choice.reportConfigEUTRA.reportInterval = LTE_ReportInterval_ms120; + ReportConfig_A5->reportConfig.choice.reportConfigEUTRA.reportAmount = LTE_ReportConfigEUTRA__reportAmount_infinity; + ASN_SEQUENCE_ADD(&ReportConfig_list->list, ReportConfig_A5); + // LTE_RRCConnectionReconfiguration->criticalExtensions.choice.c1.choice.rrcConnectionReconfiguration_r8.measConfig->reportConfigToAddModList = ReportConfig_list; + + rsrp = CALLOC(1, sizeof(LTE_RSRP_Range_t)); + *rsrp = 20; + Sparams = CALLOC(1, sizeof(*Sparams)); + Sparams->present = LTE_MeasConfig__speedStatePars_PR_setup; + Sparams->choice.setup.timeToTrigger_SF.sf_High = LTE_SpeedStateScaleFactors__sf_Medium_oDot75; + Sparams->choice.setup.timeToTrigger_SF.sf_Medium = LTE_SpeedStateScaleFactors__sf_High_oDot5; + Sparams->choice.setup.mobilityStateParameters.n_CellChangeHigh = 10; + Sparams->choice.setup.mobilityStateParameters.n_CellChangeMedium = 5; + Sparams->choice.setup.mobilityStateParameters.t_Evaluation = LTE_MobilityStateParameters__t_Evaluation_s60; + Sparams->choice.setup.mobilityStateParameters.t_HystNormal = LTE_MobilityStateParameters__t_HystNormal_s120; quantityConfig = CALLOC(1, sizeof(*quantityConfig)); memset((void *)quantityConfig, 0, sizeof(*quantityConfig)); quantityConfig->quantityConfigEUTRA = CALLOC(1, sizeof(struct LTE_QuantityConfigEUTRA)); @@ -4006,8 +4184,9 @@ flexran_rrc_eNB_generate_defaultRRCConnectionReconfiguration(const protocol_ctxt CALLOC(1, sizeof(*(quantityConfig->quantityConfigEUTRA->filterCoefficientRSRP))); quantityConfig->quantityConfigEUTRA->filterCoefficientRSRQ = CALLOC(1, sizeof(*(quantityConfig->quantityConfigEUTRA->filterCoefficientRSRQ))); - *quantityConfig->quantityConfigEUTRA->filterCoefficientRSRP = LTE_FilterCoefficient_fc4; - *quantityConfig->quantityConfigEUTRA->filterCoefficientRSRQ = LTE_FilterCoefficient_fc4; + *quantityConfig->quantityConfigEUTRA->filterCoefficientRSRP = ue_context_pP->ue_context.measurement_info->filterCoefficientRSRP; + *quantityConfig->quantityConfigEUTRA->filterCoefficientRSRQ = ue_context_pP->ue_context.measurement_info->filterCoefficientRSRQ; + /* Initialize NAS list */ dedicatedInfoNASList = CALLOC(1, sizeof(struct LTE_RRCConnectionReconfiguration_r8_IEs__dedicatedInfoNASList)); @@ -4023,12 +4202,13 @@ flexran_rrc_eNB_generate_defaultRRCConnectionReconfiguration(const protocol_ctxt } /* TODO parameters yet to process ... */ - // { - // ue_context_pP->ue_context.e_rab[i].param.qos; - // ue_context_pP->ue_context.e_rab[i].param.sgw_addr; - // ue_context_pP->ue_context.e_rab[i].param.gtp_teid; - // } - /* TODO should test if e RAB are Ok before! */ + { + // ue_context_pP->ue_context.e_rab[i].param.qos; + // ue_context_pP->ue_context.e_rab[i].param.sgw_addr; + // ue_context_pP->ue_context.e_rab[i].param.gtp_teid; + } + + /* TODO should test if e RAB are OK before! */ ue_context_pP->ue_context.e_rab[i].status = E_RAB_STATUS_DONE; LOG_D(RRC, "setting the status for the default DRB (index %d) to (%d,%s)\n", i, ue_context_pP->ue_context.e_rab[i].status, "E_RAB_STATUS_DONE"); @@ -4044,38 +4224,35 @@ flexran_rrc_eNB_generate_defaultRRCConnectionReconfiguration(const protocol_ctxt RC.rrc[ENB_INSTANCE_TO_MODULE_ID(ctxt_pP->instance)]->configuration.enable_measurement_reports; memset(buffer, 0, RRC_BUF_SIZE); + size = do_RRCConnectionReconfiguration(ctxt_pP, buffer, - xid, //Transaction_id, - (LTE_SRB_ToAddModList_t *)NULL, // SRB_configList - (LTE_DRB_ToAddModList_t *)NULL, - (LTE_DRB_ToReleaseList_t *)NULL, // DRB2_list, - (struct LTE_SPS_Config *)NULL, // *sps_Config, - (struct LTE_PhysicalConfigDedicated *)*physicalConfigDedicated, - // #ifdef EXMIMO_IOT - // NULL, NULL, NULL,NULL, - // #else - measurements_enabled ? (LTE_MeasObjectToAddModList_t *)MeasObj_list : NULL, - measurements_enabled ? (LTE_ReportConfigToAddModList_t *)ReportConfig_list : NULL, - measurements_enabled ? (LTE_QuantityConfig_t *)quantityConfig : NULL, - measurements_enabled ? (LTE_MeasIdToAddModList_t *)MeasId_list : NULL, - // #endif - (LTE_MAC_MainConfig_t *)mac_MainConfig, - (LTE_MeasGapConfig_t *)NULL, - (LTE_MobilityControlInfo_t *)NULL, - (LTE_SecurityConfigHO_t *)NULL, - (struct LTE_MeasConfig__speedStatePars *)Sparams, - (LTE_RSRP_Range_t *)rsrp, - (LTE_C_RNTI_t *)cba_RNTI, - (struct LTE_RRCConnectionReconfiguration_r8_IEs__dedicatedInfoNASList *)dedicatedInfoNASList, - (LTE_SL_CommConfig_r12_t *)NULL, - (LTE_SL_DiscConfig_r12_t *)NULL + xid, // Transaction_id, + (LTE_SRB_ToAddModList_t *) *SRB_configList2, // SRB_configList + (LTE_DRB_ToAddModList_t *) *DRB_configList, + (LTE_DRB_ToReleaseList_t *) NULL, // DRB2_list, + (struct LTE_SPS_Config *) NULL, // *sps_Config, + (struct LTE_PhysicalConfigDedicated *) *physicalConfigDedicated, + measurements_enabled ? (LTE_MeasObjectToAddModList_t *) MeasObj_list : NULL, + measurements_enabled ? (LTE_ReportConfigToAddModList_t *) ReportConfig_list : NULL, + measurements_enabled ? (LTE_QuantityConfig_t *) quantityConfig : NULL, + measurements_enabled ? (LTE_MeasIdToAddModList_t *) MeasId_list : NULL, + (LTE_MAC_MainConfig_t *) mac_MainConfig, + (LTE_MeasGapConfig_t *) NULL, + (LTE_MobilityControlInfo_t *) NULL, + (LTE_SecurityConfigHO_t *) NULL, + (struct LTE_MeasConfig__speedStatePars *) Sparams, + (LTE_RSRP_Range_t *) rsrp, + (LTE_C_RNTI_t *) cba_RNTI, + (struct LTE_RRCConnectionReconfiguration_r8_IEs__dedicatedInfoNASList *) dedicatedInfoNASList, + (LTE_SL_CommConfig_r12_t *) NULL, + (LTE_SL_DiscConfig_r12_t *) NULL #if (LTE_RRC_VERSION >= MAKE_VERSION(10, 0, 0)) - , (LTE_SCellToAddMod_r10_t *)NULL + , (LTE_SCellToAddMod_r10_t *) NULL #endif ); - LOG_DUMPMSG(RRC,DEBUG_RRC,(char *)buffer,size, - "[MSG] RRC Connection Reconfiguration\n"); + + LOG_DUMPMSG(RRC, DEBUG_RRC,(char *)buffer, size, "[MSG] RRC Connection Reconfiguration\n"); /* Free all NAS PDUs */ for (i = 0; i < ue_context_pP->ue_context.nb_of_e_rabs; i++) { @@ -4086,30 +4263,38 @@ flexran_rrc_eNB_generate_defaultRRCConnectionReconfiguration(const protocol_ctxt } } - LOG_I(RRC, - "[eNB %d] Frame %d, Logical Channel DL-DCCH, Generate LTE_RRCConnectionReconfiguration (bytes %d, UE id %x)\n", - ctxt_pP->module_id, ctxt_pP->frame, size, ue_context_pP->ue_context.rnti); - LOG_D(RRC, - "[FRAME %05d][RRC_eNB][MOD %u][][--- PDCP_DATA_REQ/%d Bytes (rrcConnectionReconfiguration to UE %x MUI %d) --->][PDCP][MOD %u][RB %u]\n", - ctxt_pP->frame, ctxt_pP->module_id, size, ue_context_pP->ue_context.rnti, rrc_eNB_mui, ctxt_pP->module_id, DCCH); - MSC_LOG_TX_MESSAGE( - MSC_RRC_ENB, - MSC_RRC_UE, - buffer, - size, - MSC_AS_TIME_FMT" LTE_RRCConnectionReconfiguration UE %x MUI %d size %u", - MSC_AS_TIME_ARGS(ctxt_pP), - ue_context_pP->ue_context.rnti, - rrc_eNB_mui, - size); - rrc_data_req( - ctxt_pP, - DCCH, - rrc_eNB_mui++, - SDU_CONFIRM_NO, - size, - buffer, - PDCP_TRANSMISSION_MODE_CONTROL); + LOG_I(RRC, "[eNB %d] Frame %d, Logical Channel DL-DCCH, Generate LTE_RRCConnectionReconfiguration (bytes %d, UE id %x)\n", + ctxt_pP->module_id, + ctxt_pP->frame, + size, + ue_context_pP->ue_context.rnti); + + LOG_D(RRC, "[FRAME %05d][RRC_eNB][MOD %u][][--- PDCP_DATA_REQ/%d Bytes (rrcConnectionReconfiguration to UE %x MUI %d) --->][PDCP][MOD %u][RB %u]\n", + ctxt_pP->frame, + ctxt_pP->module_id, + size, + ue_context_pP->ue_context.rnti, + rrc_eNB_mui, + ctxt_pP->module_id, + DCCH); + + MSC_LOG_TX_MESSAGE(MSC_RRC_ENB, + MSC_RRC_UE, + buffer, + size, + MSC_AS_TIME_FMT" LTE_RRCConnectionReconfiguration UE %x MUI %d size %u", + MSC_AS_TIME_ARGS(ctxt_pP), + ue_context_pP->ue_context.rnti, + rrc_eNB_mui, + size); + + rrc_data_req(ctxt_pP, + DCCH, + rrc_eNB_mui++, + SDU_CONFIRM_NO, + size, + buffer, + PDCP_TRANSMISSION_MODE_CONTROL); free(quantityConfig->quantityConfigEUTRA->filterCoefficientRSRQ); quantityConfig->quantityConfigEUTRA->filterCoefficientRSRQ = NULL; @@ -4133,7 +4318,6 @@ flexran_rrc_eNB_generate_defaultRRCConnectionReconfiguration(const protocol_ctxt mac_MainConfig = NULL; } - //----------------------------------------------------------------------------- int rrc_eNB_generate_RRCConnectionReconfiguration_SCell( diff --git a/openair2/RRC/LTE/rrc_proto.h b/openair2/RRC/LTE/rrc_proto.h index 5fc935c0ea..8aa0125c0e 100644 --- a/openair2/RRC/LTE/rrc_proto.h +++ b/openair2/RRC/LTE/rrc_proto.h @@ -306,8 +306,7 @@ void flexran_rrc_eNB_generate_defaultRRCConnectionReconfiguration( const protocol_ctxt_t *const ctxt_pP, rrc_eNB_ue_context_t *const ue_context_pP, - const uint8_t ho_state, - agent_reconf_rrc *trig_param + const uint8_t ho_state ); void rrc_eNB_generate_HO_RRCConnectionReconfiguration(const protocol_ctxt_t *const ctxt_pP, From 8cf520d283a5e30e3063d2fb4883ff178cd7361f Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Mon, 13 May 2019 17:39:43 +0200 Subject: [PATCH 13/32] Rename FlexRAN RRC reconfiguration function, simplify function --- openair2/ENB_APP/flexran_agent_common.c | 53 +++++------------------- openair2/ENB_APP/flexran_agent_common.h | 2 +- openair2/ENB_APP/flexran_agent_handler.c | 2 +- 3 files changed, 13 insertions(+), 44 deletions(-) diff --git a/openair2/ENB_APP/flexran_agent_common.c b/openair2/ENB_APP/flexran_agent_common.c index e2bd5f8146..9f932dd3c7 100644 --- a/openair2/ENB_APP/flexran_agent_common.c +++ b/openair2/ENB_APP/flexran_agent_common.c @@ -805,66 +805,35 @@ error: } -int flexran_agent_rrc_measurement(mid_t mod_id, const void *params, Protocol__FlexranMessage **msg) { - //protocol_ctxt_t ctxt; +int flexran_agent_rrc_reconfiguration(mid_t mod_id, const void *params, Protocol__FlexranMessage **msg) { Protocol__FlexranMessage *input = (Protocol__FlexranMessage *)params; Protocol__FlexRrcTriggering *triggering = input->rrc_triggering; - //agent_reconf_rrc *rrc_reconf = malloc(sizeof(agent_reconf_rrc)); - - #if 0 - reconf_param->trigger_policy = triggering->rrc_trigger; - reconf_param->report_interval = 0; - reconf_param->report_amount = 0; - struct rrc_eNB_ue_context_s *ue_context_p = NULL; - RB_FOREACH(ue_context_p, rrc_ue_tree_s, &(RC.rrc[mod_id]->rrc_ue_head)) { - PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, mod_id, ENB_FLAG_YES, ue_context_p->ue_context.rnti, flexran_get_current_frame(mod_id), flexran_get_current_subframe (mod_id), mod_id); - flexran_rrc_eNB_generate_defaultRRCConnectionReconfiguration(&ctxt, ue_context_p, 0, reconf_param); - } - #endif - - // TODO: Step 1 - Verification process - - // Step 2 - Set the proper values using FlexRAN API (protected with mutex ?) - int num_ue = 0; - - if (flexran_agent_get_rrc_xface(mod_id)) - num_ue = flexran_get_rrc_num_ues(mod_id); - else if (flexran_agent_get_mac_xface(mod_id)) - num_ue = flexran_get_mac_num_ues(mod_id); - - if (flexran_agent_get_rrc_xface(mod_id) && flexran_agent_get_mac_xface(mod_id) - && flexran_get_rrc_num_ues(mod_id) != flexran_get_mac_num_ues(mod_id)) { - const int nrrc = flexran_get_rrc_num_ues(mod_id); - const int nmac = flexran_get_mac_num_ues(mod_id); - num_ue = nrrc < nmac ? nrrc : nmac; - LOG_E(FLEXRAN_AGENT, "%s(): different numbers of UEs in RRC (%d) and MAC (%d), reporting for %d UEs\n", - __func__, nrrc, nmac, num_ue); + // Set the proper values using FlexRAN API (protected with mutex ?) + if (!flexran_agent_get_rrc_xface(mod_id)) { + LOG_E(FLEXRAN_AGENT, "%s(): no RRC present, aborting\n", __func__); + return -1; } + int num_ue = flexran_get_rrc_num_ues(mod_id); if (num_ue == 0) return 0; - int error = 0; rnti_t rntis[num_ue]; flexran_get_rrc_rnti_list(mod_id, rntis, num_ue); for (int i = 0; i < num_ue; i++) { const rnti_t rnti = rntis[i]; - if (flexran_agent_get_rrc_xface(mod_id)) - error = update_rrc_reconfig(mod_id, rnti, triggering); + const int error = update_rrc_reconfig(mod_id, rnti, triggering); if (error < 0) { LOG_E(FLEXRAN_AGENT, "Error in updating user %d\n", i); + continue; } - else { - // Step 3 - Call the proper wrapper in FlexRAN API - if (flexran_call_rrc_reconfiguration (mod_id, rnti) <0) { - LOG_E(FLEXRAN_AGENT, "Error in reconfiguring user %d\n", i); - } + // Call the proper wrapper in FlexRAN API + if (flexran_call_rrc_reconfiguration (mod_id, rnti) < 0) { + LOG_E(FLEXRAN_AGENT, "Error in reconfiguring user %d\n", i); } } *msg = NULL; - //free(reconf_param); - //reconf_param = NULL; return 0; } diff --git a/openair2/ENB_APP/flexran_agent_common.h b/openair2/ENB_APP/flexran_agent_common.h index 8419dae62d..aad77635f2 100644 --- a/openair2/ENB_APP/flexran_agent_common.h +++ b/openair2/ENB_APP/flexran_agent_common.h @@ -137,7 +137,7 @@ int flexran_agent_reconfiguration(mid_t mod_id, const void *params, Protocol__Fl int flexran_agent_destroy_agent_reconfiguration(Protocol__FlexranMessage *msg); /* rrc triggering measurement message constructor and destructor */ -int flexran_agent_rrc_measurement(mid_t mod_id, const void *params, Protocol__FlexranMessage **msg); +int flexran_agent_rrc_reconfiguration(mid_t mod_id, const void *params, Protocol__FlexranMessage **msg); int flexran_agent_destroy_rrc_measurement(Protocol__FlexranMessage *msg); diff --git a/openair2/ENB_APP/flexran_agent_handler.c b/openair2/ENB_APP/flexran_agent_handler.c index 6c2e6429eb..7112d1fe36 100644 --- a/openair2/ENB_APP/flexran_agent_handler.c +++ b/openair2/ENB_APP/flexran_agent_handler.c @@ -55,7 +55,7 @@ flexran_agent_message_decoded_callback agent_messages_callback[][3] = { {0, 0, 0}, /*PROTOCOL__FLEXRAN_MESSAGE__MSG_UE_STATE_CHANGE_MSG*/ {flexran_agent_control_delegation, 0, 0}, /*PROTOCOL__FLEXRAN_MESSAGE__MSG_CONTROL_DELEGATION_MSG*/ {flexran_agent_reconfiguration, 0, 0}, /*PROTOCOL__FLEXRAN_MESSAGE__MSG_AGENT_RECONFIGURATION_MSG*/ - {flexran_agent_rrc_measurement, 0, 0}, /*PROTOCOL__FLEXRAN_MESSAGE__MSG_RRC_TRIGGERING_MSG*/ + {flexran_agent_rrc_reconfiguration, 0, 0}, /*PROTOCOL__FLEXRAN_MESSAGE__MSG_RRC_TRIGGERING_MSG*/ }; flexran_agent_message_destruction_callback message_destruction_callback[] = { From 939251e0043e23d1dc3fe9b08bea9f042ba6add8 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Wed, 12 Jun 2019 10:30:59 +0200 Subject: [PATCH 14/32] Fix: Memory allocation for offsetFreq parameter --- openair2/RRC/LTE/rrc_eNB.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/openair2/RRC/LTE/rrc_eNB.c b/openair2/RRC/LTE/rrc_eNB.c index 40e82bb74e..f82f7a42a9 100644 --- a/openair2/RRC/LTE/rrc_eNB.c +++ b/openair2/RRC/LTE/rrc_eNB.c @@ -3316,7 +3316,7 @@ void rrc_eNB_generate_defaultRRCConnectionReconfiguration(const protocol_ctxt_t //TODO: Assign proper values ue_context_pP->ue_context.measurement_info->offsetFreq = 0; - ue_context_pP->ue_context.measurement_info->cellIndividualOffset[0] = 0; + ue_context_pP->ue_context.measurement_info->cellIndividualOffset[0] = LTE_Q_OffsetRange_dB0; /* TODO: Extend to multiple carriers */ // Add adjacent cell lists (max 6 per eNB) @@ -4028,6 +4028,7 @@ flexran_rrc_eNB_generate_defaultRRCConnectionReconfiguration(const protocol_ctxt MeasObj->measObject.choice.measObjectEUTRA.neighCellConfig.buf[0] = 0; MeasObj->measObject.choice.measObjectEUTRA.neighCellConfig.size = 1; MeasObj->measObject.choice.measObjectEUTRA.neighCellConfig.bits_unused = 6; + MeasObj->measObject.choice.measObjectEUTRA.offsetFreq = (LTE_Q_OffsetRange_t *) CALLOC(1,sizeof(LTE_Q_OffsetRange_t)); *(MeasObj->measObject.choice.measObjectEUTRA.offsetFreq) = ue_context_pP->ue_context.measurement_info->offsetFreq; // Default is 15 or 0dB if (RC.rrc[ctxt_pP->module_id]->num_neigh_cells > 0) { @@ -5563,7 +5564,7 @@ rrc_eNB_generate_HO_RRCConnectionReconfiguration(const protocol_ctxt_t *const ct //TODO: Assign proper values ue_context_pP->ue_context.measurement_info->offsetFreq = 0; - ue_context_pP->ue_context.measurement_info->cellIndividualOffset[0] = 0; + ue_context_pP->ue_context.measurement_info->cellIndividualOffset[0] = LTE_Q_OffsetRange_dB0; /* TODO: Extend to multiple carriers */ // Add adjacent cell lists (max 6 per eNB) From 5e148d439ad3f31a685e908d1d01bb5c98bde13f Mon Sep 17 00:00:00 2001 From: Konstantinos Alexandris Date: Fri, 17 May 2019 16:17:57 +0200 Subject: [PATCH 15/32] Legal 3GPP values check for measurement report parameters --- openair2/ENB_APP/flexran_agent_ran_api.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/openair2/ENB_APP/flexran_agent_ran_api.c b/openair2/ENB_APP/flexran_agent_ran_api.c index b711e9b13e..5b067cea55 100644 --- a/openair2/ENB_APP/flexran_agent_ran_api.c +++ b/openair2/ENB_APP/flexran_agent_ran_api.c @@ -1821,6 +1821,7 @@ int flexran_set_rrc_ofp(mid_t mod_id, rnti_t rnti, long offsetFreq) { struct rrc_eNB_ue_context_s* ue_context_p = rrc_eNB_get_ue_context(RC.rrc[mod_id], rnti); if (!ue_context_p) return -1; if (!ue_context_p->ue_context.measurement_info) return -1; + if (!((offsetFreq >= -15) && (offsetFreq <= 15))) return -1; ue_context_p->ue_context.measurement_info->offsetFreq = offsetFreq; return 0; } @@ -1830,6 +1831,7 @@ int flexran_set_rrc_ofn(mid_t mod_id, rnti_t rnti, long offsetFreq) { struct rrc_eNB_ue_context_s* ue_context_p = rrc_eNB_get_ue_context(RC.rrc[mod_id], rnti); if (!ue_context_p) return -1; if (!ue_context_p->ue_context.measurement_info) return -1; + if (!((offsetFreq >= -15) && (offsetFreq <= 15))) return -1; ue_context_p->ue_context.measurement_info->offsetFreq = offsetFreq; return 0; } @@ -1985,6 +1987,7 @@ int flexran_set_rrc_per_event_maxReportCells(mid_t mod_id, rnti_t rnti, long max if (!ue_context_p->ue_context.measurement_info) return -1; if (!ue_context_p->ue_context.measurement_info->events) return -1; if (!ue_context_p->ue_context.measurement_info->events->per_event) return -1; + if (!((maxReportCells >= 1) && (maxReportCells <= 8))) return -1; ue_context_p->ue_context.measurement_info->events->per_event->maxReportCells = maxReportCells; return 0; } @@ -1998,6 +2001,7 @@ int flexran_set_rrc_a3_event_hysteresis(mid_t mod_id, rnti_t rnti, long hysteres if (!ue_context_p->ue_context.measurement_info) return -1; if (!ue_context_p->ue_context.measurement_info->events) return -1; if (!ue_context_p->ue_context.measurement_info->events->a3_event) return -1; + if (!((hysteresis >=0) && (hysteresis <= 30))) return -1; ue_context_p->ue_context.measurement_info->events->a3_event->hysteresis = hysteresis; return 0; } @@ -2039,6 +2043,7 @@ int flexran_set_rrc_a3_event_maxReportCells(mid_t mod_id, rnti_t rnti, long maxR if (!ue_context_p->ue_context.measurement_info) return -1; if (!ue_context_p->ue_context.measurement_info->events) return -1; if (!ue_context_p->ue_context.measurement_info->events->a3_event) return -1; + if (!((maxReportCells >= 1) && (maxReportCells <= 8))) return -1; ue_context_p->ue_context.measurement_info->events->a3_event->maxReportCells = maxReportCells; return 0; } @@ -2050,6 +2055,7 @@ int flexran_set_rrc_a3_event_a3_offset(mid_t mod_id, rnti_t rnti, long a3_offset if (!ue_context_p->ue_context.measurement_info) return -1; if (!ue_context_p->ue_context.measurement_info->events) return -1; if (!ue_context_p->ue_context.measurement_info->events->a3_event) return -1; + if (!((a3_offset >= -30) && (a3_offset <= 30))) return -1; ue_context_p->ue_context.measurement_info->events->a3_event->a3_offset = a3_offset; return 0; } @@ -2061,6 +2067,7 @@ int flexran_set_rrc_a3_event_reportOnLeave(mid_t mod_id, rnti_t rnti, int report if (!ue_context_p->ue_context.measurement_info) return -1; if (!ue_context_p->ue_context.measurement_info->events) return -1; if (!ue_context_p->ue_context.measurement_info->events->a3_event) return -1; + if (!((reportOnLeave == 0) || (reportOnLeave == 1))) return -1; ue_context_p->ue_context.measurement_info->events->a3_event->reportOnLeave = reportOnLeave; return 0; } From 8957cfef78f3bb6b61cbb317b3c5099fd23f3219 Mon Sep 17 00:00:00 2001 From: Konstantinos Alexandris Date: Mon, 20 May 2019 17:51:02 +0200 Subject: [PATCH 16/32] Add HO trigger function via FlexRAN controller (OAI + FlexRAN handler) --- openair2/ENB_APP/MESSAGES/V2/flexran.proto | 7 ++ openair2/ENB_APP/MESSAGES/V2/header.proto | 1 + openair2/ENB_APP/flexran_agent_common.c | 53 +++++++++++- openair2/ENB_APP/flexran_agent_common.h | 5 +- openair2/ENB_APP/flexran_agent_handler.c | 3 + openair2/ENB_APP/flexran_agent_ran_api.c | 10 +++ openair2/ENB_APP/flexran_agent_ran_api.h | 3 + openair2/RRC/LTE/rrc_eNB.c | 93 ++++++++++++++++++++++ openair2/RRC/LTE/rrc_proto.h | 6 ++ 9 files changed, 179 insertions(+), 2 deletions(-) diff --git a/openair2/ENB_APP/MESSAGES/V2/flexran.proto b/openair2/ENB_APP/MESSAGES/V2/flexran.proto index 840e53f616..86f2e9329f 100644 --- a/openair2/ENB_APP/MESSAGES/V2/flexran.proto +++ b/openair2/ENB_APP/MESSAGES/V2/flexran.proto @@ -32,6 +32,7 @@ message flexran_message { flex_rrc_triggering rrc_triggering = 18; flex_ul_mac_config ul_mac_config_msg = 19; flex_disconnect disconnect_msg = 20; + flex_ho_command ho_command_msg = 21; } } @@ -192,6 +193,12 @@ message flex_rrc_triggering { optional flex_measurement_info meas_info = 3; } +message flex_ho_command { + optional flex_header header = 1; + optional uint32 rnti = 2; + optional uint32 target_phy_cell_id = 3; +} + // // UE state change message // diff --git a/openair2/ENB_APP/MESSAGES/V2/header.proto b/openair2/ENB_APP/MESSAGES/V2/header.proto index c91d2e2c09..41b2b37f7a 100644 --- a/openair2/ENB_APP/MESSAGES/V2/header.proto +++ b/openair2/ENB_APP/MESSAGES/V2/header.proto @@ -34,6 +34,7 @@ enum flex_type { //Controller command messages FLPT_DL_MAC_CONFIG = 13; + FLPT_HO_COMMAND = 21; // UE state change messages FLPT_UE_STATE_CHANGE = 14; diff --git a/openair2/ENB_APP/flexran_agent_common.c b/openair2/ENB_APP/flexran_agent_common.c index 9f932dd3c7..757a796233 100644 --- a/openair2/ENB_APP/flexran_agent_common.c +++ b/openair2/ENB_APP/flexran_agent_common.c @@ -837,8 +837,59 @@ int flexran_agent_rrc_reconfiguration(mid_t mod_id, const void *params, Protocol return 0; } +int flexran_agent_rrc_trigger_handover(mid_t mod_id, const void *params, Protocol__FlexranMessage **msg) { + Protocol__FlexranMessage *input = (Protocol__FlexranMessage *)params; + Protocol__FlexHoCommand *ho_command = input->ho_command_msg; -int flexran_agent_destroy_rrc_measurement(Protocol__FlexranMessage *msg) { + int rnti_found = 0; + + // Set the proper values using FlexRAN API (protected with mutex ?) + if (!flexran_agent_get_rrc_xface(mod_id)) { + LOG_E(FLEXRAN_AGENT, "%s(): no RRC present, aborting\n", __func__); + return -1; + } + + int num_ue = flexran_get_rrc_num_ues(mod_id); + if (num_ue == 0) + return 0; + + if (!ho_command->has_rnti) { + LOG_E(FLEXRAN_AGENT, "%s(): no UE rnti is present, aborting\n", __func__); + return -1; + } + + if (!ho_command->has_target_phy_cell_id) { + LOG_E(FLEXRAN_AGENT, "%s(): no target physical cell id is present, aborting\n", __func__); + return -1; + } + + rnti_t rntis[num_ue]; + flexran_get_rrc_rnti_list(mod_id, rntis, num_ue); + for (int i = 0; i < num_ue; i++) { + const rnti_t rnti = rntis[i]; + if (ho_command->rnti == rnti) { + rnti_found = 1; + // Call the proper wrapper in FlexRAN API + if (flexran_call_rrc_trigger_handover(mod_id, ho_command->rnti, ho_command->target_phy_cell_id) < 0) { + LOG_E(FLEXRAN_AGENT, "Error in handovering user %d\n", i); + } + break; + } + } + + if (!rnti_found) + return -1; + + *msg = NULL; + return 0; +} + +int flexran_agent_destroy_rrc_reconfiguration(Protocol__FlexranMessage *msg) { + // TODO + return 0; +} + +int flexran_agent_destroy_rrc_trigger_handover(Protocol__FlexranMessage *msg) { // TODO return 0; } diff --git a/openair2/ENB_APP/flexran_agent_common.h b/openair2/ENB_APP/flexran_agent_common.h index aad77635f2..f116eb6591 100644 --- a/openair2/ENB_APP/flexran_agent_common.h +++ b/openair2/ENB_APP/flexran_agent_common.h @@ -138,8 +138,11 @@ int flexran_agent_destroy_agent_reconfiguration(Protocol__FlexranMessage *msg); /* rrc triggering measurement message constructor and destructor */ int flexran_agent_rrc_reconfiguration(mid_t mod_id, const void *params, Protocol__FlexranMessage **msg); -int flexran_agent_destroy_rrc_measurement(Protocol__FlexranMessage *msg); +int flexran_agent_destroy_rrc_reconfiguration(Protocol__FlexranMessage *msg); +/* rrc triggering handover command message constructor and destructor */ +int flexran_agent_rrc_trigger_handover(mid_t mod_id, const void *params, Protocol__FlexranMessage **msg); +int flexran_agent_destroy_rrc_trigger_handover(Protocol__FlexranMessage *msg); /* FlexRAN protocol message dispatcher function */ Protocol__FlexranMessage* flexran_agent_handle_message (mid_t mod_id, diff --git a/openair2/ENB_APP/flexran_agent_handler.c b/openair2/ENB_APP/flexran_agent_handler.c index 7112d1fe36..65663e20a8 100644 --- a/openair2/ENB_APP/flexran_agent_handler.c +++ b/openair2/ENB_APP/flexran_agent_handler.c @@ -56,6 +56,9 @@ flexran_agent_message_decoded_callback agent_messages_callback[][3] = { {flexran_agent_control_delegation, 0, 0}, /*PROTOCOL__FLEXRAN_MESSAGE__MSG_CONTROL_DELEGATION_MSG*/ {flexran_agent_reconfiguration, 0, 0}, /*PROTOCOL__FLEXRAN_MESSAGE__MSG_AGENT_RECONFIGURATION_MSG*/ {flexran_agent_rrc_reconfiguration, 0, 0}, /*PROTOCOL__FLEXRAN_MESSAGE__MSG_RRC_TRIGGERING_MSG*/ + {0, 0, 0}, /*PROTOCOL__FLEXRAN_MESSAGE__MSG_UL_MAC_CONFIG_MSG*/ + {0, 0, 0}, /*PROTOCOL__FLEXRAN_MESSAGE__MSG_DISCONNECT_MSG*/ + {flexran_agent_rrc_trigger_handover, 0, 0}, /*PROTOCOL__FLEXRAN_MESSAGE__MSG_HO_COMMAND_MSG*/ }; flexran_agent_message_destruction_callback message_destruction_callback[] = { diff --git a/openair2/ENB_APP/flexran_agent_ran_api.c b/openair2/ENB_APP/flexran_agent_ran_api.c index 5b067cea55..cd91e73a7c 100644 --- a/openair2/ENB_APP/flexran_agent_ran_api.c +++ b/openair2/ENB_APP/flexran_agent_ran_api.c @@ -1446,6 +1446,16 @@ int flexran_call_rrc_reconfiguration (mid_t mod_id, rnti_t rnti) { return 0; } +int flexran_call_rrc_trigger_handover (mid_t mod_id, rnti_t rnti, int target_cell_id) { + if (!rrc_is_present(mod_id)) return -1; + protocol_ctxt_t ctxt; + memset(&ctxt, 0, sizeof(ctxt)); + struct rrc_eNB_ue_context_s* ue_context_p = rrc_eNB_get_ue_context(RC.rrc[mod_id], rnti); + if (!ue_context_p) return -1; + PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, mod_id, ENB_FLAG_YES, ue_context_p->ue_context.rnti, flexran_get_current_frame(mod_id), flexran_get_current_subframe (mod_id), mod_id); + return flexran_rrc_eNB_trigger_handover(mod_id, &ctxt, ue_context_p, target_cell_id); +} + /* RRC Getters */ LTE_MeasId_t flexran_get_rrc_pcell_measid(mid_t mod_id, rnti_t rnti) { diff --git a/openair2/ENB_APP/flexran_agent_ran_api.h b/openair2/ENB_APP/flexran_agent_ran_api.h index aabd327638..d3229bd462 100644 --- a/openair2/ENB_APP/flexran_agent_ran_api.h +++ b/openair2/ENB_APP/flexran_agent_ran_api.h @@ -501,6 +501,9 @@ uint32_t flexran_get_pdcp_rx_oo(mid_t mod_id, uint16_t uid, lcid_t lcid); /* Call RRC Reconfiguration wrapper function */ int flexran_call_rrc_reconfiguration (mid_t mod_id, rnti_t rnti); +/* Call RRC to trigger handover wrapper function */ +int flexran_call_rrc_trigger_handover (mid_t mod_id, rnti_t rnti, int target_cell_id); + /*Get primary cell measuremeant id flexRAN*/ LTE_MeasId_t flexran_get_rrc_pcell_measid(mid_t mod_id, rnti_t rnti); diff --git a/openair2/RRC/LTE/rrc_eNB.c b/openair2/RRC/LTE/rrc_eNB.c index f82f7a42a9..fd308caebe 100644 --- a/openair2/RRC/LTE/rrc_eNB.c +++ b/openair2/RRC/LTE/rrc_eNB.c @@ -4817,6 +4817,99 @@ void rrc_eNB_handover_cancel( S1AP_CAUSE_RADIO_NETWORK, s1_cause); } + +int +flexran_rrc_eNB_trigger_handover (int mod_id, + const protocol_ctxt_t *const ctxt_pP, + rrc_eNB_ue_context_t *ue_context_pP, + int target_cell_id) { + +uint32_t earfcn_dl; +uint8_t KeNB_star[32] = { 0 }; +int cell_found = 0; + + /* Check if eNB id belongs to the supported ones-Extend for multiple carrieres */ + + for (int i=0; i < RC.rrc[mod_id]->num_neigh_cells; i++) { + if (RC.rrc[mod_id]->neigh_cells_id[i][0] == target_cell_id) { + cell_found = 1; + break; + } + } + + /* Check if eNB id was found */ + + if (!cell_found) + return -1; + + /* Handover process is following */ + + /* if X2AP is disabled, do nothing */ + if (!is_x2ap_enabled()) + return -1; + + LOG_D(RRC, "Handover is triggered by FlexRAN controller...\n"); + + /* if the UE is not in handover mode, start handover procedure */ + if (ue_context_pP->ue_context.Status != RRC_HO_EXECUTION) { + MessageDef *msg; + LOG_I(RRC, "Send HO preparation message at frame %d and subframe %d \n", ctxt_pP->frame, ctxt_pP->subframe); + /* Check memory leakage for handover info */ + //if (ue_context_pP->ue_context.handover_info) { + //free(ue_context_pP->ue_context.handover_info); + //} + ue_context_pP->ue_context.handover_info = CALLOC(1, sizeof(*(ue_context_pP->ue_context.handover_info))); + ue_context_pP->ue_context.Status = RRC_HO_EXECUTION; + ue_context_pP->ue_context.handover_info->state = HO_REQUEST; + /* HO Preparation message */ + msg = itti_alloc_new_message(TASK_RRC_ENB, X2AP_HANDOVER_REQ); + rrc_eNB_generate_HandoverPreparationInformation( + ue_context_pP, + X2AP_HANDOVER_REQ(msg).rrc_buffer, + &X2AP_HANDOVER_REQ(msg).rrc_buffer_size); + X2AP_HANDOVER_REQ(msg).rnti = ctxt_pP->rnti; + X2AP_HANDOVER_REQ(msg).target_physCellId = target_cell_id; + X2AP_HANDOVER_REQ(msg).ue_gummei.mcc = ue_context_pP->ue_context.ue_gummei.mcc; + X2AP_HANDOVER_REQ(msg).ue_gummei.mnc = ue_context_pP->ue_context.ue_gummei.mnc; + X2AP_HANDOVER_REQ(msg).ue_gummei.mnc_len = ue_context_pP->ue_context.ue_gummei.mnc_len; + X2AP_HANDOVER_REQ(msg).ue_gummei.mme_code = ue_context_pP->ue_context.ue_gummei.mme_code; + X2AP_HANDOVER_REQ(msg).ue_gummei.mme_group_id = ue_context_pP->ue_context.ue_gummei.mme_group_id; + // Don't know how to get this ID? + X2AP_HANDOVER_REQ(msg).mme_ue_s1ap_id = ue_context_pP->ue_context.mme_ue_s1ap_id; + X2AP_HANDOVER_REQ(msg).security_capabilities = ue_context_pP->ue_context.security_capabilities; + // compute keNB* + earfcn_dl = (uint32_t)to_earfcn_DL(RC.rrc[ctxt_pP->module_id]->carrier[0].eutra_band, RC.rrc[ctxt_pP->module_id]->carrier[0].dl_CarrierFreq, + RC.rrc[ctxt_pP->module_id]->carrier[0].N_RB_DL); + derive_keNB_star(ue_context_pP->ue_context.kenb, X2AP_HANDOVER_REQ(msg).target_physCellId, earfcn_dl, true, KeNB_star); + memcpy(X2AP_HANDOVER_REQ(msg).kenb, KeNB_star, 32); + X2AP_HANDOVER_REQ(msg).kenb_ncc = ue_context_pP->ue_context.kenb_ncc; + //X2AP_HANDOVER_REQ(msg).ue_ambr=ue_context_pP->ue_context.ue_ambr; + X2AP_HANDOVER_REQ(msg).nb_e_rabs_tobesetup = ue_context_pP->ue_context.setup_e_rabs; + + for (int i=0; iue_context.setup_e_rabs; i++) { + X2AP_HANDOVER_REQ(msg).e_rabs_tobesetup[i].e_rab_id = ue_context_pP->ue_context.e_rab[i].param.e_rab_id; + X2AP_HANDOVER_REQ(msg).e_rabs_tobesetup[i].eNB_addr = ue_context_pP->ue_context.e_rab[i].param.sgw_addr; + X2AP_HANDOVER_REQ(msg).e_rabs_tobesetup[i].gtp_teid = ue_context_pP->ue_context.e_rab[i].param.gtp_teid; + X2AP_HANDOVER_REQ(msg).e_rab_param[i].qos.qci = ue_context_pP->ue_context.e_rab[i].param.qos.qci; + X2AP_HANDOVER_REQ(msg).e_rab_param[i].qos.allocation_retention_priority.priority_level = ue_context_pP->ue_context.e_rab[i].param.qos.allocation_retention_priority.priority_level; + X2AP_HANDOVER_REQ(msg).e_rab_param[i].qos.allocation_retention_priority.pre_emp_capability = ue_context_pP->ue_context.e_rab[i].param.qos.allocation_retention_priority.pre_emp_capability; + X2AP_HANDOVER_REQ(msg).e_rab_param[i].qos.allocation_retention_priority.pre_emp_vulnerability = ue_context_pP->ue_context.e_rab[i].param.qos.allocation_retention_priority.pre_emp_vulnerability; + } + + /* TODO: don't do that, X2AP should find the target by itself */ + //X2AP_HANDOVER_REQ(msg).target_mod_id = 0; + LOG_I(RRC, + "[eNB %d] Frame %d: potential handover preparation: store the information in an intermediate structure in case of failure\n", + ctxt_pP->module_id, ctxt_pP->frame); + itti_send_msg_to_task(TASK_X2AP, ENB_MODULE_ID_TO_INSTANCE(ctxt_pP->module_id), msg); + } else { + LOG_D(RRC, "[eNB %d] Frame %d: Ignoring MeasReport from UE %x as Handover is in progress... \n", ctxt_pP->module_id, ctxt_pP->frame, + ctxt_pP->rnti); + } + + return 0; +} + void check_handovers( protocol_ctxt_t *const ctxt_pP diff --git a/openair2/RRC/LTE/rrc_proto.h b/openair2/RRC/LTE/rrc_proto.h index 8aa0125c0e..e7e5e71d80 100644 --- a/openair2/RRC/LTE/rrc_proto.h +++ b/openair2/RRC/LTE/rrc_proto.h @@ -612,6 +612,12 @@ rrc_eNB_generate_HandoverPreparationInformation( //LTE_PhysCellId_t targetPhyId ); +int +flexran_rrc_eNB_trigger_handover (int mod_id, + const protocol_ctxt_t *const ctxt_pP, + rrc_eNB_ue_context_t *ue_context_pP, + int target_cell_id); + void check_handovers( protocol_ctxt_t *const ctxt_pP From 75e3622daf7a24367ffaf20bd1cf174f62a8ba25 Mon Sep 17 00:00:00 2001 From: Konstantinos Alexandris Date: Thu, 23 May 2019 19:02:10 +0200 Subject: [PATCH 17/32] Configure eNB for X2 handover controlled by network (ignore UE HO request) --- .../ENB_APP/CONTROL_MODULES/RRC/flexran_agent_rrc.c | 3 +++ openair2/ENB_APP/MESSAGES/V2/config_messages.proto | 1 + openair2/ENB_APP/flexran_agent_common.c | 6 ++++++ openair2/ENB_APP/flexran_agent_ran_api.c | 12 ++++++++++++ openair2/ENB_APP/flexran_agent_ran_api.h | 6 ++++++ openair2/RRC/LTE/rrc_defs.h | 3 +++ openair2/RRC/LTE/rrc_eNB.c | 3 +++ 7 files changed, 34 insertions(+) diff --git a/openair2/ENB_APP/CONTROL_MODULES/RRC/flexran_agent_rrc.c b/openair2/ENB_APP/CONTROL_MODULES/RRC/flexran_agent_rrc.c index 32038ee153..7e6d83f748 100644 --- a/openair2/ENB_APP/CONTROL_MODULES/RRC/flexran_agent_rrc.c +++ b/openair2/ENB_APP/CONTROL_MODULES/RRC/flexran_agent_rrc.c @@ -832,6 +832,9 @@ void flexran_agent_fill_rrc_cell_config(mid_t mod_id, uint8_t cc_id, } else { conf->n_plmn_id = 0; } + + conf->x2_ho_net_control = flexran_get_x2_ho_net_control(mod_id); + conf->has_x2_ho_net_control = 1; } int flexran_agent_unregister_rrc_xface(mid_t mod_id) diff --git a/openair2/ENB_APP/MESSAGES/V2/config_messages.proto b/openair2/ENB_APP/MESSAGES/V2/config_messages.proto index c339ad0bf6..6d24e5a0ac 100644 --- a/openair2/ENB_APP/MESSAGES/V2/config_messages.proto +++ b/openair2/ENB_APP/MESSAGES/V2/config_messages.proto @@ -45,6 +45,7 @@ message flex_cell_config { repeated flex_plmn plmn_id = 40; // The PLMN cell id of this cell optional flex_slice_config slice_config = 42; + optional bool x2_ho_net_control = 43; } message flex_slice_config { diff --git a/openair2/ENB_APP/flexran_agent_common.c b/openair2/ENB_APP/flexran_agent_common.c index 757a796233..d3c0a89182 100644 --- a/openair2/ENB_APP/flexran_agent_common.c +++ b/openair2/ENB_APP/flexran_agent_common.c @@ -914,6 +914,12 @@ int flexran_agent_handle_enb_config_reply(mid_t mod_id, const void *params, Prot // initiate_soft_restart(mod_id, enb_config->cell_config[0]); } + if (flexran_agent_get_rrc_xface(mod_id) && enb_config->cell_config[0]->has_x2_ho_net_control) { + if (flexran_set_x2_ho_net_control(mod_id, enb_config->cell_config[0]->x2_ho_net_control) < 0) { + LOG_E(FLEXRAN_AGENT, "Error in configuring X2 handover controlled by network"); + } + } + *msg = NULL; return 0; } diff --git a/openair2/ENB_APP/flexran_agent_ran_api.c b/openair2/ENB_APP/flexran_agent_ran_api.c index cd91e73a7c..1465f46854 100644 --- a/openair2/ENB_APP/flexran_agent_ran_api.c +++ b/openair2/ENB_APP/flexran_agent_ran_api.c @@ -2082,6 +2082,18 @@ int flexran_set_rrc_a3_event_reportOnLeave(mid_t mod_id, rnti_t rnti, int report return 0; } +int flexran_set_x2_ho_net_control(mid_t mod_id, int x2_ho_net_control) { + if (!rrc_is_present(mod_id)) return -1; + if (!((x2_ho_net_control == 0) || (x2_ho_net_control == 1))) return -1; + RC.rrc[mod_id]->x2_ho_net_control = x2_ho_net_control; + return 0; +} + +int flexran_get_x2_ho_net_control(mid_t mod_id) { + if (!rrc_is_present(mod_id)) return -1; + return RC.rrc[mod_id]->x2_ho_net_control; +} + uint8_t flexran_get_rrc_num_plmn_ids(mid_t mod_id) { if (!rrc_is_present(mod_id)) return 0; return RC.rrc[mod_id]->configuration.num_plmn; diff --git a/openair2/ENB_APP/flexran_agent_ran_api.h b/openair2/ENB_APP/flexran_agent_ran_api.h index d3229bd462..7dd6b69b61 100644 --- a/openair2/ENB_APP/flexran_agent_ran_api.h +++ b/openair2/ENB_APP/flexran_agent_ran_api.h @@ -630,6 +630,12 @@ uint16_t flexran_get_rrc_mnc(mid_t mod_id, uint8_t index); /* Get index'th MNC's digit length broadcasted in SIB1 */ uint8_t flexran_get_rrc_mnc_digit_length(mid_t mod_id, uint8_t index); +/* Get X2 handover controlled by network */ +int flexran_get_x2_ho_net_control(mid_t mod_id); + +/* Set X2 handover controlled by network */ +int flexran_set_x2_ho_net_control(mid_t mod_id, int x2_ho_net_control); + /* Get number of adjacent cells via X2 interface */ int flexran_get_rrc_num_adj_cells(mid_t mod_id); /************************** Slice configuration **************************/ diff --git a/openair2/RRC/LTE/rrc_defs.h b/openair2/RRC/LTE/rrc_defs.h index 21feaf5e4c..ef0598a40a 100644 --- a/openair2/RRC/LTE/rrc_defs.h +++ b/openair2/RRC/LTE/rrc_defs.h @@ -826,6 +826,9 @@ typedef struct eNB_RRC_INST_s { /// NR cell id uint64_t nr_cellid; + // X2 handover controlled by network + int x2_ho_net_control; + // Neighborouring cells id int num_neigh_cells; int num_neigh_cells_cc[MAX_NUM_CCs]; diff --git a/openair2/RRC/LTE/rrc_eNB.c b/openair2/RRC/LTE/rrc_eNB.c index fd308caebe..58f5ed53a7 100644 --- a/openair2/RRC/LTE/rrc_eNB.c +++ b/openair2/RRC/LTE/rrc_eNB.c @@ -4515,6 +4515,9 @@ rrc_eNB_process_MeasurementReport( if (!RC.rrc[ENB_INSTANCE_TO_MODULE_ID(ctxt_pP->instance)]->configuration.enable_x2) return; + if (RC.rrc[ctxt_pP->module_id]->x2_ho_net_control) + return; + LOG_D(RRC, "A3 event is triggered...\n"); /* if the UE is not in handover mode, start handover procedure */ From 67fc2f7c621b303918a1e98f871c5f72cb901be7 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Thu, 6 Jun 2019 15:09:12 +0200 Subject: [PATCH 18/32] FlexRAN: add GTP statistics in UE stats through RRC module --- .../CONTROL_MODULES/RRC/flexran_agent_rrc.c | 73 +++++++++++++++++++ .../CONTROL_MODULES/RRC/flexran_agent_rrc.h | 5 ++ .../ENB_APP/MESSAGES/V2/stats_common.proto | 12 +++ .../ENB_APP/MESSAGES/V2/stats_messages.proto | 2 + openair2/ENB_APP/flexran_agent_handler.c | 8 +- openair2/ENB_APP/flexran_agent_ran_api.c | 28 +++++++ openair2/ENB_APP/flexran_agent_ran_api.h | 13 ++++ 7 files changed, 140 insertions(+), 1 deletion(-) diff --git a/openair2/ENB_APP/CONTROL_MODULES/RRC/flexran_agent_rrc.c b/openair2/ENB_APP/CONTROL_MODULES/RRC/flexran_agent_rrc.c index 7e6d83f748..1feafd9954 100644 --- a/openair2/ENB_APP/CONTROL_MODULES/RRC/flexran_agent_rrc.c +++ b/openair2/ENB_APP/CONTROL_MODULES/RRC/flexran_agent_rrc.c @@ -573,6 +573,79 @@ int flexran_agent_rrc_destroy_stats_reply(Protocol__FlexStatsReply *reply) return 0; } +int flexran_agent_rrc_gtp_stats_reply(mid_t mod_id, + const report_config_t *report_config, + Protocol__FlexUeStatsReport **ue_report, + Protocol__FlexCellStatsReport **cell_report) { + /* This function fills the GTP part of the statistics. The necessary + * information is, for our purposes, completely maintained in the RRC layer. + * It would be possible to add a GTP module that handles this, though. */ + if (report_config->nr_ue > 0) { + rnti_t rntis[report_config->nr_ue]; + flexran_get_rrc_rnti_list(mod_id, rntis, report_config->nr_ue); + for (int i = 0; i < report_config->nr_ue; i++) { + const rnti_t rnti = rntis[i]; + + /* Check flag for creation of buffer status report */ + if (report_config->ue_report_type[i].ue_report_flags & PROTOCOL__FLEX_UE_STATS_TYPE__FLUST_GTP_STATS) { + + /* get number of rabs for this UE */ + const int num_e_rab = flexran_agent_rrc_gtp_num_e_rab(mod_id, rnti); + Protocol__FlexGtpStats **gtp_stats = NULL; + if (num_e_rab > 0) { + gtp_stats = calloc(num_e_rab, sizeof(Protocol__FlexGtpStats *)); + if (!gtp_stats) goto error; + for (int r = 0; r < num_e_rab; ++r) { + gtp_stats[r] = malloc(sizeof(Protocol__FlexGtpStats)); + if (!gtp_stats[r]) goto error; + protocol__flex_gtp_stats__init(gtp_stats[r]); + gtp_stats[r]->e_rab_id = flexran_agent_rrc_gtp_get_e_rab_id(mod_id, rnti, r); + gtp_stats[r]->has_e_rab_id = 1; + gtp_stats[r]->teid_enb = flexran_agent_rrc_gtp_get_teid_enb(mod_id, rnti, r); + gtp_stats[r]->has_teid_enb = 1; + gtp_stats[r]->addr_enb = NULL; + gtp_stats[r]->teid_sgw = flexran_agent_rrc_gtp_get_teid_sgw(mod_id, rnti, r); + gtp_stats[r]->has_teid_sgw = 1; + gtp_stats[r]->addr_sgw = NULL; + } + } + ue_report[i]->n_gtp_stats = num_e_rab; + ue_report[i]->gtp_stats = gtp_stats; + ue_report[i]->flags |= PROTOCOL__FLEX_UE_STATS_TYPE__FLUST_GTP_STATS; + } + } + } + return 0; +error: + for (int i = 0; i < report_config->nr_ue; i++) { + if (!ue_report[i]->gtp_stats) continue; + for (int r = 0; r < ue_report[i]->n_gtp_stats; ++r) { + if (ue_report[i]->gtp_stats[r]) { + free(ue_report[i]->gtp_stats[r]); + ue_report[i]->gtp_stats[r] = NULL; + } + } + free(ue_report[i]->gtp_stats); + ue_report[i]->gtp_stats = NULL; + } + return -1; +} + +int flexran_agent_rrc_gtp_destroy_stats_reply(Protocol__FlexStatsReply *reply) { + for (int i = 0; i < reply->n_ue_report; ++i) { + if (!reply->ue_report[i]->n_gtp_stats == 0) continue; + + for (int r = 0; r < reply->ue_report[i]->n_gtp_stats; ++r) { + //if (reply->ue_report[i]->gtp_stats[r]->addr_enb) + // free(reply->ue_report[i]->gtp_stats[r]->addr_enb); + //if (reply->ue_report[i]->gtp_stats[r]->addr_sgw) + // free(reply->ue_report[i]->gtp_stats[r]->addr_sgw); + free(reply->ue_report[i]->gtp_stats[r]); + } + } + return 0; +} + void flexran_agent_fill_rrc_ue_config(mid_t mod_id, rnti_t rnti, Protocol__FlexUeConfig *ue_conf) { diff --git a/openair2/ENB_APP/CONTROL_MODULES/RRC/flexran_agent_rrc.h b/openair2/ENB_APP/CONTROL_MODULES/RRC/flexran_agent_rrc.h index 4b9cec8614..fdf00ff841 100644 --- a/openair2/ENB_APP/CONTROL_MODULES/RRC/flexran_agent_rrc.h +++ b/openair2/ENB_APP/CONTROL_MODULES/RRC/flexran_agent_rrc.h @@ -60,6 +60,11 @@ void flexran_trigger_rrc_measurements (mid_t mod_id, LTE_MeasResults_t *); int flexran_agent_rrc_stats_reply(mid_t mod_id, const report_config_t *report_config, Protocol__FlexUeStatsReport **ue_report, Protocol__FlexCellStatsReport **cell_report); int flexran_agent_rrc_destroy_stats_reply(Protocol__FlexStatsReply *reply); +/* Statistic reply for GTP statistics which OAI stores also in the RRC layer. + * This might be moved to a separate GTP module in the future */ +int flexran_agent_rrc_gtp_stats_reply(mid_t mod_id, const report_config_t *report_config, Protocol__FlexUeStatsReport **ue_report, Protocol__FlexCellStatsReport **cell_report); +int flexran_agent_rrc_gtp_destroy_stats_reply(Protocol__FlexStatsReply *reply); + /* Fill the RRC part of a ue_config message */ void flexran_agent_fill_rrc_ue_config(mid_t mod_id, rnti_t rnti, Protocol__FlexUeConfig *ue_conf); diff --git a/openair2/ENB_APP/MESSAGES/V2/stats_common.proto b/openair2/ENB_APP/MESSAGES/V2/stats_common.proto index ee286981f5..b56ad8eea1 100644 --- a/openair2/ENB_APP/MESSAGES/V2/stats_common.proto +++ b/openair2/ENB_APP/MESSAGES/V2/stats_common.proto @@ -305,3 +305,15 @@ message flex_mac_sdus_dl { optional uint32 sdu_length = 1; optional uint32 lcid = 2; } + +// +// GTP stats +// + +message flex_gtp_stats { + optional uint32 e_rab_id = 1; + optional uint32 teid_enb = 2; + optional string addr_enb = 3; + optional uint32 teid_sgw = 4; + optional string addr_sgw = 5; +} diff --git a/openair2/ENB_APP/MESSAGES/V2/stats_messages.proto b/openair2/ENB_APP/MESSAGES/V2/stats_messages.proto index 8eb6510de3..7cceb04a01 100644 --- a/openair2/ENB_APP/MESSAGES/V2/stats_messages.proto +++ b/openair2/ENB_APP/MESSAGES/V2/stats_messages.proto @@ -50,6 +50,7 @@ message flex_ue_stats_report { optional flex_rrc_measurements rrc_measurements = 10; optional flex_pdcp_stats pdcp_stats = 11; optional flex_mac_stats mac_stats = 12; + repeated flex_gtp_stats gtp_stats = 13; } // @@ -89,6 +90,7 @@ enum flex_ue_stats_type { FLUST_MAC_STATS = 128; FLUST_PDCP_STATS = 1024; + FLUST_GTP_STATS = 2048; FLUST_RRC_MEASUREMENTS = 65536; // To be extended with more types of stats diff --git a/openair2/ENB_APP/flexran_agent_handler.c b/openair2/ENB_APP/flexran_agent_handler.c index 65663e20a8..e089675b62 100644 --- a/openair2/ENB_APP/flexran_agent_handler.c +++ b/openair2/ENB_APP/flexran_agent_handler.c @@ -511,7 +511,13 @@ int flexran_agent_stats_reply(mid_t enb_id, xid_t xid, const report_config_t *re goto error; } - + /* GTP reply split, currently performed through RRC module */ + if (flexran_agent_get_rrc_xface(enb_id) + && flexran_agent_rrc_gtp_stats_reply(enb_id, report_config, ue_report, cell_report) < 0) { + err_code = PROTOCOL__FLEXRAN_ERR__MSG_BUILD; + goto error; + } + stats_reply_msg->cell_report = cell_report; stats_reply_msg->ue_report = ue_report; diff --git a/openair2/ENB_APP/flexran_agent_ran_api.c b/openair2/ENB_APP/flexran_agent_ran_api.c index 1465f46854..9f08623aa8 100644 --- a/openair2/ENB_APP/flexran_agent_ran_api.c +++ b/openair2/ENB_APP/flexran_agent_ran_api.c @@ -2119,6 +2119,34 @@ int flexran_get_rrc_num_adj_cells(mid_t mod_id) { return RC.rrc[mod_id]->num_neigh_cells; } +int flexran_agent_rrc_gtp_num_e_rab(mid_t mod_id, rnti_t rnti) { + if (!rrc_is_present(mod_id)) return 0; + struct rrc_eNB_ue_context_s* ue_context_p = rrc_eNB_get_ue_context(RC.rrc[mod_id], rnti); + if (!ue_context_p) return 0; + return ue_context_p->ue_context.setup_e_rabs; +} + +int flexran_agent_rrc_gtp_get_e_rab_id(mid_t mod_id, rnti_t rnti, int index) { + if (!rrc_is_present(mod_id)) return 0; + struct rrc_eNB_ue_context_s* ue_context_p = rrc_eNB_get_ue_context(RC.rrc[mod_id], rnti); + if (!ue_context_p) return 0; + return ue_context_p->ue_context.e_rab[index].param.e_rab_id; +} + +int flexran_agent_rrc_gtp_get_teid_enb(mid_t mod_id, rnti_t rnti, int index) { + if (!rrc_is_present(mod_id)) return 0; + struct rrc_eNB_ue_context_s* ue_context_p = rrc_eNB_get_ue_context(RC.rrc[mod_id], rnti); + if (!ue_context_p) return 0; + return ue_context_p->ue_context.enb_gtp_teid[index]; +} + +int flexran_agent_rrc_gtp_get_teid_sgw(mid_t mod_id, rnti_t rnti, int index) { + if (!rrc_is_present(mod_id)) return 0; + struct rrc_eNB_ue_context_s* ue_context_p = rrc_eNB_get_ue_context(RC.rrc[mod_id], rnti); + if (!ue_context_p) return 0; + return ue_context_p->ue_context.e_rab[index].param.gtp_teid; +} + /**************************** SLICING ****************************/ int flexran_get_ue_dl_slice_id(mid_t mod_id, mid_t ue_id) { diff --git a/openair2/ENB_APP/flexran_agent_ran_api.h b/openair2/ENB_APP/flexran_agent_ran_api.h index 7dd6b69b61..e18c55c4bf 100644 --- a/openair2/ENB_APP/flexran_agent_ran_api.h +++ b/openair2/ENB_APP/flexran_agent_ran_api.h @@ -638,6 +638,19 @@ int flexran_set_x2_ho_net_control(mid_t mod_id, int x2_ho_net_control); /* Get number of adjacent cells via X2 interface */ int flexran_get_rrc_num_adj_cells(mid_t mod_id); + +/* Get the number of E-RABs for UE */ +int flexran_agent_rrc_gtp_num_e_rab(mid_t mod_id, rnti_t rnti); + +/* Get the e-RAB ID for UE */ +int flexran_agent_rrc_gtp_get_e_rab_id(mid_t mod_id, rnti_t rnti, int index); + +/* Get the TEID at the eNB for UE */ +int flexran_agent_rrc_gtp_get_teid_enb(mid_t mod_id, rnti_t rnti, int index); + +/* Get the TEID at the SGW for UE */ +int flexran_agent_rrc_gtp_get_teid_sgw(mid_t mod_id, rnti_t rnti, int index); + /************************** Slice configuration **************************/ /* Get the DL slice ID for a UE */ From a90a7f352e87ae5d4aa89f86ae5ba2f8adb0ed85 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Fri, 7 Jun 2019 16:44:10 +0200 Subject: [PATCH 19/32] Additional messages for error diagnosis for net-ctrld HO --- openair2/ENB_APP/flexran_agent_common.c | 2 +- openair2/RRC/LTE/rrc_eNB.c | 8 ++++++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/openair2/ENB_APP/flexran_agent_common.c b/openair2/ENB_APP/flexran_agent_common.c index d3c0a89182..ac18f16069 100644 --- a/openair2/ENB_APP/flexran_agent_common.c +++ b/openair2/ENB_APP/flexran_agent_common.c @@ -871,7 +871,7 @@ int flexran_agent_rrc_trigger_handover(mid_t mod_id, const void *params, Protoco rnti_found = 1; // Call the proper wrapper in FlexRAN API if (flexran_call_rrc_trigger_handover(mod_id, ho_command->rnti, ho_command->target_phy_cell_id) < 0) { - LOG_E(FLEXRAN_AGENT, "Error in handovering user %d\n", i); + LOG_E(FLEXRAN_AGENT, "Error in handovering user %d/RNTI %x\n", i, rnti); } break; } diff --git a/openair2/RRC/LTE/rrc_eNB.c b/openair2/RRC/LTE/rrc_eNB.c index 58f5ed53a7..c4979051af 100644 --- a/openair2/RRC/LTE/rrc_eNB.c +++ b/openair2/RRC/LTE/rrc_eNB.c @@ -4842,14 +4842,18 @@ int cell_found = 0; /* Check if eNB id was found */ - if (!cell_found) + if (!cell_found) { + LOG_E(RRC, "%s(): cannot find target eNB with phyCellId %d\n", __func__, target_cell_id); return -1; + } /* Handover process is following */ /* if X2AP is disabled, do nothing */ - if (!is_x2ap_enabled()) + if (!is_x2ap_enabled()) { + LOG_E(RRC, "X2 is disabled\n"); return -1; + } LOG_D(RRC, "Handover is triggered by FlexRAN controller...\n"); From 960e8dc9d85dc8b802cdcb1464ed278264e6e1a7 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Tue, 11 Jun 2019 15:59:47 +0200 Subject: [PATCH 20/32] FlexRAN: Calculate sfnsn such that diff 1s = 1000 --- openair2/ENB_APP/flexran_agent_ran_api.c | 13 ++----------- openair2/ENB_APP/flexran_agent_ran_api.h | 2 +- 2 files changed, 3 insertions(+), 12 deletions(-) diff --git a/openair2/ENB_APP/flexran_agent_ran_api.c b/openair2/ENB_APP/flexran_agent_ran_api.c index 9f08623aa8..bb81c2c2d2 100644 --- a/openair2/ENB_APP/flexran_agent_ran_api.c +++ b/openair2/ENB_APP/flexran_agent_ran_api.c @@ -71,19 +71,10 @@ sub_frame_t flexran_get_current_subframe(mid_t mod_id) return RC.mac[mod_id]->subframe; } -/* Why uint16_t, frame_t and sub_frame_t are defined as uint32_t? */ -uint16_t flexran_get_sfn_sf(mid_t mod_id) +uint32_t flexran_get_sfn_sf(mid_t mod_id) { if (!mac_is_present(mod_id)) return 0; - frame_t frame = flexran_get_current_system_frame_num(mod_id); - sub_frame_t subframe = flexran_get_current_subframe(mod_id); - uint16_t sfn_sf, frame_mask, sf_mask; - - frame_mask = (1 << 12) - 1; - sf_mask = (1 << 4) - 1; - sfn_sf = (subframe & sf_mask) | ((frame & frame_mask) << 4); - - return sfn_sf; + return flexran_get_current_frame(mod_id) * 10 + flexran_get_current_subframe(mod_id); } uint16_t flexran_get_future_sfn_sf(mid_t mod_id, int ahead_of_time) diff --git a/openair2/ENB_APP/flexran_agent_ran_api.h b/openair2/ENB_APP/flexran_agent_ran_api.h index e18c55c4bf..f9d0d97405 100644 --- a/openair2/ENB_APP/flexran_agent_ran_api.h +++ b/openair2/ENB_APP/flexran_agent_ran_api.h @@ -63,7 +63,7 @@ sub_frame_t flexran_get_current_subframe(mid_t mod_id); /*Return the frame and subframe number in compact 16-bit format. Bits 0-3 subframe, rest for frame. Required by FlexRAN protocol*/ -uint16_t flexran_get_sfn_sf(mid_t mod_id); +uint32_t flexran_get_sfn_sf(mid_t mod_id); /* Return a future frame and subframe number that is ahead_of_time subframes later in compact 16-bit format. Bits 0-3 subframe, From a6be54a6f45d81d6a041c2e0e2d47a59d821421b Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Mon, 24 Jun 2019 17:54:38 +0200 Subject: [PATCH 21/32] Fix: X2 Setup Req/Resp: first check, then increase number of cells --- openair2/RRC/LTE/rrc_eNB.c | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/openair2/RRC/LTE/rrc_eNB.c b/openair2/RRC/LTE/rrc_eNB.c index c4979051af..f9831490e7 100644 --- a/openair2/RRC/LTE/rrc_eNB.c +++ b/openair2/RRC/LTE/rrc_eNB.c @@ -4592,9 +4592,6 @@ rrc_eNB_generate_HandoverPreparationInformation( } void rrc_eNB_process_x2_setup_request(int mod_id, x2ap_setup_req_t *m) { - - RC.rrc[mod_id]->num_neigh_cells ++; - if (RC.rrc[mod_id]->num_neigh_cells > MAX_NUM_NEIGH_CELLs) { LOG_E(RRC, "Error: number of neighbouring cells is exceeded \n"); return; @@ -4605,18 +4602,14 @@ void rrc_eNB_process_x2_setup_request(int mod_id, x2ap_setup_req_t *m) { return; } + RC.rrc[mod_id]->num_neigh_cells++; RC.rrc[mod_id]->num_neigh_cells_cc[RC.rrc[mod_id]->num_neigh_cells-1] = m->num_cc; - for (int i=0; inum_cc; i++) { RC.rrc[mod_id]->neigh_cells_id[RC.rrc[mod_id]->num_neigh_cells-1][i] = m->Nid_cell[i]; } - } void rrc_eNB_process_x2_setup_response(int mod_id, x2ap_setup_resp_t *m) { - - RC.rrc[mod_id]->num_neigh_cells ++; - if (RC.rrc[mod_id]->num_neigh_cells > MAX_NUM_NEIGH_CELLs) { LOG_E(RRC, "Error: number of neighbouring cells is exceeded \n"); return; @@ -4627,12 +4620,11 @@ void rrc_eNB_process_x2_setup_response(int mod_id, x2ap_setup_resp_t *m) { return; } + RC.rrc[mod_id]->num_neigh_cells++; RC.rrc[mod_id]->num_neigh_cells_cc[RC.rrc[mod_id]->num_neigh_cells-1] = m->num_cc; - for (int i=0; inum_cc; i++) { RC.rrc[mod_id]->neigh_cells_id[RC.rrc[mod_id]->num_neigh_cells-1][i] = m->Nid_cell[i]; } - } void rrc_eNB_process_handoverPreparationInformation(int mod_id, x2ap_handover_req_t *m) { From f1a1ff036d872cf5321313efa1ee9e413f5dbfea Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Mon, 24 Jun 2019 17:55:13 +0200 Subject: [PATCH 22/32] FlexRAN: HO request first check whether X2 is active, minor indentation fixes --- openair2/RRC/LTE/rrc_eNB.c | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/openair2/RRC/LTE/rrc_eNB.c b/openair2/RRC/LTE/rrc_eNB.c index f9831490e7..34195ec0d2 100644 --- a/openair2/RRC/LTE/rrc_eNB.c +++ b/openair2/RRC/LTE/rrc_eNB.c @@ -4819,12 +4819,17 @@ flexran_rrc_eNB_trigger_handover (int mod_id, rrc_eNB_ue_context_t *ue_context_pP, int target_cell_id) { -uint32_t earfcn_dl; -uint8_t KeNB_star[32] = { 0 }; -int cell_found = 0; + uint32_t earfcn_dl; + uint8_t KeNB_star[32] = { 0 }; + int cell_found = 0; + + /* if X2AP is disabled, do nothing */ + if (!is_x2ap_enabled()) { + LOG_E(RRC, "X2 is disabled\n"); + return -1; + } /* Check if eNB id belongs to the supported ones-Extend for multiple carrieres */ - for (int i=0; i < RC.rrc[mod_id]->num_neigh_cells; i++) { if (RC.rrc[mod_id]->neigh_cells_id[i][0] == target_cell_id) { cell_found = 1; @@ -4833,20 +4838,12 @@ int cell_found = 0; } /* Check if eNB id was found */ - if (!cell_found) { LOG_E(RRC, "%s(): cannot find target eNB with phyCellId %d\n", __func__, target_cell_id); return -1; } /* Handover process is following */ - - /* if X2AP is disabled, do nothing */ - if (!is_x2ap_enabled()) { - LOG_E(RRC, "X2 is disabled\n"); - return -1; - } - LOG_D(RRC, "Handover is triggered by FlexRAN controller...\n"); /* if the UE is not in handover mode, start handover procedure */ From 0f568fd40ae195f47baa5ebfd35c05226674a371 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Tue, 25 Jun 2019 10:40:12 +0200 Subject: [PATCH 23/32] FlexRAN: Comment non-functional code regarding Neigh CGI PLMN ID reporting --- .../CONTROL_MODULES/RRC/flexran_agent_rrc.c | 93 ++++++++++--------- 1 file changed, 47 insertions(+), 46 deletions(-) diff --git a/openair2/ENB_APP/CONTROL_MODULES/RRC/flexran_agent_rrc.c b/openair2/ENB_APP/CONTROL_MODULES/RRC/flexran_agent_rrc.c index 1feafd9954..6299e101a4 100644 --- a/openair2/ENB_APP/CONTROL_MODULES/RRC/flexran_agent_rrc.c +++ b/openair2/ENB_APP/CONTROL_MODULES/RRC/flexran_agent_rrc.c @@ -449,55 +449,56 @@ int flexran_agent_rrc_stats_reply(mid_t mod_id, eutra_meas[j]->phys_cell_id = flexran_get_rrc_neigh_phy_cell_id(mod_id, rnti, j); eutra_meas[j]->has_phys_cell_id = 1; - if (flexran_get_rrc_neigh_cgi(mod_id, rnti, j)) { - /* Initialize CGI measurements. */ - Protocol__FlexEutraCgiMeasurements *cgi_meas; - cgi_meas = malloc(sizeof(Protocol__FlexEutraCgiMeasurements)); + /* The following is not correctly implemented */ + //if (flexran_get_rrc_neigh_cgi(mod_id, rnti, j)) { + // /* Initialize CGI measurements. */ + // Protocol__FlexEutraCgiMeasurements *cgi_meas; + // cgi_meas = malloc(sizeof(Protocol__FlexEutraCgiMeasurements)); - if (cgi_meas) { - protocol__flex_eutra_cgi_measurements__init(cgi_meas); + // if (cgi_meas) { + // protocol__flex_eutra_cgi_measurements__init(cgi_meas); - cgi_meas->tracking_area_code = flexran_get_rrc_neigh_cgi_tac(mod_id, rnti, j); - cgi_meas->has_tracking_area_code = 1; + // cgi_meas->tracking_area_code = flexran_get_rrc_neigh_cgi_tac(mod_id, rnti, j); + // cgi_meas->has_tracking_area_code = 1; - /* EUTRA Cell Global Identity (CGI) */ - Protocol__FlexCellGlobalEutraId *cgi; - cgi = malloc(sizeof(Protocol__FlexCellGlobalEutraId)); + // /* EUTRA Cell Global Identity (CGI) */ + // Protocol__FlexCellGlobalEutraId *cgi; + // cgi = malloc(sizeof(Protocol__FlexCellGlobalEutraId)); - if (cgi) { - protocol__flex_cell_global_eutra_id__init(cgi); + // if (cgi) { + // protocol__flex_cell_global_eutra_id__init(cgi); - cgi->cell_id = flexran_get_rrc_neigh_cgi_cell_id(mod_id, rnti, j); - cgi->has_cell_id = 1; + // cgi->cell_id = flexran_get_rrc_neigh_cgi_cell_id(mod_id, rnti, j); + // cgi->has_cell_id = 1; - /* PLMN for neighbouring cell */ - Protocol__FlexPlmnIdentity *plmn_id; - plmn_id = malloc(sizeof(Protocol__FlexPlmnIdentity)); + // /* PLMN for neighbouring cell */ + // Protocol__FlexPlmnIdentity *plmn_id; + // plmn_id = malloc(sizeof(Protocol__FlexPlmnIdentity)); - if (plmn_id) { - protocol__flex_plmn_identity__init(plmn_id); + // if (plmn_id) { + // protocol__flex_plmn_identity__init(plmn_id); - plmn_id->mcc = 0; - plmn_id->n_mcc = flexran_get_rrc_neigh_cgi_num_mcc(mod_id, rnti, j); + // plmn_id->mcc = 0; + // plmn_id->n_mcc = flexran_get_rrc_neigh_cgi_num_mcc(mod_id, rnti, j); - for (int m = 0; m < plmn_id->n_mcc; m++) { - plmn_id->mcc += flexran_get_rrc_neigh_cgi_mcc(mod_id, rnti, j, m); - } + // for (int m = 0; m < plmn_id->n_mcc; m++) { + // plmn_id->mcc += flexran_get_rrc_neigh_cgi_mcc(mod_id, rnti, j, m); + // } - plmn_id->mnc = 0; - plmn_id->n_mnc = flexran_get_rrc_neigh_cgi_num_mnc(mod_id, rnti, j); + // plmn_id->mnc = 0; + // plmn_id->n_mnc = flexran_get_rrc_neigh_cgi_num_mnc(mod_id, rnti, j); - for (int m = 0; m < plmn_id->n_mnc; m++) { - plmn_id->mnc += flexran_get_rrc_neigh_cgi_mnc(mod_id, rnti, j, m); - } + // for (int m = 0; m < plmn_id->n_mnc; m++) { + // plmn_id->mnc += flexran_get_rrc_neigh_cgi_mnc(mod_id, rnti, j, m); + // } - cgi->plmn_id = plmn_id; - } - cgi_meas->cgi = cgi; - } - eutra_meas[j]->cgi_meas = cgi_meas; - } - } + // cgi->plmn_id = plmn_id; + // } + // cgi_meas->cgi = cgi; + // } + // eutra_meas[j]->cgi_meas = cgi_meas; + // } + //} /*RSRP/RSRQ of the neighbouring cell */ Protocol__FlexEutraRefSignalMeas *meas_result; @@ -551,15 +552,15 @@ int flexran_agent_rrc_destroy_stats_reply(Protocol__FlexStatsReply *reply) for (int i = 0; i < reply->n_ue_report; i++){ if (reply->ue_report[i]->rrc_measurements && reply->ue_report[i]->rrc_measurements->neigh_meas) { for (int j = 0; j < reply->ue_report[i]->rrc_measurements->neigh_meas->n_eutra_meas; j++) { - if (reply->ue_report[i]->rrc_measurements->neigh_meas->eutra_meas[j]->cgi_meas) { - if (reply->ue_report[i]->rrc_measurements->neigh_meas->eutra_meas[j]->cgi_meas->cgi) { - if (reply->ue_report[i]->rrc_measurements->neigh_meas->eutra_meas[j]->cgi_meas->plmn_id) { - free(reply->ue_report[i]->rrc_measurements->neigh_meas->eutra_meas[j]->cgi_meas->cgi->plmn_id); - } - free(reply->ue_report[i]->rrc_measurements->neigh_meas->eutra_meas[j]->cgi_meas->cgi); - } - free(reply->ue_report[i]->rrc_measurements->neigh_meas->eutra_meas[j]->cgi_meas); - } + //if (reply->ue_report[i]->rrc_measurements->neigh_meas->eutra_meas[j]->cgi_meas) { + // if (reply->ue_report[i]->rrc_measurements->neigh_meas->eutra_meas[j]->cgi_meas->cgi) { + // if (reply->ue_report[i]->rrc_measurements->neigh_meas->eutra_meas[j]->cgi_meas->plmn_id) { + // free(reply->ue_report[i]->rrc_measurements->neigh_meas->eutra_meas[j]->cgi_meas->cgi->plmn_id); + // } + // free(reply->ue_report[i]->rrc_measurements->neigh_meas->eutra_meas[j]->cgi_meas->cgi); + // } + // free(reply->ue_report[i]->rrc_measurements->neigh_meas->eutra_meas[j]->cgi_meas); + //} if (reply->ue_report[i]->rrc_measurements->neigh_meas->eutra_meas[j]->meas_result) { free(reply->ue_report[i]->rrc_measurements->neigh_meas->eutra_meas[j]->meas_result); } From 5b12a609505ab654132cd74f67695f9ebe62fd47 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Tue, 25 Jun 2019 15:47:52 +0200 Subject: [PATCH 24/32] Flexran-triggered RRC Reconf: free memory of mac_MainConfig after setting new, do not free new memory --- openair2/RRC/LTE/rrc_eNB.c | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/openair2/RRC/LTE/rrc_eNB.c b/openair2/RRC/LTE/rrc_eNB.c index 34195ec0d2..9238e634dd 100644 --- a/openair2/RRC/LTE/rrc_eNB.c +++ b/openair2/RRC/LTE/rrc_eNB.c @@ -3836,7 +3836,6 @@ flexran_rrc_eNB_generate_defaultRRCConnectionReconfiguration(const protocol_ctxt /* MAC Main Config */ // The different parts of MAC main config are set below mac_MainConfig = CALLOC(1, sizeof(*mac_MainConfig)); - ue_context_pP->ue_context.mac_MainConfig = mac_MainConfig; mac_MainConfig->ul_SCH_Config = CALLOC(1, sizeof(*mac_MainConfig->ul_SCH_Config)); maxHARQ_Tx = CALLOC(1, sizeof(long)); *maxHARQ_Tx = LTE_MAC_MainConfig__ul_SCH_Config__maxHARQ_Tx_n5; @@ -3904,6 +3903,21 @@ flexran_rrc_eNB_generate_defaultRRCConnectionReconfiguration(const protocol_ctxt mac_MainConfig->ext1->sr_ProhibitTimer_r9 = sr_ProhibitTimer_r9; #endif + // free the old LTE_MAC_MainConfig_t: get a pointer to "old" memory, assign + // the new values in the ue_context, then free it + // Note: can not completely avoid race condition with FlexRAN + LTE_MAC_MainConfig_t *old_mac_MainConfig = ue_context_pP->ue_context.mac_MainConfig; + ue_context_pP->ue_context.mac_MainConfig = mac_MainConfig; + free(old_mac_MainConfig->ul_SCH_Config->periodicBSR_Timer); + free(old_mac_MainConfig->ul_SCH_Config->maxHARQ_Tx); + free(old_mac_MainConfig->ul_SCH_Config); + free(old_mac_MainConfig->phr_Config); +#if (LTE_RRC_VERSION >= MAKE_VERSION(9, 0, 0)) + free(old_mac_MainConfig->ext1->sr_ProhibitTimer_r9); + free(old_mac_MainConfig->ext1); +#endif + free(old_mac_MainConfig); + // change the transmission mode for the primary component carrier // TODO: add codebook subset restriction here // TODO: change TM for secondary CC in SCelltoaddmodlist @@ -4308,15 +4322,6 @@ flexran_rrc_eNB_generate_defaultRRCConnectionReconfiguration(const protocol_ctxt free(quantityConfig); quantityConfig = NULL; - - free(mac_MainConfig->ul_SCH_Config); - mac_MainConfig->ul_SCH_Config = NULL; - - free(mac_MainConfig->phr_Config); - mac_MainConfig->phr_Config = NULL; - - free(mac_MainConfig); - mac_MainConfig = NULL; } //----------------------------------------------------------------------------- From 175da6f258a67cbbc1238cd050fd69e92e7b2e67 Mon Sep 17 00:00:00 2001 From: Cedric Roux Date: Thu, 27 Jun 2019 12:19:39 +0200 Subject: [PATCH 25/32] minor: fix parameters to T call for T_ENB_MASTER_TICK --- targets/RT/USER/lte-enb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/targets/RT/USER/lte-enb.c b/targets/RT/USER/lte-enb.c index 2cf2b7b505..89a82604ca 100644 --- a/targets/RT/USER/lte-enb.c +++ b/targets/RT/USER/lte-enb.c @@ -458,7 +458,7 @@ void eNB_top(PHY_VARS_eNB *eNB, int frame_rx, int subframe_rx, char *string,RU_t proc->subframe_rx = subframe_rx; if (!oai_exit) { - T(T_ENB_MASTER_TICK, T_INT(0), T_INT(proc->frame_rx), T_INT(proc->subframe_rx)); + T(T_ENB_MASTER_TICK, T_INT(0), T_INT(ru_proc->frame_rx), T_INT(ru_proc->subframe_rx)); L1_proc->timestamp_tx = ru_proc->timestamp_rx + (sf_ahead*fp->samples_per_tti); L1_proc->frame_rx = ru_proc->frame_rx; L1_proc->subframe_rx = ru_proc->subframe_rx; From e26f7d7555b06c64c67af9ec91b921957c382367 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Thu, 27 Jun 2019 14:17:46 +0200 Subject: [PATCH 26/32] F1: correctly initialize CU RRC params (clean up code after 99012f88b986d) --- openair2/ENB_APP/enb_config.c | 164 +++++++++++++++++----------------- 1 file changed, 81 insertions(+), 83 deletions(-) diff --git a/openair2/ENB_APP/enb_config.c b/openair2/ENB_APP/enb_config.c index 30130cf841..290b1c8cdf 100644 --- a/openair2/ENB_APP/enb_config.c +++ b/openair2/ENB_APP/enb_config.c @@ -449,98 +449,96 @@ int RCconfig_RRC(uint32_t i, eNB_RRC_INST *rrc, int macrlc_has_f1) { //printf("Component carrier %d\n",component_carrier); nb_cc++; - if (1 || !NODE_IS_CU(rrc->node_type)) { - // Cell params, MIB/SIB1 in DU - RRC_CONFIGURATION_REQ (msg_p).tdd_config[j] = ccparams_lte.tdd_config; - AssertFatal (ccparams_lte.tdd_config <= LTE_TDD_Config__subframeAssignment_sa6, - "Failed to parse eNB configuration file %s, enb %d illegal tdd_config %d (should be 0-%d)!", - RC.config_file_name, i, ccparams_lte.tdd_config, LTE_TDD_Config__subframeAssignment_sa6); - RRC_CONFIGURATION_REQ (msg_p).tdd_config_s[j] = ccparams_lte.tdd_config_s; - AssertFatal (ccparams_lte.tdd_config_s <= LTE_TDD_Config__specialSubframePatterns_ssp8, - "Failed to parse eNB configuration file %s, enb %d illegal tdd_config_s %d (should be 0-%d)!", - RC.config_file_name, i, ccparams_lte.tdd_config_s, LTE_TDD_Config__specialSubframePatterns_ssp8); + // Cell params, MIB/SIB1 in DU + RRC_CONFIGURATION_REQ (msg_p).tdd_config[j] = ccparams_lte.tdd_config; + AssertFatal (ccparams_lte.tdd_config <= LTE_TDD_Config__subframeAssignment_sa6, + "Failed to parse eNB configuration file %s, enb %d illegal tdd_config %d (should be 0-%d)!", + RC.config_file_name, i, ccparams_lte.tdd_config, LTE_TDD_Config__subframeAssignment_sa6); + RRC_CONFIGURATION_REQ (msg_p).tdd_config_s[j] = ccparams_lte.tdd_config_s; + AssertFatal (ccparams_lte.tdd_config_s <= LTE_TDD_Config__specialSubframePatterns_ssp8, + "Failed to parse eNB configuration file %s, enb %d illegal tdd_config_s %d (should be 0-%d)!", + RC.config_file_name, i, ccparams_lte.tdd_config_s, LTE_TDD_Config__specialSubframePatterns_ssp8); - if (!ccparams_lte.prefix_type) - AssertFatal (0, - "Failed to parse eNB configuration file %s, enb %d define %s: NORMAL,EXTENDED!\n", - RC.config_file_name, i, ENB_CONFIG_STRING_PREFIX_TYPE); - else if (strcmp(ccparams_lte.prefix_type, "NORMAL") == 0) { - RRC_CONFIGURATION_REQ (msg_p).prefix_type[j] = NORMAL; - } else if (strcmp(ccparams_lte.prefix_type, "EXTENDED") == 0) { - RRC_CONFIGURATION_REQ (msg_p).prefix_type[j] = EXTENDED; - } else { - AssertFatal (0, - "Failed to parse eNB configuration file %s, enb %d unknown value \"%s\" for prefix_type choice: NORMAL or EXTENDED !\n", - RC.config_file_name, i, ccparams_lte.prefix_type); - } + if (!ccparams_lte.prefix_type) + AssertFatal (0, + "Failed to parse eNB configuration file %s, enb %d define %s: NORMAL,EXTENDED!\n", + RC.config_file_name, i, ENB_CONFIG_STRING_PREFIX_TYPE); + else if (strcmp(ccparams_lte.prefix_type, "NORMAL") == 0) { + RRC_CONFIGURATION_REQ (msg_p).prefix_type[j] = NORMAL; + } else if (strcmp(ccparams_lte.prefix_type, "EXTENDED") == 0) { + RRC_CONFIGURATION_REQ (msg_p).prefix_type[j] = EXTENDED; + } else { + AssertFatal (0, + "Failed to parse eNB configuration file %s, enb %d unknown value \"%s\" for prefix_type choice: NORMAL or EXTENDED !\n", + RC.config_file_name, i, ccparams_lte.prefix_type); + } #if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0)) - if (!ccparams_lte.pbch_repetition) - AssertFatal (0, - "Failed to parse eNB configuration file %s, enb %d define %s: TRUE,FALSE!\n", - RC.config_file_name, i, ENB_CONFIG_STRING_PBCH_REPETITION); - else if (strcmp(ccparams_lte.pbch_repetition, "TRUE") == 0) { - RRC_CONFIGURATION_REQ (msg_p).pbch_repetition[j] = 1; - } else if (strcmp(ccparams_lte.pbch_repetition, "FALSE") == 0) { - RRC_CONFIGURATION_REQ (msg_p).pbch_repetition[j] = 0; - } else { - AssertFatal (0, - "Failed to parse eNB configuration file %s, enb %d unknown value \"%s\" for pbch_repetition choice: TRUE or FALSE !\n", - RC.config_file_name, i, ccparams_lte.pbch_repetition); - } + if (!ccparams_lte.pbch_repetition) + AssertFatal (0, + "Failed to parse eNB configuration file %s, enb %d define %s: TRUE,FALSE!\n", + RC.config_file_name, i, ENB_CONFIG_STRING_PBCH_REPETITION); + else if (strcmp(ccparams_lte.pbch_repetition, "TRUE") == 0) { + RRC_CONFIGURATION_REQ (msg_p).pbch_repetition[j] = 1; + } else if (strcmp(ccparams_lte.pbch_repetition, "FALSE") == 0) { + RRC_CONFIGURATION_REQ (msg_p).pbch_repetition[j] = 0; + } else { + AssertFatal (0, + "Failed to parse eNB configuration file %s, enb %d unknown value \"%s\" for pbch_repetition choice: TRUE or FALSE !\n", + RC.config_file_name, i, ccparams_lte.pbch_repetition); + } #endif - RRC_CONFIGURATION_REQ (msg_p).eutra_band[j] = ccparams_lte.eutra_band; - RRC_CONFIGURATION_REQ (msg_p).downlink_frequency[j] = (uint32_t) ccparams_lte.downlink_frequency; - RRC_CONFIGURATION_REQ (msg_p).uplink_frequency_offset[j] = (unsigned int) ccparams_lte.uplink_frequency_offset; - RRC_CONFIGURATION_REQ (msg_p).Nid_cell[j]= ccparams_lte.Nid_cell; + RRC_CONFIGURATION_REQ (msg_p).eutra_band[j] = ccparams_lte.eutra_band; + RRC_CONFIGURATION_REQ (msg_p).downlink_frequency[j] = (uint32_t) ccparams_lte.downlink_frequency; + RRC_CONFIGURATION_REQ (msg_p).uplink_frequency_offset[j] = (unsigned int) ccparams_lte.uplink_frequency_offset; + RRC_CONFIGURATION_REQ (msg_p).Nid_cell[j]= ccparams_lte.Nid_cell; - if (ccparams_lte.Nid_cell>503) { - AssertFatal (0, - "Failed to parse eNB configuration file %s, enb %d unknown value \"%d\" for Nid_cell choice: 0...503 !\n", - RC.config_file_name, i, ccparams_lte.Nid_cell); - } - - RRC_CONFIGURATION_REQ (msg_p).N_RB_DL[j]= ccparams_lte.N_RB_DL; - - if ((ccparams_lte.N_RB_DL!=6) && - (ccparams_lte.N_RB_DL!=15) && - (ccparams_lte.N_RB_DL!=25) && - (ccparams_lte.N_RB_DL!=50) && - (ccparams_lte.N_RB_DL!=75) && - (ccparams_lte.N_RB_DL!=100)) { - AssertFatal (0, - "Failed to parse eNB configuration file %s, enb %d unknown value \"%d\" for N_RB_DL choice: 6,15,25,50,75,100 !\n", - RC.config_file_name, i, ccparams_lte.N_RB_DL); - } - - if (strcmp(ccparams_lte.frame_type, "FDD") == 0) { - RRC_CONFIGURATION_REQ (msg_p).frame_type[j] = FDD; - } else if (strcmp(ccparams_lte.frame_type, "TDD") == 0) { - RRC_CONFIGURATION_REQ (msg_p).frame_type[j] = TDD; - } else { - AssertFatal (0, - "Failed to parse eNB configuration file %s, enb %d unknown value \"%s\" for frame_type choice: FDD or TDD !\n", - RC.config_file_name, i, ccparams_lte.frame_type); - } - - if (config_check_band_frequencies(j, - RRC_CONFIGURATION_REQ (msg_p).eutra_band[j], - RRC_CONFIGURATION_REQ (msg_p).downlink_frequency[j], - RRC_CONFIGURATION_REQ (msg_p).uplink_frequency_offset[j], - RRC_CONFIGURATION_REQ (msg_p).frame_type[j])) { - AssertFatal(0, "error calling enb_check_band_frequencies\n"); - } - - if ((ccparams_lte.nb_antenna_ports <1) || (ccparams_lte.nb_antenna_ports > 2)) - AssertFatal (0, - "Failed to parse eNB configuration file %s, enb %d unknown value \"%d\" for nb_antenna_ports choice: 1..2 !\n", - RC.config_file_name, i, ccparams_lte.nb_antenna_ports); - - RRC_CONFIGURATION_REQ (msg_p).nb_antenna_ports[j] = ccparams_lte.nb_antenna_ports; + if (ccparams_lte.Nid_cell>503) { + AssertFatal (0, + "Failed to parse eNB configuration file %s, enb %d unknown value \"%d\" for Nid_cell choice: 0...503 !\n", + RC.config_file_name, i, ccparams_lte.Nid_cell); } + RRC_CONFIGURATION_REQ (msg_p).N_RB_DL[j]= ccparams_lte.N_RB_DL; + + if ((ccparams_lte.N_RB_DL!=6) && + (ccparams_lte.N_RB_DL!=15) && + (ccparams_lte.N_RB_DL!=25) && + (ccparams_lte.N_RB_DL!=50) && + (ccparams_lte.N_RB_DL!=75) && + (ccparams_lte.N_RB_DL!=100)) { + AssertFatal (0, + "Failed to parse eNB configuration file %s, enb %d unknown value \"%d\" for N_RB_DL choice: 6,15,25,50,75,100 !\n", + RC.config_file_name, i, ccparams_lte.N_RB_DL); + } + + if (strcmp(ccparams_lte.frame_type, "FDD") == 0) { + RRC_CONFIGURATION_REQ (msg_p).frame_type[j] = FDD; + } else if (strcmp(ccparams_lte.frame_type, "TDD") == 0) { + RRC_CONFIGURATION_REQ (msg_p).frame_type[j] = TDD; + } else { + AssertFatal (0, + "Failed to parse eNB configuration file %s, enb %d unknown value \"%s\" for frame_type choice: FDD or TDD !\n", + RC.config_file_name, i, ccparams_lte.frame_type); + } + + if (config_check_band_frequencies(j, + RRC_CONFIGURATION_REQ (msg_p).eutra_band[j], + RRC_CONFIGURATION_REQ (msg_p).downlink_frequency[j], + RRC_CONFIGURATION_REQ (msg_p).uplink_frequency_offset[j], + RRC_CONFIGURATION_REQ (msg_p).frame_type[j])) { + AssertFatal(0, "error calling enb_check_band_frequencies\n"); + } + + if ((ccparams_lte.nb_antenna_ports <1) || (ccparams_lte.nb_antenna_ports > 2)) + AssertFatal (0, + "Failed to parse eNB configuration file %s, enb %d unknown value \"%d\" for nb_antenna_ports choice: 1..2 !\n", + RC.config_file_name, i, ccparams_lte.nb_antenna_ports); + + RRC_CONFIGURATION_REQ (msg_p).nb_antenna_ports[j] = ccparams_lte.nb_antenna_ports; + if (!NODE_IS_DU(rrc->node_type)) { //this is CU or eNB, SIB2-20 in CU // Radio Resource Configuration (SIB2) RRC_CONFIGURATION_REQ (msg_p).radioresourceconfig[j].prach_root = ccparams_lte.prach_root; From 924e10f73a62b8b0eac0f84ccdfeedd797a91c11 Mon Sep 17 00:00:00 2001 From: laurent Date: Mon, 1 Jul 2019 15:17:07 +0200 Subject: [PATCH 27/32] fix rfsim ue initial sync and legacy OAI C struct syntax --- cmake_targets/CMakeLists.txt | 27 +- common/config/config_userapi.c | 2 +- common/utils/minimal_stub.c | 4 + common/utils/simple_executable.h | 37 +++ openair1/PHY/defs_eNB.h | 2 + openair1/PHY/impl_defs_lte_NB_IoT.h | 2 +- openair1/PHY/impl_defs_top.h | 8 + openair2/LAYER2/MAC/config.c | 2 +- openair2/LAYER2/MAC/eNB_scheduler.c | 6 +- openair2/LAYER2/MAC/eNB_scheduler_dlsch.c | 8 +- openair2/LAYER2/MAC/eNB_scheduler_fairRR.c | 12 +- openair2/LAYER2/MAC/eNB_scheduler_phytest.c | 2 +- .../LAYER2/MAC/eNB_scheduler_primitives.c | 18 +- openair2/LAYER2/MAC/eNB_scheduler_ulsch.c | 6 +- openair2/LAYER2/MAC/mac.h | 12 +- openair2/LAYER2/MAC/mac_proto.h | 2 +- openair2/LAYER2/MAC/pre_processor.c | 20 +- openair2/RRC/LTE/rrc_eNB.c | 2 +- targets/ARCH/COMMON/common_lib.c | 24 +- targets/ARCH/COMMON/common_lib.h | 34 ++- targets/ARCH/rfsimulator/README.md | 74 +++-- targets/ARCH/rfsimulator/simulator.c | 281 ++++++++++++++---- targets/ARCH/rfsimulator/stored_node.c | 142 +++++++++ targets/RT/USER/lte-softmodem-common.c | 2 + targets/RT/USER/lte-softmodem.h | 3 +- targets/RT/USER/lte-uesoftmodem.c | 2 - 26 files changed, 587 insertions(+), 147 deletions(-) create mode 100644 common/utils/minimal_stub.c create mode 100644 common/utils/simple_executable.h create mode 100644 targets/ARCH/rfsimulator/stored_node.c diff --git a/cmake_targets/CMakeLists.txt b/cmake_targets/CMakeLists.txt index 29792d1260..22394aa5eb 100644 --- a/cmake_targets/CMakeLists.txt +++ b/cmake_targets/CMakeLists.txt @@ -174,7 +174,7 @@ 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} -std=c++11 -D${MKVER}" + "${CMAKE_CXX_FLAGS} ${C_FLAGS_PROCESSOR} -Wno-packed-bitfield-compat -fPIC -Wall -fno-strict-aliasing -rdynamic -std=c++11 -D${MKVER}" ) @@ -604,7 +604,6 @@ set(HWLIB_TCP_BRIDGE_OAI_SOURCE add_library(tcp_bridge_oai MODULE ${HWLIB_TCP_BRIDGE_OAI_SOURCE} ) set_target_properties(tcp_bridge_oai PROPERTIES COMPILE_FLAGS "-fvisibility=hidden") -add_library(rfsimulator MODULE ${OPENAIR_TARGETS}/ARCH/rfsimulator/simulator.c) ########################################################## @@ -1986,6 +1985,11 @@ add_library(uescope MODULE ${XFORMS_SOURCE} ${XFORMS_SOURCE_SOFTMODEM} ${XFORMS_ target_link_libraries(enbscope ${XFORMS_LIBRARIES}) target_link_libraries(uescope ${XFORMS_LIBRARIES}) +add_library(rfsimulator MODULE + ${OPENAIR_TARGETS}/ARCH/rfsimulator/simulator.c + ) +target_link_libraries(rfsimulator SIMU ${ATLAS_LIBRARIES}) + set(CMAKE_MODULE_PATH "${OPENAIR_DIR}/cmake_targets/tools/MODULES" "${CMAKE_MODULE_PATH}") #include T directory even if the T is off because T macros are in the code @@ -2029,6 +2033,25 @@ add_definitions(-DASN1_MINIMUM_VERSION=924) ################################# # add executables for operation ################################# +add_library(minimal_lib + ${OPENAIR_DIR}/common/utils/backtrace.c + ${OPENAIR_DIR}/common/utils/LOG/log.c + ${OPENAIR_DIR}/common/config/config_userapi.c + ${OPENAIR_DIR}/common/config/config_load_configmodule.c + ${OPENAIR_DIR}/common/config/config_cmdline.c + ${OPENAIR_DIR}/common/utils/minimal_stub.c + ${T_SOURCE} + ) +target_link_libraries(minimal_lib pthread dl ${T_LIB}) + +add_executable(replay_node + ${OPENAIR_TARGETS}/ARCH/rfsimulator/stored_node.c + ) +target_link_libraries (replay_node minimal_lib) + +add_executable(measurement_display + ${OPENAIR_DIR}/common/utils/threadPool/measurement_display.c) +target_link_libraries (measurement_display minimal_lib) # lte-softmodem is both eNB and UE implementation ################################################### diff --git a/common/config/config_userapi.c b/common/config/config_userapi.c index 66d3078d33..65e7a6dcc2 100644 --- a/common/config/config_userapi.c +++ b/common/config/config_userapi.c @@ -450,7 +450,7 @@ int config_setdefault_double(paramdef_t *cfgoptions, char *prefix) { config_check_valptr(cfgoptions, (char **)&(cfgoptions->dblptr),sizeof(double)); if( ((cfgoptions->paramflags & PARAMFLAG_MANDATORY) == 0)) { - *(cfgoptions->u64ptr)=cfgoptions->defdblval; + *(cfgoptions->dblptr)=cfgoptions->defdblval; status=1; printf_params("[CONFIG] %s set to default value %lf\n",cfgoptions->optname , *(cfgoptions->dblptr)); } diff --git a/common/utils/minimal_stub.c b/common/utils/minimal_stub.c new file mode 100644 index 0000000000..86454fe53f --- /dev/null +++ b/common/utils/minimal_stub.c @@ -0,0 +1,4 @@ +int T_stdout; + +void exit_function(const char *file, const char *function, const int line, const char *s) { +} diff --git a/common/utils/simple_executable.h b/common/utils/simple_executable.h new file mode 100644 index 0000000000..98b75012df --- /dev/null +++ b/common/utils/simple_executable.h @@ -0,0 +1,37 @@ +#ifndef __SIMPLE_EXE_H__ +#define __SIMPLE_EXE_H__ +#ifndef __USE_GNU +#define __USE_GNU +#endif +#ifndef _GNU_SOURCE +#define _GNU_SOURCE +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "common_lib.h" + +#ifdef T + #undef T + #define T(...) +#endif + +#endif diff --git a/openair1/PHY/defs_eNB.h b/openair1/PHY/defs_eNB.h index 1f2c44ca5b..f7123d6b43 100644 --- a/openair1/PHY/defs_eNB.h +++ b/openair1/PHY/defs_eNB.h @@ -33,7 +33,9 @@ #define __PHY_DEFS_ENB__H__ +#ifndef _GNU_SOURCE #define _GNU_SOURCE +#endif #include #include #include diff --git a/openair1/PHY/impl_defs_lte_NB_IoT.h b/openair1/PHY/impl_defs_lte_NB_IoT.h index 1167323174..97617b0ee0 100644 --- a/openair1/PHY/impl_defs_lte_NB_IoT.h +++ b/openair1/PHY/impl_defs_lte_NB_IoT.h @@ -415,7 +415,7 @@ typedef struct { /// nprach_CP_Length_r13, for the CP length(unit us) only 66.7 and 266.7 is implemented uint16_t nprach_CP_Length; /// The criterion for UEs to select a NPRACH resource. Up to 2 RSRP threshold values can be signalled. \vr{[1..2]} - struct rsrp_ThresholdsNPrachInfoList *rsrp_ThresholdsPrachInfoList; + rsrp_ThresholdsNPrachInfoList *rsrp_ThresholdsPrachInfoList; /// NPRACH Parameters List NPRACH_List_NB_IoT_t nprach_ParametersList; diff --git a/openair1/PHY/impl_defs_top.h b/openair1/PHY/impl_defs_top.h index df1f6f4693..c7c3e0e92e 100644 --- a/openair1/PHY/impl_defs_top.h +++ b/openair1/PHY/impl_defs_top.h @@ -282,8 +282,16 @@ typedef struct { #define cmax(a,b) ((a>b) ? (a) : (b)) #define cmax3(a,b,c) ((cmax(a,b)>c) ? (cmax(a,b)) : (c)) #define cmin(a,b) ((aUE_list); diff --git a/openair2/LAYER2/MAC/eNB_scheduler.c b/openair2/LAYER2/MAC/eNB_scheduler.c index bb051dcd1e..c6200dc74d 100644 --- a/openair2/LAYER2/MAC/eNB_scheduler.c +++ b/openair2/LAYER2/MAC/eNB_scheduler.c @@ -91,7 +91,7 @@ void schedule_SRS(module_id_t module_idP, eNB_MAC_INST *eNB = RC.mac[module_idP]; UE_list_t *UE_list = &(eNB->UE_list); nfapi_ul_config_request_body_t *ul_req = NULL; - UE_sched_ctrl *UE_scheduling_control = NULL; + UE_sched_ctrl_t *UE_scheduling_control = NULL; COMMON_channels_t *cc = eNB->common_channels; LTE_SoundingRS_UL_ConfigCommon_t *soundingRS_UL_ConfigCommon = NULL; struct LTE_SoundingRS_UL_ConfigDedicated *soundingRS_UL_ConfigDedicated = NULL; @@ -198,7 +198,7 @@ void schedule_CSI(module_id_t module_idP, UE_list_t *UE_list = &eNB->UE_list; COMMON_channels_t *cc = NULL; nfapi_ul_config_request_body_t *ul_req = NULL; - UE_sched_ctrl *UE_scheduling_control = NULL; + UE_sched_ctrl_t *UE_scheduling_control = NULL; for (CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) { cc = &eNB->common_channels[CC_id]; @@ -571,7 +571,7 @@ eNB_dlsch_ulsch_scheduler(module_id_t module_idP, eNB_MAC_INST *eNB = RC.mac[module_idP]; UE_list_t *UE_list = &(eNB->UE_list); COMMON_channels_t *cc = eNB->common_channels; - UE_sched_ctrl *UE_scheduling_control = NULL; + UE_sched_ctrl_t *UE_scheduling_control = NULL; start_meas(&(eNB->eNB_scheduler)); diff --git a/openair2/LAYER2/MAC/eNB_scheduler_dlsch.c b/openair2/LAYER2/MAC/eNB_scheduler_dlsch.c index 95e2bf59e8..ddbda5b2a0 100644 --- a/openair2/LAYER2/MAC/eNB_scheduler_dlsch.c +++ b/openair2/LAYER2/MAC/eNB_scheduler_dlsch.c @@ -480,7 +480,7 @@ schedule_ue_spec(module_id_t module_idP, eNB_UE_STATS *eNB_UE_stats = NULL; UE_TEMPLATE *ue_template = NULL; eNB_STATS *eNB_stats = NULL; - RRC_release_ctrl *release_ctrl = NULL; + RRC_release_ctrl_t *release_ctrl = NULL; DLSCH_PDU *dlsch_pdu = NULL; RA_t *ra = NULL; int sdu_length_total = 0; @@ -490,7 +490,7 @@ schedule_ue_spec(module_id_t module_idP, int continue_flag = 0; int32_t normalized_rx_power, target_rx_power; int tpc = 1; - UE_sched_ctrl *ue_sched_ctrl; + UE_sched_ctrl_t *ue_sched_ctrl; int mcs; int i; int min_rb_unit[NFAPI_CC_MAX]; @@ -1688,7 +1688,7 @@ dlsch_scheduler_interslice_multiplexing(module_id_t Mod_id, int nb_mac_CC = RC.nb_mac_CC[Mod_id]; UE_list_t *UE_list = &eNB->UE_list; slice_info_t *sli = &eNB->slice_info; - UE_sched_ctrl *ue_sched_ctl; + UE_sched_ctrl_t *ue_sched_ctl; COMMON_channels_t *cc; int N_RBG[NFAPI_CC_MAX]; int slice_sorted_list[MAX_NUM_SLICES]; @@ -1914,7 +1914,7 @@ schedule_ue_spec_br(module_id_t module_idP, COMMON_channels_t *cc = mac->common_channels; UE_list_t *UE_list = &mac->UE_list; UE_TEMPLATE *UE_template = NULL; - UE_sched_ctrl *ue_sched_ctl = NULL; + UE_sched_ctrl_t *ue_sched_ctl = NULL; nfapi_dl_config_request_pdu_t *dl_config_pdu = NULL; nfapi_ul_config_request_pdu_t *ul_config_pdu = NULL; nfapi_tx_request_pdu_t *TX_req = NULL; diff --git a/openair2/LAYER2/MAC/eNB_scheduler_fairRR.c b/openair2/LAYER2/MAC/eNB_scheduler_fairRR.c index 4c2e0b46a2..697c738b80 100644 --- a/openair2/LAYER2/MAC/eNB_scheduler_fairRR.c +++ b/openair2/LAYER2/MAC/eNB_scheduler_fairRR.c @@ -179,7 +179,7 @@ void dlsch_scheduler_pre_ue_select_fairRR( eNB_MAC_INST *eNB = RC.mac[module_idP]; COMMON_channels_t *cc = eNB->common_channels; UE_list_t *UE_list = &eNB->UE_list; - UE_sched_ctrl *ue_sched_ctl; + UE_sched_ctrl_t *ue_sched_ctl; uint8_t CC_id; int UE_id; unsigned char round = 0; @@ -585,7 +585,7 @@ void dlsch_scheduler_pre_processor_fairRR (module_id_t Mod_id, // uint16_t r1=0; uint8_t CC_id; UE_list_t *UE_list = &RC.mac[Mod_id]->UE_list; - UE_sched_ctrl *ue_sched_ctl; + UE_sched_ctrl_t *ue_sched_ctl; // int rrc_status = RRC_IDLE; COMMON_channels_t *cc; #ifdef TM5 @@ -596,7 +596,7 @@ void dlsch_scheduler_pre_processor_fairRR (module_id_t Mod_id, rnti_t rnti1, rnti2; LTE_eNB_UE_stats *eNB_UE_stats1 = NULL; LTE_eNB_UE_stats *eNB_UE_stats2 = NULL; - UE_sched_ctrl *ue_sched_ctl1, *ue_sched_ctl2; + UE_sched_ctrl_t *ue_sched_ctl1, *ue_sched_ctl2; #endif memset(rballoc_sub[0],0,(MAX_NUM_CCs)*(N_RBG_MAX)*sizeof(unsigned char)); memset(min_rb_unit,0,sizeof(min_rb_unit)); @@ -828,7 +828,7 @@ schedule_ue_spec_fairRR(module_id_t module_idP, int32_t normalized_rx_power, target_rx_power; int32_t tpc = 1; static int32_t tpc_accumulated = 0; - UE_sched_ctrl *ue_sched_ctl; + UE_sched_ctrl_t *ue_sched_ctl; int mcs; int i; int min_rb_unit[MAX_NUM_CCs]; @@ -1968,7 +1968,7 @@ void ulsch_scheduler_pre_ue_select_fairRR( uint8_t ulsch_ue_max_num[MAX_NUM_CCs]; uint16_t saved_ulsch_dci[MAX_NUM_CCs]; rnti_t rnti; - UE_sched_ctrl *UE_sched_ctl = NULL; + UE_sched_ctrl_t *UE_sched_ctl = NULL; uint8_t cc_id_flag[MAX_NUM_CCs]; uint8_t harq_pid = 0,round = 0; UE_list_t *UE_list= &eNB->UE_list; @@ -2627,7 +2627,7 @@ void schedule_ulsch_rnti_fairRR(module_id_t module_idP, COMMON_channels_t *cc; UE_list_t *UE_list=&eNB->UE_list; UE_TEMPLATE *UE_template; - UE_sched_ctrl *UE_sched_ctrl; + UE_sched_ctrl_t *UE_sched_ctrl; int sched_frame=frameP; int rvidx_tab[4] = {0,2,3,1}; uint16_t ul_req_index; diff --git a/openair2/LAYER2/MAC/eNB_scheduler_phytest.c b/openair2/LAYER2/MAC/eNB_scheduler_phytest.c index 2f566c0d7a..4f74ab0d09 100644 --- a/openair2/LAYER2/MAC/eNB_scheduler_phytest.c +++ b/openair2/LAYER2/MAC/eNB_scheduler_phytest.c @@ -208,7 +208,7 @@ void schedule_ulsch_phy_test(module_id_t module_idP,frame_t frameP,sub_frame_t s COMMON_channels_t *cc = &mac->common_channels[0]; UE_list_t *UE_list=&mac->UE_list; UE_TEMPLATE *UE_template; - UE_sched_ctrl *UE_sched_ctrl; + UE_sched_ctrl_t *UE_sched_ctrl; int sched_frame=frameP; int sched_subframe = (subframeP+4)%10; uint16_t ul_req_index; diff --git a/openair2/LAYER2/MAC/eNB_scheduler_primitives.c b/openair2/LAYER2/MAC/eNB_scheduler_primitives.c index 85fd84a305..856045166f 100644 --- a/openair2/LAYER2/MAC/eNB_scheduler_primitives.c +++ b/openair2/LAYER2/MAC/eNB_scheduler_primitives.c @@ -1073,7 +1073,7 @@ get_dl_cqi_pmi_size_pusch(COMMON_channels_t *cc, //------------------------------------------------------------------------------ uint8_t -get_rel8_dl_cqi_pmi_size(UE_sched_ctrl *sched_ctl, +get_rel8_dl_cqi_pmi_size(UE_sched_ctrl_t *sched_ctl, int CC_idP, COMMON_channels_t *cc, uint8_t tmode, @@ -2182,7 +2182,7 @@ add_new_ue(module_id_t mod_idP, #endif memset((void *) &UE_list->UE_sched_ctrl[UE_id], 0, - sizeof(UE_sched_ctrl)); + sizeof(UE_sched_ctrl_t)); memset((void *) &UE_list->eNB_UE_stats[cc_idP][UE_id], 0, sizeof(eNB_UE_STATS)); @@ -2520,7 +2520,7 @@ UE_is_to_be_scheduled(module_id_t module_idP, //------------------------------------------------------------------------------ { UE_TEMPLATE *UE_template = &RC.mac[module_idP]->UE_list.UE_template[CC_id][UE_id]; - UE_sched_ctrl *UE_sched_ctl = &RC.mac[module_idP]->UE_list.UE_sched_ctrl[UE_id]; + UE_sched_ctrl_t *UE_sched_ctl = &RC.mac[module_idP]->UE_list.UE_sched_ctrl[UE_id]; // do not schedule UE if UL is not working if (UE_sched_ctl->ul_failure_timer > 0 || UE_sched_ctl->ul_out_of_sync > 0) @@ -3928,7 +3928,7 @@ extract_harq(module_id_t mod_idP, { eNB_MAC_INST *eNB = RC.mac[mod_idP]; UE_list_t *UE_list = &eNB->UE_list; - UE_sched_ctrl *sched_ctl = &UE_list->UE_sched_ctrl[UE_id]; + UE_sched_ctrl_t *sched_ctl = &UE_list->UE_sched_ctrl[UE_id]; rnti_t rnti = UE_RNTI(mod_idP, UE_id); COMMON_channels_t *cc = &eNB->common_channels[CC_idP]; nfapi_harq_indication_fdd_rel13_t *harq_indication_fdd; @@ -4573,7 +4573,7 @@ extract_pucch_csi(module_id_t mod_idP, //------------------------------------------------------------------------------ { UE_list_t *UE_list = &RC.mac[mod_idP]->UE_list; - UE_sched_ctrl *sched_ctl = &UE_list->UE_sched_ctrl[UE_id]; + UE_sched_ctrl_t *sched_ctl = &UE_list->UE_sched_ctrl[UE_id]; COMMON_channels_t *cc = &RC.mac[mod_idP]->common_channels[CC_idP]; int no_pmi; uint8_t Ltab[6] = { 0, 2, 4, 4, 4, 4 }; @@ -4685,7 +4685,7 @@ extract_pusch_csi(module_id_t mod_idP, { UE_list_t *UE_list = &RC.mac[mod_idP]->UE_list; COMMON_channels_t *cc = &RC.mac[mod_idP]->common_channels[CC_idP]; - UE_sched_ctrl *sched_ctl = &UE_list->UE_sched_ctrl[UE_id]; + UE_sched_ctrl_t *sched_ctl = &UE_list->UE_sched_ctrl[UE_id]; int Ntab[6] = { 0, 4, 7, 9, 10, 13 }; int Ntab_uesel[6] = { 0, 8, 13, 17, 19, 25 }; int Ltab_uesel[6] = { 0, 6, 9, 13, 15, 18 }; @@ -4980,7 +4980,7 @@ cqi_indication(module_id_t mod_idP, return; } - UE_sched_ctrl *sched_ctl = &UE_list->UE_sched_ctrl[UE_id]; + UE_sched_ctrl_t *sched_ctl = &UE_list->UE_sched_ctrl[UE_id]; if (UE_id >= 0) { LOG_D(MAC,"%s() UE_id:%d channel:%d cqi:%d\n", @@ -5047,7 +5047,7 @@ SR_indication(module_id_t mod_idP, T_INT(rntiP)); int UE_id = find_UE_id(mod_idP, rntiP); UE_list_t *UE_list = &RC.mac[mod_idP]->UE_list; - UE_sched_ctrl *UE_scheduling_ctrl = NULL; + UE_sched_ctrl_t *UE_scheduling_ctrl = NULL; if (UE_id != -1) { UE_scheduling_ctrl = &(UE_list->UE_sched_ctrl[UE_id]); @@ -5178,7 +5178,7 @@ harq_indication(module_id_t mod_idP, } UE_list_t *UE_list = &RC.mac[mod_idP]->UE_list; - UE_sched_ctrl *sched_ctl = &UE_list->UE_sched_ctrl[UE_id]; + UE_sched_ctrl_t *sched_ctl = &UE_list->UE_sched_ctrl[UE_id]; COMMON_channels_t *cc = &RC.mac[mod_idP]->common_channels[CC_idP]; // extract HARQ Information diff --git a/openair2/LAYER2/MAC/eNB_scheduler_ulsch.c b/openair2/LAYER2/MAC/eNB_scheduler_ulsch.c index 454278ed98..dd228c4250 100644 --- a/openair2/LAYER2/MAC/eNB_scheduler_ulsch.c +++ b/openair2/LAYER2/MAC/eNB_scheduler_ulsch.c @@ -121,7 +121,7 @@ rx_sdu(const module_id_t enb_mod_idP, eNB_MAC_INST *mac = NULL; UE_list_t *UE_list = NULL; rrc_eNB_ue_context_t *ue_contextP = NULL; - UE_sched_ctrl *UE_scheduling_control = NULL; + UE_sched_ctrl_t *UE_scheduling_control = NULL; UE_TEMPLATE *UE_template_ptr = NULL; /* Init */ @@ -1340,7 +1340,7 @@ schedule_ulsch_rnti(module_id_t module_idP, UE_list_t *UE_list = NULL; slice_info_t *sli = NULL; UE_TEMPLATE *UE_template_ptr = NULL; - UE_sched_ctrl *UE_sched_ctrl_ptr = NULL; + UE_sched_ctrl_t *UE_sched_ctrl_ptr = NULL; int rvidx_tab[4] = {0, 2, 3, 1}; int first_rb_slice[NFAPI_CC_MAX]; int n_rb_ul_tab[NFAPI_CC_MAX]; @@ -1954,7 +1954,7 @@ void schedule_ulsch_rnti_emtc(module_id_t module_idP, COMMON_channels_t *cc = eNB->common_channels; UE_list_t *UE_list = &(eNB->UE_list); UE_TEMPLATE *UE_template = NULL; - UE_sched_ctrl *UE_sched_ctrl = NULL; + UE_sched_ctrl_t *UE_sched_ctrl = NULL; if (sched_subframeP < subframeP) { sched_frame++; diff --git a/openair2/LAYER2/MAC/mac.h b/openair2/LAYER2/MAC/mac.h index 8f9a1b94f6..276f1e4e6f 100644 --- a/openair2/LAYER2/MAC/mac.h +++ b/openair2/LAYER2/MAC/mac.h @@ -1070,7 +1070,7 @@ typedef struct { /// DRX UL retransmission timer, one per UL HARQ process /* Not implemented yet */ /* End of C-DRX related timers */ -} UE_sched_ctrl; +} UE_sched_ctrl_t; /*! \brief eNB template for the Random access information */ typedef struct { @@ -1168,7 +1168,7 @@ typedef struct { /// eNB to UE statistics eNB_UE_STATS eNB_UE_stats[NFAPI_CC_MAX][MAX_MOBILES_PER_ENB]; /// scheduling control info - UE_sched_ctrl UE_sched_ctrl[MAX_MOBILES_PER_ENB]; + UE_sched_ctrl_t UE_sched_ctrl[MAX_MOBILES_PER_ENB]; int next[MAX_MOBILES_PER_ENB]; int head; int next_ul[MAX_MOBILES_PER_ENB]; @@ -1191,11 +1191,11 @@ typedef struct { rnti_t rnti; ///remove UE context flag boolean_t removeContextFlg; -} UE_free_ctrl; +} UE_free_ctrl_t; /*! \brief REMOVE UE list used by eNB to order UEs/CC for deleting*/ typedef struct { /// deleting control info - UE_free_ctrl UE_free_ctrl[NUMBER_OF_UE_MAX+1]; + UE_free_ctrl_t UE_free_ctrl[NUMBER_OF_UE_MAX+1]; int num_UEs; int head_freelist; ///the head position of the delete list int tail_freelist; ///the tail position of the delete list @@ -1772,11 +1772,11 @@ typedef struct { volatile uint8_t flag; rnti_t rnti; mui_t rrc_eNB_mui; -}RRC_release_ctrl; +}RRC_release_ctrl_t; typedef struct { uint16_t num_UEs; - RRC_release_ctrl RRC_release_ctrl[NUMBER_OF_UE_MAX]; + RRC_release_ctrl_t RRC_release_ctrl[NUMBER_OF_UE_MAX]; } RRC_release_list_t; typedef struct { diff --git a/openair2/LAYER2/MAC/mac_proto.h b/openair2/LAYER2/MAC/mac_proto.h index f5762cb14e..695005cd1f 100644 --- a/openair2/LAYER2/MAC/mac_proto.h +++ b/openair2/LAYER2/MAC/mac_proto.h @@ -1160,7 +1160,7 @@ void get_csi_params(COMMON_channels_t * cc, struct LTE_CQI_ReportPeriodic *cqi_PMI_ConfigIndex, uint16_t * Npd, uint16_t * N_OFFSET_CQI, int *H); -uint8_t get_rel8_dl_cqi_pmi_size(UE_sched_ctrl * sched_ctl, int CC_idP, +uint8_t get_rel8_dl_cqi_pmi_size(UE_sched_ctrl_t * sched_ctl, int CC_idP, COMMON_channels_t * cc, uint8_t tmode, struct LTE_CQI_ReportPeriodic *cqi_ReportPeriodic); diff --git a/openair2/LAYER2/MAC/pre_processor.c b/openair2/LAYER2/MAC/pre_processor.c index a162dd5bd6..0dc11b0e45 100644 --- a/openair2/LAYER2/MAC/pre_processor.c +++ b/openair2/LAYER2/MAC/pre_processor.c @@ -505,7 +505,7 @@ void sort_UEs(module_id_t Mod_idP, int list_size = 0; struct sort_ue_dl_params params = {Mod_idP, frameP, subframeP, slice_idx}; UE_list_t *UE_list = &(RC.mac[Mod_idP]->UE_list); - UE_sched_ctrl *UE_scheduling_control = NULL; + UE_sched_ctrl_t *UE_scheduling_control = NULL; for (int i = 0; i < MAX_MOBILES_PER_ENB; i++) { @@ -546,7 +546,7 @@ void dlsch_scheduler_pre_processor_partitioning(module_id_t Mod_id, const uint8_t rbs_retx[NFAPI_CC_MAX]) { int UE_id, CC_id, N_RB_DL, i; UE_list_t *UE_list = &RC.mac[Mod_id]->UE_list; - UE_sched_ctrl *ue_sched_ctl; + UE_sched_ctrl_t *ue_sched_ctl; uint16_t available_rbs; for (UE_id = UE_list->head; UE_id >= 0; UE_id = UE_list->next[UE_id]) { @@ -590,7 +590,7 @@ void dlsch_scheduler_pre_processor_accounting(module_id_t Mod_id, int ue_count_retx[NFAPI_CC_MAX]; //uint8_t ue_retx_flag[NFAPI_CC_MAX][MAX_MOBILES_PER_ENB]; UE_list_t *UE_list = &RC.mac[Mod_id]->UE_list; - UE_sched_ctrl *ue_sched_ctl; + UE_sched_ctrl_t *ue_sched_ctl; COMMON_channels_t *cc; // Reset @@ -1226,7 +1226,7 @@ dlsch_scheduler_pre_processor(module_id_t Mod_id, uint8_t (*MIMO_mode_indicator)[N_RBG_MAX] = sli->pre_processor_results[slice_idx].MIMO_mode_indicator; UE_list_t *UE_list = &eNB->UE_list; - UE_sched_ctrl *ue_sched_ctl; + UE_sched_ctrl_t *ue_sched_ctl; // int rrc_status = RRC_IDLE; #ifdef TM5 int harq_pid1 = 0; @@ -1236,7 +1236,7 @@ dlsch_scheduler_pre_processor(module_id_t Mod_id, rnti_t rnti1, rnti2; LTE_eNB_UE_stats *eNB_UE_stats1 = NULL; LTE_eNB_UE_stats *eNB_UE_stats2 = NULL; - UE_sched_ctrl *ue_sched_ctl1, *ue_sched_ctl2; + UE_sched_ctrl_t *ue_sched_ctl1, *ue_sched_ctl2; #endif // Initialize scheduling information for all active UEs memset(&sli->pre_processor_results[slice_idx], 0, sizeof(sli->pre_processor_results[slice_idx])); @@ -1391,7 +1391,7 @@ dlsch_scheduler_pre_processor_reset(module_id_t module_idP, uint8_t CC_id; int i, j; UE_list_t *UE_list; - UE_sched_ctrl *ue_sched_ctl; + UE_sched_ctrl_t *ue_sched_ctl; int N_RB_DL, RBGsize, RBGsize_last; int N_RBG[NFAPI_CC_MAX]; #ifdef SF0_LIMIT @@ -1615,7 +1615,7 @@ dlsch_scheduler_pre_processor_allocate(module_id_t Mod_id, int i; int tm = get_tmode(Mod_id, CC_id, UE_id); UE_list_t *UE_list = &RC.mac[Mod_id]->UE_list; - UE_sched_ctrl *ue_sched_ctl = &UE_list->UE_sched_ctrl[UE_id]; + UE_sched_ctrl_t *ue_sched_ctl = &UE_list->UE_sched_ctrl[UE_id]; int N_RB_DL = to_prb(RC.mac[Mod_id]->common_channels[CC_id].mib->message.dl_Bandwidth); for (i = 0; i < N_RBG; i++) { @@ -1685,7 +1685,7 @@ void ulsch_scheduler_pre_processor(module_id_t module_idP, UE_list_t *UE_list = &eNB->UE_list; slice_info_t *sli = &eNB->slice_info; UE_TEMPLATE *UE_template = 0; - UE_sched_ctrl *ue_sched_ctl; + UE_sched_ctrl_t *ue_sched_ctl; int N_RB_UL = 0; uint16_t available_rbs, first_rb_offset; rnti_t rntiTable[MAX_MOBILES_PER_ENB]; @@ -1865,7 +1865,7 @@ assign_max_mcs_min_rb(module_id_t module_idP, UE_list_t *UE_list = &eNB->UE_list; slice_info_t *sli = &eNB->slice_info; UE_TEMPLATE *UE_template; - UE_sched_ctrl *ue_sched_ctl; + UE_sched_ctrl_t *ue_sched_ctl; int Ncp; int N_RB_UL; int first_rb_offset, available_rbs; @@ -2042,7 +2042,7 @@ void sort_ue_ul(module_id_t module_idP, int list_size = 0; struct sort_ue_ul_params params = { module_idP, sched_frameP, sched_subframeP }; UE_list_t *UE_list = &RC.mac[module_idP]->UE_list; - UE_sched_ctrl *UE_scheduling_control = NULL; + UE_sched_ctrl_t *UE_scheduling_control = NULL; for (int i = 0; i < MAX_MOBILES_PER_ENB; i++) { diff --git a/openair2/RRC/LTE/rrc_eNB.c b/openair2/RRC/LTE/rrc_eNB.c index 230b9511f0..b7ca81f6dd 100644 --- a/openair2/RRC/LTE/rrc_eNB.c +++ b/openair2/RRC/LTE/rrc_eNB.c @@ -5814,7 +5814,7 @@ rrc_eNB_process_RRCConnectionReconfigurationComplete( LOG_E(RRC,PROTOCOL_RRC_CTXT_UE_FMT" rrc_eNB_process_RRCConnectionReconfigurationComplete without UE_id(MAC) rnti %x, let's return\n",PROTOCOL_RRC_CTXT_UE_ARGS(ctxt_pP),ue_context_pP->ue_context.rnti); return; } - UE_sched_ctrl *UE_scheduling_control = &(RC.mac[ctxt_pP->module_id]->UE_list.UE_sched_ctrl[UE_id_mac]); + UE_sched_ctrl_t *UE_scheduling_control = &(RC.mac[ctxt_pP->module_id]->UE_list.UE_sched_ctrl[UE_id_mac]); if (UE_scheduling_control->cdrx_waiting_ack == TRUE) { UE_scheduling_control->cdrx_waiting_ack = FALSE; diff --git a/targets/ARCH/COMMON/common_lib.c b/targets/ARCH/COMMON/common_lib.c index 3f81816aa1..42a39f90ed 100644 --- a/targets/ARCH/COMMON/common_lib.c +++ b/targets/ARCH/COMMON/common_lib.c @@ -42,35 +42,35 @@ int set_device(openair0_device *device) { switch (device->type) { case EXMIMO_DEV: - printf("[%s] has loaded EXPRESS MIMO device.\n",((device->host_type == RAU_HOST) ? "RAU": "RRU")); + LOG_I(HW,"[%s] has loaded EXPRESS MIMO device.\n",((device->host_type == RAU_HOST) ? "RAU": "RRU")); break; case USRP_B200_DEV: - printf("[%s] has loaded USRP B200 device.\n",((device->host_type == RAU_HOST) ? "RAU": "RRU")); + LOG_I(HW,"[%s] has loaded USRP B200 device.\n",((device->host_type == RAU_HOST) ? "RAU": "RRU")); break; case USRP_X300_DEV: - printf("[%s] has loaded USRP X300 device.\n",((device->host_type == RAU_HOST) ? "RAU": "RRU")); + LOG_I(HW,"[%s] has loaded USRP X300 device.\n",((device->host_type == RAU_HOST) ? "RAU": "RRU")); break; case BLADERF_DEV: - printf("[%s] has loaded BLADERF device.\n",((device->host_type == RAU_HOST) ? "RAU": "RRU")); + LOG_I(HW,"[%s] has loaded BLADERF device.\n",((device->host_type == RAU_HOST) ? "RAU": "RRU")); break; case LMSSDR_DEV: - printf("[%s] has loaded LMSSDR device.\n",((device->host_type == RAU_HOST) ? "RAU": "RRU")); + LOG_I(HW,"[%s] has loaded LMSSDR device.\n",((device->host_type == RAU_HOST) ? "RAU": "RRU")); break; case IRIS_DEV: - printf("[%s] has loaded Iris device.\n",((device->host_type == RAU_HOST) ? "RAU": "RRU")); + LOG_I(HW,"[%s] has loaded Iris device.\n",((device->host_type == RAU_HOST) ? "RAU": "RRU")); break; case NONE_DEV: - printf("[%s] has not loaded a HW device.\n",((device->host_type == RAU_HOST) ? "RAU": "RRU")); + LOG_I(HW,"[%s] has not loaded a HW device.\n",((device->host_type == RAU_HOST) ? "RAU": "RRU")); break; default: - printf("[%s] invalid HW device.\n",((device->host_type == RAU_HOST) ? "RAU": "RRU")); + LOG_E(HW,"[%s] invalid HW device.\n",((device->host_type == RAU_HOST) ? "RAU": "RRU")); return -1; } @@ -90,7 +90,7 @@ int set_transport(openair0_device *device) { break; default: - printf("[%s] invalid transport protocol.\n",((device->host_type == RAU_HOST) ? "RAU": "RRU")); + LOG_E(HW,"[%s] invalid transport protocol.\n",((device->host_type == RAU_HOST) ? "RAU": "RRU")); return -1; break; } @@ -119,7 +119,7 @@ int load_lib(openair0_device *device, openair0_config_t *openair0_cfg, eth_param ret=load_module_shlib(libname,shlib_fdesc,1,NULL); if (ret < 0) { - fprintf(stderr,"Library %s couldn't be loaded\n",libname); + LOG_E(HW,"Library %s couldn't be loaded\n",libname); } else { ret=((devfunc_t)shlib_fdesc[0].fptr)(device,openair0_cfg,cfg); } @@ -135,7 +135,7 @@ int openair0_device_load(openair0_device *device, openair0_config_t *openair0_cf if ( rc >= 0) { if ( set_device(device) < 0) { - fprintf(stderr, "%s %d:Unsupported radio head\n",__FILE__, __LINE__); + LOG_E(HW, "%s %d:Unsupported radio head\n",__FILE__, __LINE__); return -1; } } @@ -149,7 +149,7 @@ int openair0_transport_load(openair0_device *device, openair0_config_t *openair0 if ( rc >= 0) { if ( set_transport(device) < 0) { - fprintf(stderr, "%s %d:Unsupported transport protocol\n",__FILE__, __LINE__); + LOG_E(HW, "%s %d:Unsupported transport protocol\n",__FILE__, __LINE__); return -1; } } diff --git a/targets/ARCH/COMMON/common_lib.h b/targets/ARCH/COMMON/common_lib.h index c7ae3b9d25..81a5bd0f54 100644 --- a/targets/ARCH/COMMON/common_lib.h +++ b/targets/ARCH/COMMON/common_lib.h @@ -34,6 +34,7 @@ #define COMMON_LIB_H #include #include +#include /* name of shared library implementing the radio front end */ #define OAI_RF_LIBNAME "oai_device" @@ -83,9 +84,6 @@ typedef enum { */ /*!\brief RF device types */ -#ifdef OCP_FRAMEWORK -#include -#else typedef enum { MIN_RF_DEV_TYPE = 0, /*!\brief device is ExpressMIMO */ @@ -102,10 +100,13 @@ typedef enum { IRIS_DEV, /*!\brief device is NONE*/ NONE_DEV, + /*!\brief device is ADRV9371_ZC706 */ + ADRV9371_ZC706_DEV, + /*!\brief device is UEDv2 */ + UEDv2_DEV, MAX_RF_DEV_TYPE } dev_type_t; -#endif /*!\brief transport protocol types */ @@ -397,6 +398,31 @@ struct openair0_device_t { typedef int(*oai_device_initfunc_t)(openair0_device *device, openair0_config_t *openair0_cfg); /* type of transport init function, implemented in shared lib */ typedef int(*oai_transport_initfunc_t)(openair0_device *device, openair0_config_t *openair0_cfg, eth_params_t *eth_params); +#define UE_MAGICDL_FDD 0xA5A5A5A5A5A5A5A5 // UE DL FDD record +#define UE_MAGICUL_FDD 0x5A5A5A5A5A5A5A5A // UE UL FDD record +#define UE_MAGICDL_TDD 0xA6A6A6A6A6A6A6A6 // UE DL TDD record +#define UE_MAGICUL_TDD 0x6A6A6A6A6A6A6A6A // UE UL TDD record + +#define ENB_MAGICDL_FDD 0xB5B5B5B5B5B5B5B5 // eNB DL FDD record +#define ENB_MAGICUL_FDD 0x5B5B5B5B5B5B5B5B // eNB UL FDD record +#define ENB_MAGICDL_TDD 0xB6B6B6B6B6B6B6B6 // eNB DL TDD record +#define ENB_MAGICUL_TDD 0x6B6B6B6B6B6B6B6B // eNB UL TDD record + +#define OPTION_LZ4 0x00000001 // LZ4 compression (option_value is set to compressed size) + +#define sample_t struct complex16 // 2*16 bits complex number + +typedef struct { + uint64_t magic; // Magic value (see defines above) + uint32_t size; // Number of samples per antenna to follow this header + uint32_t nbAnt; // Total number of antennas following this header + // Samples per antenna follow this header, + // i.e. nbAnt = 2 => this header+samples_antenna_0+samples_antenna_1 + // data following this header in bytes is nbAnt*size*sizeof(sample_t) + uint64_t timestamp; // Timestamp value of first sample + uint32_t option_value; // Option value + uint32_t option_flag; // Option flag +} samplesBlockHeader_t; #ifdef __cplusplus extern "C" diff --git a/targets/ARCH/rfsimulator/README.md b/targets/ARCH/rfsimulator/README.md index ebe7d72ee0..ae82b27f93 100644 --- a/targets/ARCH/rfsimulator/README.md +++ b/targets/ARCH/rfsimulator/README.md @@ -1,14 +1,26 @@ -## General - +#General This is a RF simulator that allows to test OAI without a RF board. It replaces a actual RF board driver. As much as possible, it works like a RF board, but not in realtime: it can run faster than realtime if there is enough CPU or slower (it is CPU bound instead of real time RF sampling bound) -## build +#build - No specific build is required, use the [oai softmodem build procedure](../../../doc/BUILD.md) +## From build_oai +You can build it the same way, and together with actual RF driver +Example: +```bash +./build_oai --ue-nas-use-tun --UE --eNB -w SIMU +``` +It is also possible to build actual RF and use choose on each run: +```bash +./build_oai --ue-nas-use-tun --UE --eNB -w USRP --rfsimulator +``` +Will build both the eNB (lte-softmodem) and the UE (lte-uesoftmodem) +We recommend to use the option --ue-nas-use-tun that is much simpler to use than the OAI kernel driver. + +## Add the rfsimulator after initial build After any regular build, you can compile the driver ```bash cd /build @@ -18,25 +30,15 @@ Then, you can use it freely # Usage Setting the env variable RFSIMULATOR enables the RF board simulator -It should the set to "enb" in the eNB +It should the set to "server" in the eNB or gNB ## 4G case For the UE, it should be set to the IP address of the eNB example: ```bash -sudo RFSIMULATOR=192.168.2.200 ./lte-uesoftmodem -C 2685000000 -r 50 --rfsim +sudo RFSIMULATOR=192.168.2.200 ./lte-uesoftmodem -C 2685000000 -r 50 ``` -For the eNodeB, use a valid configuration file setup for USRP board tests and start the softmodem as usual, but adding the `--rfsim` option. - - - -```bash -sudo RFSIMULATOR=enb ./lte-softmodem -O --rfsim -``` - - - Except this, the UE and the eNB can be used as it the RF is real If you reach 'RA not active' on UE, be careful to generate a valid SIM @@ -55,7 +57,7 @@ make rfsimulator ``` ### Launch gNB in one window ```bash -sudo RFSIMULATOR=enb ./nr-softmodem -O ../../../targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.106PRB.usrpn300.conf --parallel-config PARALLEL_SINGLE_THREAD +sudo RFSIMULATOR=server ./nr-softmodem -O ../../../targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.106PRB.usrpn300.conf --parallel-config PARALLEL_SINGLE_THREAD ``` ### Launch UE in another window ```bash @@ -64,8 +66,40 @@ sudo RFSIMULATOR=127.0.0.1 ./nr-uesoftmodem --numerology 1 -r 106 -C 3510000000 Of course, set the gNB machine IP address if the UE and the gNB are not on the same machine In UE, you can add "-d" to get the softscope -## Caveacts +### store and replay +You can store emitted I/Q samples: + +If you set the environment variable: saveIQfile to a file name +The simulator will write all IQ samples into this file + +Then, you can replay with the executable "replay_node" + +First compile it, as the other binaries +``` +make replay_node +``` +You can use this binary as I/Q data source to feed whatever UE or NB with recorded I/Q samples. + +The file format is successive blocks of a header followed by the I/Q array. +If you have existing stored I/Q, you can adpat the tool "replay_node" to convert your format to the rfsimulator format. + +The format intend to be compatible with the OAI store/replay feature on USRP + +### Channel simulation +The RF channel simulator is called. +In current version all channel paramters are hard coded in the call to: +``` +new_channel_desc_scm(bridge->tx_num_channels,bridge->rx_num_channels, + AWGN, + bridge->sample_rate, + bridge->tx_bw, + 0.0, // forgetting_factor + 0, // maybe used for TA + 0); // path_loss in dB +``` +Only the input noise can be changed on command line with -s parameter. +With path loss = 0 set "-s 5" to see a little noise + +#Caveacts Still issues in power control: txgain, rxgain are not used - - diff --git a/targets/ARCH/rfsimulator/simulator.c b/targets/ARCH/rfsimulator/simulator.c index a17327b03e..c8c21fce4f 100644 --- a/targets/ARCH/rfsimulator/simulator.c +++ b/targets/ARCH/rfsimulator/simulator.c @@ -21,63 +21,172 @@ #include "common_lib.h" #include #include "openair1/PHY/defs_UE.h" +#include #define PORT 4043 //TCP port for this simulator #define CirSize 3072000 // 100ms is enough -#define sample_t uint32_t // 2*16 bits complex number #define sampleToByte(a,b) ((a)*(b)*sizeof(sample_t)) #define byteToSample(a,b) ((a)/(sizeof(sample_t)*(b))) -#define MAGICeNB 0xA5A5A5A5A5A5A5A5 -#define MAGICUE 0x5A5A5A5A5A5A5A5A -typedef struct { - uint64_t magic; - uint32_t size; - uint32_t nbAnt; - uint64_t timestamp; -} transferHeader; +#define MAX_SIMULATION_CONNECTED_NODES 5 +#define GENERATE_CHANNEL 10 //each frame in DL + +// Fixme: datamodel, external variables in .h files, ... +#include +extern double snr_dB; +extern RAN_CONTEXT_t RC; +// + +pthread_mutex_t Sockmutex; typedef struct buffer_s { int conn_sock; bool alreadyRead; uint64_t lastReceivedTS; bool headerMode; - transferHeader th; + samplesBlockHeader_t th; char *transferPtr; uint64_t remainToTransfer; char *circularBufEnd; sample_t *circularBuf; + channel_desc_t *channel_model; } buffer_t; typedef struct { int listen_sock, epollfd; uint64_t nextTimestamp; uint64_t typeStamp; - uint64_t initialAhead; char *ip; + int saveIQfile; buffer_t buf[FD_SETSIZE]; + int rx_num_channels; + int tx_num_channels; + double sample_rate; + double tx_bw; } rfsimulator_state_t; +/* + Legacy study: + The parameters are: + gain&loss (decay, signal power, ...) + either a fixed gain in dB, a target power in dBm or ACG (automatic control gain) to a target average + => don't redo the AGC, as it was used in UE case, that must have a AGC inside the UE + will be better to handle the "set_gain()" called by UE to apply it's gain (enable test of UE power loop) + lin_amp = pow(10.0,.05*txpwr_dBm)/sqrt(nb_tx_antennas); + a lot of operations in legacy, grouped in one simulation signal decay: txgain*decay*rxgain + + multi_path (auto convolution, ISI, ...) + either we regenerate the channel (call again random_channel(desc,0)), or we keep it over subframes + legacy: we regenerate each sub frame in UL, and each frame only in DL +*/ +void rxAddInput( struct complex16 *input_sig, struct complex16 *after_channel_sig, + int rxAnt, + channel_desc_t *channelDesc, + int nbSamples, + uint64_t TS + ) { + // channelDesc->path_loss_dB should contain the total path gain + // so, in actual RF: tx gain + path loss + rx gain (+antenna gain, ...) + // UE and NB gain control to be added + // Fixme: not sure when it is "volts" so dB is 20*log10(...) or "power", so dB is 10*log10(...) + const double pathLossLinear = pow(10,channelDesc->path_loss_dB/20.0); + // Energy in one sample to calibrate input noise + //Fixme: modified the N0W computation, not understand the origin value + const double KT=1.38e-23*290; //Boltzman*temperature + // sampling rate is linked to acquisition band (the input pass band filter) + const double noise_figure_watt = KT*channelDesc->sampling_rate; + // Fixme: how to convert a noise in Watt into a 12 bits value out of the RF ADC ? + // the parameter "-s" is declared as SNR, but the input power is not well defined + // −132.24 dBm is a LTE subcarrier noise, that was used in origin code (15KHz BW thermal noise) + const double rxGain= 132.24 - snr_dB; + // sqrt(4*noise_figure_watt) is the thermal noise factor (volts) + // fixme: the last constant is pure trial results to make decent noise + const double noise_per_sample = sqrt(4*noise_figure_watt) * pow(10,rxGain/20) *10; + // Fixme: we don't fill the offset length samples at begining ? + // anyway, in today code, channel_offset=0 + const int dd = abs(channelDesc->channel_offset); + const int nbTx=channelDesc->nb_tx; + + for (int i=0; i<((int)nbSamples-dd); i++) { + struct complex16 *out_ptr=after_channel_sig+dd+i; + struct complex rx_tmp= {0}; + + for (int txAnt=0; txAnt < nbTx; txAnt++) { + const struct complex *channelModel= channelDesc->ch[rxAnt+(txAnt*channelDesc->nb_rx)]; + + //const struct complex *channelModelEnd=channelModel+channelDesc->channel_length; + for (int l = 0; l<(int)channelDesc->channel_length; l++) { + // let's assume TS+i >= l + // fixme: the rfsimulator current structure is interleaved antennas + // this has been designed to not have to wait a full block transmission + // but it is not very usefull + // it would be better to split out each antenna in a separate flow + // that will allow to mix ru antennas freely + struct complex16 tx16=input_sig[((TS+i-l)*nbTx+txAnt)%CirSize]; + rx_tmp.x += tx16.r * channelModel[l].x - tx16.i * channelModel[l].y; + rx_tmp.y += tx16.i * channelModel[l].x + tx16.r * channelModel[l].y; + } //l + } + + out_ptr->r += round(rx_tmp.x*pathLossLinear + noise_per_sample*gaussdouble(0.0,1.0)); + out_ptr->i += round(rx_tmp.y*pathLossLinear + noise_per_sample*gaussdouble(0.0,1.0)); + out_ptr++; + } + + if ( (TS*nbTx)%CirSize+nbSamples <= CirSize ) + // Cast to a wrong type for compatibility ! + LOG_D(HW,"Input power %f, output power: %f, channel path loss %f, noise coeff: %f \n", + 10*log10((double)signal_energy((int32_t *)&input_sig[(TS*nbTx)%CirSize], nbSamples)), + 10*log10((double)signal_energy((int32_t *)after_channel_sig, nbSamples)), + channelDesc->path_loss_dB, + 10*log10(noise_per_sample)); +} + void allocCirBuf(rfsimulator_state_t *bridge, int sock) { buffer_t *ptr=&bridge->buf[sock]; AssertFatal ( (ptr->circularBuf=(sample_t *) malloc(sampleToByte(CirSize,1))) != NULL, ""); ptr->circularBufEnd=((char *)ptr->circularBuf)+sampleToByte(CirSize,1); ptr->conn_sock=sock; + ptr->alreadyRead=false; + ptr->lastReceivedTS=0; ptr->headerMode=true; ptr->transferPtr=(char *)&ptr->th; - ptr->remainToTransfer=sizeof(transferHeader); + ptr->remainToTransfer=sizeof(samplesBlockHeader_t); int sendbuff=1000*1000*10; AssertFatal ( setsockopt(sock, SOL_SOCKET, SO_SNDBUF, &sendbuff, sizeof(sendbuff)) == 0, ""); struct epoll_event ev= {0}; ev.events = EPOLLIN | EPOLLRDHUP; ev.data.fd = sock; AssertFatal(epoll_ctl(bridge->epollfd, EPOLL_CTL_ADD, sock, &ev) != -1, ""); + // create channel simulation model for this mode reception + // snr_dB is pure global, coming from configuration paramter "-s" + // Fixme: referenceSignalPower should come from the right place + // but the datamodel is inconsistant + // legacy: RC.ru[ru_id]->frame_parms.pdsch_config_common.referenceSignalPower + // (must not come from ru[]->frame_parms as it doesn't belong to ru !!!) + // Legacy sets it as: + // ptr->channel_model->path_loss_dB = -132.24 + snr_dB - RC.ru[0]->frame_parms->pdsch_config_common.referenceSignalPower; + // we use directly the paramter passed on the command line ("-s") + // the value channel_model->path_loss_dB seems only a storage place (new_channel_desc_scm() only copy the passed value) + // Legacy changes directlty the variable channel_model->path_loss_dB place to place + // while calling new_channel_desc_scm() with path losses = 0 + ptr->channel_model=new_channel_desc_scm(bridge->tx_num_channels,bridge->rx_num_channels, + AWGN, + bridge->sample_rate, + bridge->tx_bw, + 0.0, // forgetting_factor + 0, // maybe used for TA + 0); // path_loss in dB + random_channel(ptr->channel_model,false); } void removeCirBuf(rfsimulator_state_t *bridge, int sock) { AssertFatal( epoll_ctl(bridge->epollfd, EPOLL_CTL_DEL, sock, NULL) != -1, ""); close(sock); free(bridge->buf[sock].circularBuf); + // Fixme: no free_channel_desc_scm(bridge->buf[sock].channel_model) implemented + // a lot of mem leaks + free(bridge->buf[sock].channel_model); memset(&bridge->buf[sock], 0, sizeof(buffer_t)); bridge->buf[sock].conn_sock=-1; } @@ -87,12 +196,11 @@ void socketError(rfsimulator_state_t *bridge, int sock) { LOG_W(HW,"Lost socket \n"); removeCirBuf(bridge, sock); - if (bridge->typeStamp==MAGICUE) + if (bridge->typeStamp==UE_MAGICDL_FDD) exit(1); } } - #define helpTxt "\ \x1b[31m\ rfsimulator: error: you have to run one UE and one eNB\n\ @@ -117,11 +225,18 @@ void setblocking(int sock, enum blocking_t active) { AssertFatal(fcntl(sock, F_SETFL, opts) >= 0, ""); } -static bool flushInput(rfsimulator_state_t *t); +static bool flushInput(rfsimulator_state_t *t, int timeout); -void fullwrite(int fd, void *_buf, int count, rfsimulator_state_t *t) { +void fullwrite(int fd, void *_buf, ssize_t count, rfsimulator_state_t *t) { + if (t->saveIQfile != -1) { + if (write(t->saveIQfile, _buf, count) != count ) + LOG_E(HW,"write in save iq file failed (%s)\n",strerror(errno)); + } + + AssertFatal(fd>=0 && _buf && count >0 && t, + "Bug: %d/%p/%zd/%p", fd, _buf, count, t); char *buf = _buf; - int l; + ssize_t l; setblocking(fd, notBlocking); while (count) { @@ -132,7 +247,9 @@ void fullwrite(int fd, void *_buf, int count, rfsimulator_state_t *t) { continue; if(errno==EAGAIN) { - flushInput(t); + // The opposite side is saturated + // we read incoming sockets meawhile waiting + flushInput(t, 5); continue; } else return; @@ -145,7 +262,7 @@ void fullwrite(int fd, void *_buf, int count, rfsimulator_state_t *t) { int server_start(openair0_device *device) { rfsimulator_state_t *t = (rfsimulator_state_t *) device->priv; - t->typeStamp=MAGICeNB; + t->typeStamp=ENB_MAGICDL_FDD; AssertFatal((t->listen_sock = socket(AF_INET, SOCK_STREAM, 0)) >= 0, ""); int enable = 1; AssertFatal(setsockopt(t->listen_sock, SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(int)) == 0, ""); @@ -168,7 +285,7 @@ sin_addr: int start_ue(openair0_device *device) { rfsimulator_state_t *t = device->priv; - t->typeStamp=MAGICUE; + t->typeStamp=UE_MAGICDL_FDD; int sock; AssertFatal((sock = socket(AF_INET, SOCK_STREAM, 0)) >= 0, ""); struct sockaddr_in addr = { @@ -200,14 +317,16 @@ sin_addr: return 0; } +uint64_t lastW=-1; int rfsimulator_write(openair0_device *device, openair0_timestamp timestamp, void **samplesVoid, int nsamps, int nbAnt, int flags) { rfsimulator_state_t *t = device->priv; + LOG_D(HW,"sending %d samples at time: %ld\n", nsamps, timestamp); for (int i=0; ibuf[i]; if (ptr->conn_sock >= 0 ) { - transferHeader header= {t->typeStamp, nsamps, nbAnt, timestamp}; + samplesBlockHeader_t header= {t->typeStamp, nsamps, nbAnt, timestamp}; fullwrite(ptr->conn_sock,&header, sizeof(header), t); sample_t tmpSamples[nsamps][nbAnt]; @@ -223,21 +342,27 @@ int rfsimulator_write(openair0_device *device, openair0_timestamp timestamp, voi } } + lastW=timestamp; LOG_D(HW,"sent %d samples at time: %ld->%ld, energy in first antenna: %d\n", nsamps, timestamp, timestamp+nsamps, signal_energy(samplesVoid[0], nsamps) ); + // Let's verify we don't have incoming data + // This is mandatory when the opposite side don't transmit + // This is mandatory when the opposite side don't transmit + flushInput(t, 0); + pthread_mutex_unlock(&Sockmutex); return nsamps; } -static bool flushInput(rfsimulator_state_t *t) { +static bool flushInput(rfsimulator_state_t *t, int timeout) { // Process all incoming events on sockets // store the data in lists struct epoll_event events[FD_SETSIZE]= {0}; - int nfds = epoll_wait(t->epollfd, events, FD_SETSIZE, 200); + int nfds = epoll_wait(t->epollfd, events, FD_SETSIZE, timeout); if ( nfds==-1 ) { - if ( errno==EINTR || errno==EAGAIN ) + if ( errno==EINTR || errno==EAGAIN ) { return false; - else + } else AssertFatal(false,"error in epoll_wait\n"); } @@ -263,7 +388,7 @@ static bool flushInput(rfsimulator_state_t *t) { continue; } - int blockSz; + ssize_t blockSz; if ( b->headerMode) blockSz=b->remainToTransfer; @@ -272,7 +397,7 @@ static bool flushInput(rfsimulator_state_t *t) { b->remainToTransfer : b->circularBufEnd - 1 - b->transferPtr ; - int sz=recv(fd, b->transferPtr, blockSz, MSG_DONTWAIT); + ssize_t sz=recv(fd, b->transferPtr, blockSz, MSG_DONTWAIT); if ( sz < 0 ) { if ( errno != EAGAIN ) { @@ -282,6 +407,7 @@ static bool flushInput(rfsimulator_state_t *t) { } else if ( sz == 0 ) continue; + LOG_D(HW, "Socket rcv %zd bytes\n", sz); AssertFatal((b->remainToTransfer-=sz) >= 0, ""); b->transferPtr+=sz; @@ -290,39 +416,44 @@ static bool flushInput(rfsimulator_state_t *t) { // check the header and start block transfer if ( b->headerMode==true && b->remainToTransfer==0) { - AssertFatal( (t->typeStamp == MAGICUE && b->th.magic==MAGICeNB) || - (t->typeStamp == MAGICeNB && b->th.magic==MAGICUE), "Socket Error in protocol"); + AssertFatal( (t->typeStamp == UE_MAGICDL_FDD && b->th.magic==ENB_MAGICDL_FDD) || + (t->typeStamp == ENB_MAGICDL_FDD && b->th.magic==UE_MAGICDL_FDD), "Socket Error in protocol"); b->headerMode=false; b->alreadyRead=true; if ( b->lastReceivedTS != b->th.timestamp) { int nbAnt= b->th.nbAnt; - for (uint64_t index=b->lastReceivedTS; index < b->th.timestamp; index++ ) - for (int a=0; a < nbAnt; a++) - b->circularBuf[(index*nbAnt+a)%CirSize]=0; + for (uint64_t index=b->lastReceivedTS; index < b->th.timestamp; index++ ) { + for (int a=0; a < nbAnt; a++) { + b->circularBuf[(index*nbAnt+a)%CirSize].r=0; + b->circularBuf[(index*nbAnt+a)%CirSize].i=0; + } + } LOG_W(HW,"gap of: %ld in reception\n", b->th.timestamp-b->lastReceivedTS ); } b->lastReceivedTS=b->th.timestamp; + AssertFatal(lastW == -1 || ( abs((double)lastW-b->lastReceivedTS) < (double)CirSize), + "Tx/Rx shift too large Tx:%lu, Rx:%lu\n", lastW, b->lastReceivedTS); b->transferPtr=(char *)&b->circularBuf[b->lastReceivedTS%CirSize]; b->remainToTransfer=sampleToByte(b->th.size, b->th.nbAnt); } if ( b->headerMode==false ) { + LOG_D(HW,"Set b->lastReceivedTS %ld\n", b->lastReceivedTS); b->lastReceivedTS=b->th.timestamp+b->th.size-byteToSample(b->remainToTransfer,b->th.nbAnt); - - if ( b->remainToTransfer==0) { - LOG_D(HW,"Completed block reception: %ld\n", b->lastReceivedTS); - + // First block in UE, resync with the eNB current TS if ( t->nextTimestamp == 0 ) t->nextTimestamp=b->lastReceivedTS-b->th.size; + if ( b->remainToTransfer==0) { + LOG_D(HW,"Completed block reception: %ld\n", b->lastReceivedTS); b->headerMode=true; b->transferPtr=(char *)&b->th; - b->remainToTransfer=sizeof(transferHeader); + b->remainToTransfer=sizeof(samplesBlockHeader_t); b->th.magic=-1; } } @@ -334,10 +465,10 @@ static bool flushInput(rfsimulator_state_t *t) { int rfsimulator_read(openair0_device *device, openair0_timestamp *ptimestamp, void **samplesVoid, int nsamps, int nbAnt) { if (nbAnt != 1) { - LOG_E(HW, "rfsimulator: only 1 antenna tested\n"); - exit(1); + LOG_W(HW, "rfsimulator: only 1 antenna tested\n"); } + pthread_mutex_lock(&Sockmutex); rfsimulator_state_t *t = device->priv; LOG_D(HW, "Enter rfsimulator_read, expect %d samples, will release at TS: %ld\n", nsamps, t->nextTimestamp+nsamps); // deliver data from received data @@ -350,13 +481,14 @@ int rfsimulator_read(openair0_device *device, openair0_timestamp *ptimestamp, vo if ( first_sock == FD_SETSIZE ) { // no connected device (we are eNB, no UE is connected) - if (!flushInput(t)) { + if (!flushInput(t, 10)) { for (int x=0; x < nbAnt; x++) memset(samplesVoid[x],0,sampleToByte(nsamps,1)); t->nextTimestamp+=nsamps; LOG_W(HW,"Generated void samples for Rx: %ld\n", t->nextTimestamp); *ptimestamp = t->nextTimestamp-nsamps; + pthread_mutex_unlock(&Sockmutex); return nsamps; } } else { @@ -365,12 +497,13 @@ int rfsimulator_read(openair0_device *device, openair0_timestamp *ptimestamp, vo do { have_to_wait=false; - for ( int sock=0; sockbuf[sock].circularBuf && - t->buf[sock].alreadyRead && //>= t->initialAhead && + for ( int sock=0; sockbuf[sock].circularBuf && t->buf[sock].alreadyRead ) + if ( t->buf[sock].lastReceivedTS == 0 || (t->nextTimestamp+nsamps) > t->buf[sock].lastReceivedTS ) { have_to_wait=true; break; + } } if (have_to_wait) @@ -378,7 +511,7 @@ int rfsimulator_read(openair0_device *device, openair0_timestamp *ptimestamp, vo ptr->lastReceivedTS, t->nextTimestamp+nsamps); */ - flushInput(t); + flushInput(t, 3); } while (have_to_wait); } @@ -391,12 +524,20 @@ int rfsimulator_read(openair0_device *device, openair0_timestamp *ptimestamp, vo buffer_t *ptr=&t->buf[sock]; if ( ptr->circularBuf && ptr->alreadyRead ) { - for (int a=0; acircularBuf[((t->nextTimestamp+i)*nbAnt+a)%CirSize]<<1; - } + //fixme: when do we regenerate + // it seems legacy behavior is: never in UL, each frame in DL + if (reGenerateChannel) + random_channel(ptr->channel_model,0); + + for (int a=0; acircularBuf, (struct complex16 *) samplesVoid[a], + a, + ptr->channel_model, + nsamps, + t->nextTimestamp + ); } } @@ -406,10 +547,9 @@ int rfsimulator_read(openair0_device *device, openair0_timestamp *ptimestamp, vo nsamps, *ptimestamp, t->nextTimestamp, signal_energy(samplesVoid[0], nsamps)); + pthread_mutex_unlock(&Sockmutex); return nsamps; } - - int rfsimulator_request(openair0_device *device, void *msg, ssize_t msg_len) { abort(); return 0; @@ -434,10 +574,10 @@ int rfsimulator_set_freq(openair0_device *device, openair0_config_t *openair0_cf int rfsimulator_set_gains(openair0_device *device, openair0_config_t *openair0_cfg) { return 0; } - - __attribute__((__visibility__("default"))) int device_init(openair0_device *device, openair0_config_t *openair0_cfg) { + // to change the log level, use this on command line + // --log_config.hw_log_level debug //set_log(HW,OAILOG_DEBUG); rfsimulator_state_t *rfsimulator = (rfsimulator_state_t *)calloc(sizeof(rfsimulator_state_t),1); @@ -446,11 +586,28 @@ int device_init(openair0_device *device, openair0_config_t *openair0_cfg) { exit(1); } - rfsimulator->typeStamp = strncasecmp(rfsimulator->ip,"enb",3) == 0 ? - MAGICeNB: - MAGICUE; - LOG_I(HW,"rfsimulator: running as %s\n", rfsimulator-> typeStamp == MAGICeNB ? "eNB" : "UE"); - device->trx_start_func = rfsimulator->typeStamp == MAGICeNB ? + pthread_mutex_init(&Sockmutex, NULL); + + if ( strncasecmp(rfsimulator->ip,"enb",3) == 0 || + strncasecmp(rfsimulator->ip,"server",3) == 0 ) + rfsimulator->typeStamp = ENB_MAGICDL_FDD; + else + rfsimulator->typeStamp = UE_MAGICDL_FDD; + + LOG_I(HW,"rfsimulator: running as %s\n", rfsimulator-> typeStamp == ENB_MAGICDL_FDD ? "(eg)NB" : "UE"); + char *saveF; + + if ((saveF=getenv("saveIQfile")) != NULL) { + rfsimulator->saveIQfile=open(saveF,O_APPEND| O_CREAT|O_TRUNC | O_WRONLY, 0666); + + if ( rfsimulator->saveIQfile != -1 ) + LOG_I(HW,"rfsimulator: will save written IQ samples in %s\n", saveF); + else + LOG_E(HW, "can't open %s for IQ saving (%s)\n", saveF, strerror(errno)); + } else + rfsimulator->saveIQfile = -1; + + device->trx_start_func = rfsimulator->typeStamp == ENB_MAGICDL_FDD ? server_start : start_ue; device->trx_get_stats_func = rfsimulator_get_stats; @@ -470,6 +627,12 @@ int device_init(openair0_device *device, openair0_config_t *openair0_cfg) { rfsimulator->buf[i].conn_sock=-1; AssertFatal((rfsimulator->epollfd = epoll_create1(0)) != -1,""); - rfsimulator->initialAhead=openair0_cfg[0].sample_rate/1000; // One sub frame + // initialize channel simulation + rfsimulator->tx_num_channels=openair0_cfg->tx_num_channels; + rfsimulator->rx_num_channels=openair0_cfg->rx_num_channels; + rfsimulator->sample_rate=openair0_cfg->sample_rate; + rfsimulator->tx_bw=openair0_cfg->tx_bw; + randominit(0); + set_taus_seed(0); return 0; } diff --git a/targets/ARCH/rfsimulator/stored_node.c b/targets/ARCH/rfsimulator/stored_node.c new file mode 100644 index 0000000000..888b5f6de0 --- /dev/null +++ b/targets/ARCH/rfsimulator/stored_node.c @@ -0,0 +1,142 @@ +/* + Author: Laurent THOMAS, Open Cells + copyleft: OpenAirInterface Software Alliance and it's licence +*/ + +#include + + +void fullwrite(int fd, void *_buf, int count) { + char *buf = _buf; + int l; + + while (count) { + l = write(fd, buf, count); + + if (l <= 0) { + if (errno==EINTR) + continue; + + if(errno==EAGAIN) { + continue; + } else { + AssertFatal(false,"Lost socket\n"); + } + } else { + count -= l; + buf += l; + } + } +} + +int server_start(short port) { + int listen_sock; + AssertFatal((listen_sock = socket(AF_INET, SOCK_STREAM, 0)) >= 0, ""); + int enable = 1; + AssertFatal(setsockopt(listen_sock, SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(int)) == 0, ""); + struct sockaddr_in addr = { +sin_family: + AF_INET, +sin_port: + htons(port), +sin_addr: + { s_addr: INADDR_ANY } + }; + bind(listen_sock, (struct sockaddr *)&addr, sizeof(addr)); + AssertFatal(listen(listen_sock, 5) == 0, ""); + return accept(listen_sock,NULL,NULL); +} + +int client_start(char *IP, short port) { + int sock; + AssertFatal((sock = socket(AF_INET, SOCK_STREAM, 0)) >= 0, ""); + struct sockaddr_in addr = { +sin_family: + AF_INET, +sin_port: + htons(port), +sin_addr: + { s_addr: INADDR_ANY } + }; + addr.sin_addr.s_addr = inet_addr(IP); + bool connected=false; + + while(!connected) { + LOG_I(HW,"rfsimulator: trying to connect to %s:%d\n", IP, port); + + if (connect(sock, (struct sockaddr *)&addr, sizeof(addr)) == 0) { + LOG_I(HW,"rfsimulator: connection established\n"); + connected=true; + } + + perror("simulated node"); + sleep(1); + } + + return sock; +} + +enum blocking_t { + notBlocking, + blocking +}; + +void setblocking(int sock, enum blocking_t active) { + int opts; + AssertFatal( (opts = fcntl(sock, F_GETFL)) >= 0,""); + + if (active==blocking) + opts = opts & ~O_NONBLOCK; + else + opts = opts | O_NONBLOCK; + + AssertFatal(fcntl(sock, F_SETFL, opts) >= 0, ""); +} + +int main(int argc, char *argv[]) { + if(argc != 4) { + printf("Need parameters: source file, server or destination IP, TCP port\n"); + exit(1); + } + + int fd; + AssertFatal((fd=open(argv[1],O_RDONLY)) != -1, "file: %s", argv[1]); + off_t fileSize=lseek(fd, 0, SEEK_END); + int serviceSock; + + if (strcmp(argv[2],"server")==0) { + serviceSock=server_start(atoi(argv[3])); + } else { + client_start(argv[2],atoi(argv[3])); + } + + samplesBlockHeader_t header; + int bufSize=100000; + void *buff=malloc(bufSize); + + while (1) { + //Rewind the file to loop on the samples + if ( lseek(fd, 0, SEEK_CUR) >= fileSize ) + lseek(fd, 0, SEEK_SET); + + // Read one block and send it + setblocking(serviceSock, blocking); + AssertFatal(read(fd,&header,sizeof(header)), ""); + fullwrite(serviceSock, &header, sizeof(header)); + int dataSize=sizeof(sample_t)*header.size*header.nbAnt; + + if (dataSize>bufSize) + buff=realloc(buff,dataSize); + + AssertFatal(read(fd,buff,dataSize) == dataSize, ""); + fullwrite(serviceSock, buff, dataSize); + // Purge incoming samples + setblocking(serviceSock, notBlocking); + + while(recv(serviceSock,buff, bufSize, MSG_DONTWAIT) > 0) { + } + } + + return 0; +} + diff --git a/targets/RT/USER/lte-softmodem-common.c b/targets/RT/USER/lte-softmodem-common.c index f152e7c83d..dd91f54004 100644 --- a/targets/RT/USER/lte-softmodem-common.c +++ b/targets/RT/USER/lte-softmodem-common.c @@ -34,9 +34,11 @@ #include "UTIL/OPT/opt.h" #include "common/config/config_userapi.h" #include "common/utils/load_module_shlib.h" +#include static softmodem_params_t softmodem_params; char *parallel_config=NULL; char *worker_config=NULL; +double snr_dB=25; uint64_t get_softmodem_optmask(void) { return softmodem_params.optmask; diff --git a/targets/RT/USER/lte-softmodem.h b/targets/RT/USER/lte-softmodem.h index 987db67b00..b9a775509d 100644 --- a/targets/RT/USER/lte-softmodem.h +++ b/targets/RT/USER/lte-softmodem.h @@ -152,7 +152,6 @@ {"usrp-clksrc", CONFIG_HLP_USRP_CLK_SRC,0, strptr:(char **)&usrp_clksrc, defstrval:"internal", TYPE_STRING, 0}, \ {"mmapped-dma", CONFIG_HLP_DMAMAP, PARAMFLAG_BOOL, uptr:&mmapped_dma, defintval:0, TYPE_INT, 0}, \ {"clock", CONFIG_HLP_CLK, 0, uptr:&clock_source, defintval:0, TYPE_UINT, 0}, \ - {"s" , CONFIG_HLP_SNR, 0, iptr:&snr_dB, defintval:25, TYPE_INT, 0}, \ {"T" , CONFIG_HLP_TDD, PARAMFLAG_BOOL, iptr:&tddflag, defintval:0, TYPE_INT, 0}, \ {"A", CONFIG_HLP_TADV, 0, iptr:&(timingadv), defintval:0, TYPE_INT, 0} \ } @@ -201,6 +200,7 @@ {"d" , CONFIG_HLP_SOFTS, PARAMFLAG_BOOL, uptr:(uint32_t *)&do_forms, defintval:0, TYPE_INT8, 0}, \ {"q" , CONFIG_HLP_STMON, PARAMFLAG_BOOL, iptr:&opp_enabled, defintval:0, TYPE_INT, 0}, \ {"S" , CONFIG_HLP_MSLOTS, PARAMFLAG_BOOL, u8ptr:&exit_missed_slots, defintval:1, TYPE_UINT8, 0}, \ + {"s" , CONFIG_HLP_SNR, 0, dblptr:&snr_dB, defdblval:25, TYPE_DOUBLE, 0}, \ {"numerology" , CONFIG_HLP_NUMEROLOGY, PARAMFLAG_BOOL, iptr:&NUMEROLOGY, defintval:0, TYPE_INT, 0}, \ {"parallel-config", CONFIG_HLP_PARALLEL_CMD,0, strptr:(char **)¶llel_config, defstrval:NULL, TYPE_STRING, 0}, \ {"worker-config", CONFIG_HLP_WORKER_CMD, 0, strptr:(char **)&worker_config, defstrval:NULL, TYPE_STRING, 0}, \ @@ -283,6 +283,7 @@ uint64_t get_pdcp_optmask(void); extern pthread_cond_t sync_cond; extern pthread_mutex_t sync_mutex; extern int sync_var; +extern double snr_dB; extern uint32_t downlink_frequency[MAX_NUM_CCs][4]; diff --git a/targets/RT/USER/lte-uesoftmodem.c b/targets/RT/USER/lte-uesoftmodem.c index eb510e5ff2..d9b03ac5fd 100644 --- a/targets/RT/USER/lte-uesoftmodem.c +++ b/targets/RT/USER/lte-uesoftmodem.c @@ -132,8 +132,6 @@ int32_t uplink_frequency_offset[MAX_NUM_CCs][4]; int UE_scan = 1; int UE_scan_carrier = 0; -int snr_dB=25; - runmode_t mode = normal_txrx; FILE *input_fd=NULL; From d2a6cca8f9be0d8a4061a64122698e4ceba9a291 Mon Sep 17 00:00:00 2001 From: Raphael Defosseux Date: Thu, 4 Jul 2019 12:58:55 +0200 Subject: [PATCH 28/32] CI: better detection for segmentation fault Signed-off-by: Raphael Defosseux --- ci-scripts/main.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/ci-scripts/main.py b/ci-scripts/main.py index 0e7e8feb80..3384a29b3e 100644 --- a/ci-scripts/main.py +++ b/ci-scripts/main.py @@ -2546,6 +2546,9 @@ class SSHConnection(): if result is not None and not exitSignalReceived: foundSegFault = True result = re.search('[Cc]ore [dD]ump', str(line)) + if result is not None and not exitSignalReceived: + foundSegFault = True + result = re.search('./lte_build_oai/build/lte-softmodem', str(line)) if result is not None and not exitSignalReceived: foundSegFault = True result = re.search('[Aa]ssertion', str(line)) @@ -2688,6 +2691,9 @@ class SSHConnection(): if result is not None and not exitSignalReceived: foundSegFault = True result = re.search('[Cc]ore [dD]ump', str(line)) + if result is not None and not exitSignalReceived: + foundSegFault = True + result = re.search('./lte-uesoftmodem', str(line)) if result is not None and not exitSignalReceived: foundSegFault = True result = re.search('[Aa]ssertion', str(line)) From e0eac2e3319fd51ef0c6c101e2dffff24ba738b4 Mon Sep 17 00:00:00 2001 From: Cedric Roux Date: Thu, 4 Jul 2019 14:47:11 +0200 Subject: [PATCH 29/32] hotfix: do not set s-Measure in measurement report configuration The value was set to 20 which means -120 dB. Setting this value means that the UE reports an event only if the RSRP of the serving cell is lower than -120 dB. In the lab, we get values of around -70, and to go as low as -120 means a very degraded environment. This is not practical. Let's disactivate the setting of this parameter for the moment so that the UE reports an event without taking into consideration the RSRP of the serving cell. With this hotfix, the X2 handover works much better. --- openair2/RRC/LTE/rrc_eNB.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/openair2/RRC/LTE/rrc_eNB.c b/openair2/RRC/LTE/rrc_eNB.c index 230b9511f0..6a038c51a0 100644 --- a/openair2/RRC/LTE/rrc_eNB.c +++ b/openair2/RRC/LTE/rrc_eNB.c @@ -1893,8 +1893,15 @@ rrc_eNB_process_RRCConnectionReestablishmentComplete( ReportConfig_A5->reportConfig.choice.reportConfigEUTRA.reportAmount = LTE_ReportConfigEUTRA__reportAmount_infinity; ASN_SEQUENCE_ADD(&ReportConfig_list->list, ReportConfig_A5); // LTE_RRCConnectionReconfiguration->criticalExtensions.choice.c1.choice.rrcConnectionReconfiguration_r8.measConfig->reportConfigToAddModList = ReportConfig_list; +#if 0 + /* TODO: set a proper value. + * 20 means: UE does not report if RSRP of serving cell is higher + * than -120 dB (see 36.331 5.5.3.1). + * This is too low for the X2 handover experiment. + */ rsrp = CALLOC(1, sizeof(LTE_RSRP_Range_t)); *rsrp = 20; +#endif Sparams = CALLOC(1, sizeof(*Sparams)); Sparams->present = LTE_MeasConfig__speedStatePars_PR_setup; Sparams->choice.setup.timeToTrigger_SF.sf_High = LTE_SpeedStateScaleFactors__sf_Medium_oDot75; @@ -3416,8 +3423,15 @@ void rrc_eNB_generate_defaultRRCConnectionReconfiguration(const protocol_ctxt_t ReportConfig_A5->reportConfig.choice.reportConfigEUTRA.reportAmount = LTE_ReportConfigEUTRA__reportAmount_infinity; ASN_SEQUENCE_ADD(&ReportConfig_list->list, ReportConfig_A5); // LTE_RRCConnectionReconfiguration->criticalExtensions.choice.c1.choice.rrcConnectionReconfiguration_r8.measConfig->reportConfigToAddModList = ReportConfig_list; +#if 0 + /* TODO: set a proper value. + * 20 means: UE does not report if RSRP of serving cell is higher + * than -120 dB (see 36.331 5.5.3.1). + * This is too low for the X2 handover experiment. + */ rsrp = CALLOC(1, sizeof(LTE_RSRP_Range_t)); *rsrp = 20; +#endif Sparams = CALLOC(1, sizeof(*Sparams)); Sparams->present = LTE_MeasConfig__speedStatePars_PR_setup; Sparams->choice.setup.timeToTrigger_SF.sf_High = LTE_SpeedStateScaleFactors__sf_Medium_oDot75; @@ -5401,8 +5415,15 @@ rrc_eNB_generate_HO_RRCConnectionReconfiguration(const protocol_ctxt_t *const ct ReportConfig_A5->reportConfig.choice.reportConfigEUTRA.reportAmount = LTE_ReportConfigEUTRA__reportAmount_infinity; ASN_SEQUENCE_ADD(&ReportConfig_list->list, ReportConfig_A5); // rrcConnectionReconfiguration->criticalExtensions.choice.c1.choice.rrcConnectionReconfiguration_r8.measConfig->reportConfigToAddModList = ReportConfig_list; +#if 0 + /* TODO: set a proper value. + * 20 means: UE does not report if RSRP of serving cell is higher + * than -120 dB (see 36.331 5.5.3.1). + * This is too low for the X2 handover experiment. + */ rsrp = CALLOC(1, sizeof(RSRP_Range_t)); *rsrp = 20; +#endif Sparams = CALLOC(1, sizeof(*Sparams)); Sparams->present = LTE_MeasConfig__speedStatePars_PR_setup; Sparams->choice.setup.timeToTrigger_SF.sf_High = LTE_SpeedStateScaleFactors__sf_Medium_oDot75; From 3f2acf94852d6ca3f53a35f9d86ae19204da73f8 Mon Sep 17 00:00:00 2001 From: Raphael Defosseux Date: Fri, 5 Jul 2019 11:03:30 +0200 Subject: [PATCH 30/32] Fix Coverity Scan CID 342010 Fix a few cppcheck errors/warnings Signed-off-by: Raphael Defosseux --- .../ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac.c | 1 - openair2/LAYER2/RLC/AM_v9.3.0/rlc_am_status_report.c | 2 +- openair3/NAS/COMMON/API/NETWORK/nas_message.c | 12 ++++++++---- targets/ARCH/rfsimulator/stored_node.c | 11 +++++++++-- targets/RT/USER/lte-enb.c | 4 ++-- 5 files changed, 20 insertions(+), 10 deletions(-) diff --git a/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac.c b/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac.c index 45ac61a927..51ec781de3 100644 --- a/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac.c +++ b/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac.c @@ -826,7 +826,6 @@ int flexran_agent_mac_stats_reply(mid_t mod_id, } } free(ue_report); - ue_report = NULL; } return -1; diff --git a/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am_status_report.c b/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am_status_report.c index 5c68aecf61..ddff2cc3d1 100644 --- a/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am_status_report.c +++ b/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am_status_report.c @@ -235,7 +235,7 @@ rlc_am_receive_process_control_pdu( rlc_sn_t ack_sn = RLC_AM_NEXT_SN(rlc_pP->vt_a); rlc_sn_t sn_cursor = rlc_pP->vt_a; rlc_sn_t vt_a_new = rlc_pP->vt_a; - rlc_sn_t sn_data_cnf; + rlc_sn_t sn_data_cnf = (rlc_sn_t) 0; rlc_sn_t nack_sn,prev_nack_sn; sdu_size_t data_cnf_so_stop = 0x7FFF; unsigned int nack_index; diff --git a/openair3/NAS/COMMON/API/NETWORK/nas_message.c b/openair3/NAS/COMMON/API/NETWORK/nas_message.c index 4eea2c4d6b..769eab5260 100644 --- a/openair3/NAS/COMMON/API/NETWORK/nas_message.c +++ b/openair3/NAS/COMMON/API/NETWORK/nas_message.c @@ -267,7 +267,7 @@ int nas_message_decrypt( { LOG_FUNC_IN; - emm_security_context_t *emm_security_context = (emm_security_context_t*)security; + emm_security_context_t *emm_security_context = NULL; int bytes = length; /* Decode the header */ @@ -277,7 +277,8 @@ int nas_message_decrypt( LOG_TRACE(DEBUG, "MESSAGE TOO SHORT"); LOG_FUNC_RETURN (TLV_DECODE_BUFFER_TOO_SHORT); } else if (size > 1) { - if (emm_security_context) { + if (security) { + emm_security_context = (emm_security_context_t*)security; #if defined(NAS_MME) if (emm_security_context->ul_count.seq_num > header->sequence_number) { @@ -376,7 +377,7 @@ int nas_message_decode( void *security) { LOG_FUNC_IN; - emm_security_context_t *emm_security_context = (emm_security_context_t*)security; + emm_security_context_t *emm_security_context = NULL; int bytes; /* Decode the header */ @@ -385,7 +386,8 @@ int nas_message_decode( if (size < 0) { LOG_FUNC_RETURN (TLV_DECODE_BUFFER_TOO_SHORT); } else if (size > 1) { - if (emm_security_context) { + if (security) { + emm_security_context = (emm_security_context_t*)security; #if defined(NAS_MME) if (emm_security_context->ul_count.seq_num > msg->header.sequence_number) { @@ -971,6 +973,8 @@ static int _nas_message_decrypt( #else direction = SECU_DIRECTION_DOWNLINK; #endif + if (emm_security_context == NULL) + LOG_FUNC_RETURN (0); switch (security_header_type) { case SECURITY_HEADER_TYPE_NOT_PROTECTED: diff --git a/targets/ARCH/rfsimulator/stored_node.c b/targets/ARCH/rfsimulator/stored_node.c index 888b5f6de0..a23127d3b5 100644 --- a/targets/ARCH/rfsimulator/stored_node.c +++ b/targets/ARCH/rfsimulator/stored_node.c @@ -125,8 +125,15 @@ int main(int argc, char *argv[]) { fullwrite(serviceSock, &header, sizeof(header)); int dataSize=sizeof(sample_t)*header.size*header.nbAnt; - if (dataSize>bufSize) - buff=realloc(buff,dataSize); + if (dataSize>bufSize) { + void * new_buff = realloc(buff, dataSize); + if (new_buff == NULL) { + free(buff); + AssertFatal(1, "Could not reallocate"); + } else { + buff = new_buff; + } + } AssertFatal(read(fd,buff,dataSize) == dataSize, ""); fullwrite(serviceSock, buff, dataSize); diff --git a/targets/RT/USER/lte-enb.c b/targets/RT/USER/lte-enb.c index 89a82604ca..3105b7c855 100644 --- a/targets/RT/USER/lte-enb.c +++ b/targets/RT/USER/lte-enb.c @@ -508,9 +508,9 @@ int wakeup_txfh(PHY_VARS_eNB *eNB, L1_rxtx_proc_t *proc,int frame_tx,int subfram if (((fp->frame_type == TDD) && (subframe_select(fp,proc->subframe_tx)==SF_UL))|| (eNB->RU_list[ru_id]->state == RU_SYNC)|| (eNB->RU_list[ru_id]->wait_cnt>0)){ - AssertFatal((pthread_mutex_lock(&proc->mutex_RUs))==0, "mutex_lock returns %d\n",ret); + AssertFatal((ret=pthread_mutex_lock(&proc->mutex_RUs))==0, "mutex_lock returns %d\n",ret); proc->instance_cnt_RUs = 0; - AssertFatal((pthread_mutex_unlock(&proc->mutex_RUs))==0, "mutex_unlock returns %d\n",ret); + AssertFatal((ret=pthread_mutex_unlock(&proc->mutex_RUs))==0, "mutex_unlock returns %d\n",ret); continue;//hacking only works when all RU_tx works on the same subframe #TODO: adding mask stuff } From b99c6a898d6cc638bd76fafa049a8010b3e01ff0 Mon Sep 17 00:00:00 2001 From: Raphael Defosseux Date: Fri, 5 Jul 2019 14:08:11 +0200 Subject: [PATCH 31/32] CI: little bug fixes Signed-off-by: Raphael Defosseux --- ci-scripts/main.py | 19 ++++++++++++++----- .../enb_usrp210_band7_test_05mhz_tm1.xml | 6 +++--- 2 files changed, 17 insertions(+), 8 deletions(-) diff --git a/ci-scripts/main.py b/ci-scripts/main.py index 3384a29b3e..23e8921a64 100644 --- a/ci-scripts/main.py +++ b/ci-scripts/main.py @@ -543,11 +543,11 @@ class SSHConnection(): sys.exit('Insufficient Parameter') ci_full_config_file = config_path + '/ci-' + config_file rruCheck = False - result = re.search('rru|du', str(config_file)) + result = re.search('rru|du.band', str(config_file)) if result is not None: rruCheck = True # do not reset board twice in IF4.5 case - result = re.search('rru|enb|du', str(config_file)) + result = re.search('rru|enb|du.band', str(config_file)) if result is not None: self.command('echo ' + self.eNBPassword + ' | sudo -S uhd_find_devices', '\$', 10) result = re.search('type: b200', str(self.ssh.before)) @@ -571,11 +571,12 @@ class SSHConnection(): self.command('chmod 775 ./my-lte-softmodem-run' + str(self.eNB_instance) + '.sh', '\$', 5) self.command('echo ' + self.eNBPassword + ' | sudo -S rm -Rf enb_' + self.testCase_id + '.log', '\$', 5) self.command('echo ' + self.eNBPassword + ' | sudo -S -E daemon --inherit --unsafe --name=enb' + str(self.eNB_instance) + '_daemon --chdir=' + self.eNBSourceCodePath + '/cmake_targets -o ' + self.eNBSourceCodePath + '/cmake_targets/enb_' + self.testCase_id + '.log ./my-lte-softmodem-run' + str(self.eNB_instance) + '.sh', '\$', 5) - if not rruCheck: + result = re.search('rcc|enb|cu.band', str(config_file)) + if result is not None: self.eNBLogFile = 'enb_' + self.testCase_id + '.log' if extra_options != '': self.eNBOptions = extra_options - result = re.search('rru|du', str(config_file)) + result = re.search('rru|du.band', str(config_file)) if result is not None: self.rruLogFile = 'enb_' + self.testCase_id + '.log' time.sleep(6) @@ -2527,6 +2528,7 @@ class SSHConnection(): pdcpFailure = 0 ulschFailure = 0 cdrxActivationMessageCount = 0 + dropNotEnoughRBs = 0 self.htmleNBFailureMsg = '' for line in enb_log_file.readlines(): if self.rruOptions != '': @@ -2599,6 +2601,9 @@ class SSHConnection(): result = re.search('Canceled RA procedure for UE rnti', str(line)) if result is not None: rachCanceledProcedure += 1 + result = re.search('dropping, not enough RBs', str(line)) + if result is not None: + dropNotEnoughRBs += 1 enb_log_file.close() logging.debug(' File analysis completed') if uciStatMsgCount > 0: @@ -2613,6 +2618,10 @@ class SSHConnection(): statMsg = 'eNB showed ' + str(ulschFailure) + ' "ULSCH in error in round" message(s)' logging.debug('\u001B[1;30;43m ' + statMsg + ' \u001B[0m') self.htmleNBFailureMsg += statMsg + '\n' + if dropNotEnoughRBs > 0: + statMsg = 'eNB showed ' + str(dropNotEnoughRBs) + ' "dropping, not enough RBs" message(s)' + logging.debug('\u001B[1;30;43m ' + statMsg + ' \u001B[0m') + self.htmleNBFailureMsg += statMsg + '\n' if rrcSetupComplete > 0: rrcMsg = 'eNB completed ' + str(rrcSetupComplete) + ' RRC Connection Setup(s)' logging.debug('\u001B[1;30;43m ' + rrcMsg + ' \u001B[0m') @@ -2896,7 +2905,7 @@ class SSHConnection(): self.htmleNBFailureMsg = 'Could not copy eNB logfile to analyze it!' self.CreateHtmlTestRow('N/A', 'KO', ENB_PROCESS_NOLOGFILE_TO_ANALYZE) return - logging.debug('\u001B[1m Analyzing eNB logfile \u001B[0m') + logging.debug('\u001B[1m Analyzing eNB logfile \u001B[0m ' + fileToAnalyze) logStatus = self.AnalyzeLogFile_eNB(fileToAnalyze) if (logStatus < 0): self.CreateHtmlTestRow('N/A', 'KO', logStatus) diff --git a/ci-scripts/xml_files/enb_usrp210_band7_test_05mhz_tm1.xml b/ci-scripts/xml_files/enb_usrp210_band7_test_05mhz_tm1.xml index afafd3fb65..3b07ed4950 100644 --- a/ci-scripts/xml_files/enb_usrp210_band7_test_05mhz_tm1.xml +++ b/ci-scripts/xml_files/enb_usrp210_band7_test_05mhz_tm1.xml @@ -30,7 +30,7 @@ 030101 040301 040501 040603 040604 040605 040606 040607 040641 040642 040643 040644 040401 040201 030201 030102 000010 040301 040502 000011 040302 000001 000012 040303 000002 000013 040503 040401 040201 030201 050102 - 030102 000020 040301 040504 000021 040302 000001 000022 040303 000002 040504 000023 040401 040201 030201 + 030103 000020 040301 040504 000021 040302 000001 000022 040303 000002 040504 000023 040401 040201 030201 050202 @@ -113,13 +113,13 @@ Initialize_eNB - Initialize eNB (FDD/Band7/5MHz) + Initialize eNB (FDD/Band7/5MHz) for RRC Inactivity Timer testing -- no FlexRan Ctl -O ci-scripts/conf_files/enb.band7.tm1.25PRB.usrpb210.conf Initialize_eNB - Initialize eNB (FDD/Band7/5MHz) + Initialize eNB (FDD/Band7/5MHz) for RRC Inactivity Timer testing -- with FlexRan Ctl -O ci-scripts/conf_files/enb.band7.tm1.25PRB.usrpb210.conf From 94875783dd7c8498ba8158a3007cca0f9280635f Mon Sep 17 00:00:00 2001 From: Raphael Defosseux Date: Fri, 5 Jul 2019 17:17:44 +0200 Subject: [PATCH 32/32] Fix a few compilation warnings Signed-off-by: Raphael Defosseux --- targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp b/targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp index 085a8fa33a..f9b4ae3d2b 100644 --- a/targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp +++ b/targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp @@ -539,7 +539,7 @@ static int trx_usrp_write(openair0_device *device, openair0_timestamp timestamp, */ static int trx_usrp_read(openair0_device *device, openair0_timestamp *ptimestamp, void **buff, int nsamps, int cc) { usrp_state_t *s = (usrp_state_t *)device->priv; - int samples_received=0,i,j; + int samples_received=0; int nsamps2; // aligned to upper 32 or 16 byte boundary #if defined(USRP_REC_PLAY) @@ -760,12 +760,9 @@ int trx_usrp_set_freq(openair0_device *device, openair0_config_t *openair0_cfg, */ int openair0_set_rx_frequencies(openair0_device *device, openair0_config_t *openair0_cfg) { usrp_state_t *s = (usrp_state_t *)device->priv; - static int first_call=1; - static double rf_freq,diff; uhd::tune_request_t rx_tune_req(openair0_cfg[0].rx_freq[0]); rx_tune_req.rf_freq_policy = uhd::tune_request_t::POLICY_MANUAL; rx_tune_req.rf_freq = openair0_cfg[0].rx_freq[0]; - rf_freq=openair0_cfg[0].rx_freq[0]; s->usrp->set_rx_freq(rx_tune_req); return(0); } @@ -1248,7 +1245,7 @@ extern "C" { openair0_cfg[0].iq_txshift = 4;//shift openair0_cfg[0].iq_rxrescale = 15;//rescale iqs - for(int i=0; iusrp->get_rx_num_channels(); i++) { + for(int i=0; i<((int) s->usrp->get_rx_num_channels()); i++) { if (iusrp->set_rx_rate(openair0_cfg[0].sample_rate,i); s->usrp->set_rx_freq(openair0_cfg[0].rx_freq[i],i); @@ -1268,7 +1265,7 @@ extern "C" { LOG_D(PHY, "usrp->get_tx_num_channels() == %zd\n", s->usrp->get_tx_num_channels()); LOG_D(PHY, "openair0_cfg[0].tx_num_channels == %d\n", openair0_cfg[0].tx_num_channels); - for(int i=0; iusrp->get_tx_num_channels(); i++) { + for(int i=0; i<((int) s->usrp->get_tx_num_channels()); i++) { ::uhd::gain_range_t gain_range_tx = s->usrp->get_tx_gain_range(i); if (itx_stream = s->usrp->get_tx_stream(stream_args_tx); /* Setting TX/RX BW after streamers are created due to USRP calibration issue */ - for(int i=0; iusrp->get_tx_num_channels() && iusrp->get_tx_num_channels()) && iusrp->set_tx_bandwidth(openair0_cfg[0].tx_bw,i); - for(int i=0; iusrp->get_rx_num_channels() && iusrp->get_rx_num_channels()) && iusrp->set_rx_bandwidth(openair0_cfg[0].rx_bw,i); for (int i=0; i